From 3300282db3f8711a5ed5a5f627c4ddfb83168e3b Mon Sep 17 00:00:00 2001 From: talyz Date: Tue, 6 Jul 2021 18:28:04 +0200 Subject: [PATCH] discourse: Add `update-plugins` action to update.py --- pkgs/servers/web-apps/discourse/default.nix | 1 - pkgs/servers/web-apps/discourse/update.py | 100 ++++++++++++++++++-- 2 files changed, 92 insertions(+), 9 deletions(-) diff --git a/pkgs/servers/web-apps/discourse/default.nix b/pkgs/servers/web-apps/discourse/default.nix index 5a3301040d3..ae5d1818c61 100644 --- a/pkgs/servers/web-apps/discourse/default.nix +++ b/pkgs/servers/web-apps/discourse/default.nix @@ -64,7 +64,6 @@ let }); in stdenv.mkDerivation (builtins.removeAttrs args [ "bundlerEnvArgs" ] // { - inherit name pname version src meta; pluginName = if name != null then name else "${pname}-${version}"; phases = [ "unpackPhase" "installPhase" ]; installPhase = '' diff --git a/pkgs/servers/web-apps/discourse/update.py b/pkgs/servers/web-apps/discourse/update.py index c401ab552bb..d10a49be58f 100755 --- a/pkgs/servers/web-apps/discourse/update.py +++ b/pkgs/servers/web-apps/discourse/update.py @@ -1,5 +1,5 @@ #!/usr/bin/env nix-shell -#! nix-shell -i python3 -p bundix bundler nix-update python3 python3Packages.requests python3Packages.click python3Packages.click-log +#! nix-shell -i python3 -p bundix bundler nix-update nix-universal-prefetch python3 python3Packages.requests python3Packages.click python3Packages.click-log import click import click_log @@ -8,17 +8,22 @@ import tempfile import re import logging import subprocess -import pathlib +import os +import stat +import json +import requests from distutils.version import LooseVersion +from pathlib import Path from typing import Iterable -import requests logger = logging.getLogger(__name__) class DiscourseRepo: version_regex = re.compile(r'^v\d+\.\d+\.\d+$') + _latest_commit_sha = None + def __init__(self, owner: str = 'discourse', repo: str = 'discourse'): self.owner = owner self.repo = repo @@ -35,6 +40,15 @@ class DiscourseRepo: versions.sort(key=lambda x: LooseVersion(x.replace('v', '')), reverse=True) return versions + @property + def latest_commit_sha(self) -> str: + if self._latest_commit_sha is None: + r = requests.get(f'https://api.github.com/repos/{self.owner}/{self.repo}/commits?per_page=1') + r.raise_for_status() + self._latest_commit_sha = r.json()[0]['sha'] + + return self._latest_commit_sha + @staticmethod def rev2version(tag: str) -> str: """ @@ -57,19 +71,23 @@ class DiscourseRepo: def _call_nix_update(pkg, version): """calls nix-update from nixpkgs root dir""" - nixpkgs_path = pathlib.Path(__file__).parent / '../../../../' + nixpkgs_path = Path(__file__).parent / '../../../../' return subprocess.check_output(['nix-update', pkg, '--version', version], cwd=nixpkgs_path) +def _nix_eval(expr: str): + nixpkgs_path = Path(__file__).parent / '../../../../' + return json.loads(subprocess.check_output(['nix', 'eval', '--json', f'(with import {nixpkgs_path} {{}}; {expr})'], text=True)) + + def _get_current_package_version(pkg: str): - nixpkgs_path = pathlib.Path(__file__).parent / '../../../../' - return subprocess.check_output(['nix', 'eval', '--raw', f'nixpkgs.{pkg}.version'], text=True) + return _nix_eval(f'{pkg}.version') def _diff_file(filepath: str, old_version: str, new_version: str): repo = DiscourseRepo() - current_dir = pathlib.Path(__file__).parent + current_dir = Path(__file__).parent old = repo.get_file(filepath, 'v' + old_version) new = repo.get_file(filepath, 'v' + new_version) @@ -148,7 +166,7 @@ def update(rev): version = repo.rev2version(rev) logger.debug(f"Using version {version}") - rubyenv_dir = pathlib.Path(__file__).parent / "rubyEnv" + rubyenv_dir = Path(__file__).parent / "rubyEnv" for fn in ['Gemfile.lock', 'Gemfile']: with open(rubyenv_dir / fn, 'w') as f: @@ -159,6 +177,72 @@ def update(rev): _call_nix_update('discourse', repo.rev2version(rev)) +@cli.command() +def update_plugins(): + """Update plugins to their latest revision. + + """ + plugins = [ + {'name': 'discourse-canned-replies'}, + {'name': 'discourse-github'}, + {'name': 'discourse-math'}, + {'name': 'discourse-solved'}, + {'name': 'discourse-spoiler-alert'}, + {'name': 'discourse-yearly-review'}, + ] + + for plugin in plugins: + fetcher = plugin.get('fetcher') or "fetchFromGitHub" + owner = plugin.get('owner') or "discourse" + name = plugin.get('name') + repo_name = plugin.get('repo_name') or name + + repo = DiscourseRepo(owner=owner, repo=repo_name) + prev_commit_sha = _nix_eval(f'discourse.plugins.{name}.src.rev') + + if prev_commit_sha == repo.latest_commit_sha: + click.echo(f'Plugin {name} is already at the latest revision') + continue + + filename = _nix_eval(f'builtins.unsafeGetAttrPos "src" discourse.plugins.{name}')['file'] + prev_hash = _nix_eval(f'discourse.plugins.{name}.src.outputHash') + new_hash = subprocess.check_output([ + 'nix-universal-prefetch', fetcher, + '--owner', owner, + '--repo', repo_name, + '--rev', repo.latest_commit_sha, + ], text=True).strip("\n") + + click.echo(f"Update {name}, {prev_commit_sha} -> {repo.latest_commit_sha} in {filename}") + + with open(filename, 'r+') as f: + content = f.read() + content = content.replace(prev_commit_sha, repo.latest_commit_sha) + content = content.replace(prev_hash, new_hash) + f.seek(0) + f.write(content) + f.truncate() + + rubyenv_dir = Path(filename).parent + gemfile = rubyenv_dir / "Gemfile" + gemfile_text = '' + for line in repo.get_file('plugin.rb', repo.latest_commit_sha).splitlines(): + if 'gem ' in line: + gemfile_text = gemfile_text + line + os.linesep + + if len(gemfile_text) > 0: + if os.path.isfile(gemfile): + os.remove(gemfile) + + subprocess.check_output(['bundle', 'init'], cwd=rubyenv_dir) + os.chmod(gemfile, stat.S_IREAD | stat.S_IWRITE | stat.S_IRGRP | stat.S_IROTH) + + with open(gemfile, 'a') as f: + f.write(gemfile_text) + + subprocess.check_output(['bundle', 'lock', '--update'], cwd=rubyenv_dir) + subprocess.check_output(['bundix'], cwd=rubyenv_dir) + if __name__ == '__main__': cli()