From fd169abf9bb666d3f27434ace9c6038174524c48 Mon Sep 17 00:00:00 2001 From: talyz Date: Fri, 13 Aug 2021 18:42:56 +0200 Subject: [PATCH] discourse.plugins: Make the updater able to package plugins Let the update.py script handle the initial, repetitive task of packaging new plugins. With this in place, the plugin only needs to be added to the list in `update-plugins` and most of the work will be done automatically when the script is run. Metadata still needs to be filled in manually and some packages may of course require additional work/patching. (cherry picked from commit f8096460bd15d4f13a01cfddf0a30798921fdb42) --- nixos/modules/services/web-apps/discourse.xml | 13 ++++- pkgs/servers/web-apps/discourse/update.py | 55 ++++++++++++++++++- 2 files changed, 65 insertions(+), 3 deletions(-) diff --git a/nixos/modules/services/web-apps/discourse.xml b/nixos/modules/services/web-apps/discourse.xml index 1d6866e7b35..184c9c6363e 100644 --- a/nixos/modules/services/web-apps/discourse.xml +++ b/nixos/modules/services/web-apps/discourse.xml @@ -284,11 +284,22 @@ services.discourse = { Ruby dependencies are listed in its plugin.rb file as function calls to gem. To construct the corresponding - Gemfile, run bundle + Gemfile manually, run bundle init, then add the gem lines to it verbatim. + + Much of the packaging can be done automatically by the + nixpkgs/pkgs/servers/web-apps/discourse/update.py + script - just add the plugin to the plugins + list in the update_plugins function and run + the script: + +./update.py update-plugins +. + + Some plugins provide site diff --git a/pkgs/servers/web-apps/discourse/update.py b/pkgs/servers/web-apps/discourse/update.py index 4832e8638ea..c77cb06e120 100755 --- a/pkgs/servers/web-apps/discourse/update.py +++ b/pkgs/servers/web-apps/discourse/update.py @@ -12,6 +12,7 @@ import os import stat import json import requests +import textwrap from distutils.version import LooseVersion from pathlib import Path from typing import Iterable @@ -77,7 +78,11 @@ def _call_nix_update(pkg, version): 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)) + try: + output = subprocess.check_output(['nix', 'eval', '--json', f'(with import {nixpkgs_path} {{}}; {expr})'], text=True) + except subprocess.CalledProcessError: + return None + return json.loads(output) def _get_current_package_version(pkg: str): @@ -206,13 +211,59 @@ def update_plugins(): repo_name = plugin.get('repo_name') or name repo = DiscourseRepo(owner=owner, repo=repo_name) + + filename = _nix_eval(f'builtins.unsafeGetAttrPos "src" discourse.plugins.{name}') + if filename is None: + filename = Path(__file__).parent / 'plugins' / name / 'default.nix' + filename.parent.mkdir() + + has_ruby_deps = False + for line in repo.get_file('plugin.rb', repo.latest_commit_sha).splitlines(): + if 'gem ' in line: + has_ruby_deps = True + break + + with open(filename, 'w') as f: + f.write(textwrap.dedent(f""" + {{ lib, mkDiscoursePlugin, fetchFromGitHub }}: + + mkDiscoursePlugin {{ + name = "{name}";"""[1:] + (""" + bundlerEnvArgs.gemdir = ./.;""" if has_ruby_deps else "") + f""" + src = {fetcher} {{ + owner = "{owner}"; + repo = "{repo_name}"; + rev = "replace-with-git-rev"; + sha256 = "replace-with-sha256"; + }}; + meta = with lib; {{ + homepage = ""; + maintainers = with maintainers; [ ]; + license = licenses.mit; # change to the correct license! + description = ""; + }}; + }}""")) + + all_plugins_filename = Path(__file__).parent / 'plugins' / 'all-plugins.nix' + with open(all_plugins_filename, 'r+') as f: + content = f.read() + pos = -1 + while content[pos] != '}': + pos -= 1 + content = content[:pos] + f' {name} = callPackage ./{name} {{}};' + os.linesep + content[pos:] + f.seek(0) + f.write(content) + f.truncate() + + else: + filename = filename['file'] + 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,