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,