summary refs log tree commit diff
diff options
context:
space:
mode:
authortalyz <kim.lindberger@gmail.com>2021-08-13 18:42:56 +0200
committertalyz <kim.lindberger@gmail.com>2021-08-17 18:21:15 +0200
commitf8096460bd15d4f13a01cfddf0a30798921fdb42 (patch)
tree56d40267559bab6abffc45a6b2a295d0292093d3
parent4197b6dd146c395f1caec3b086334a2b0eff623a (diff)
downloadnixpkgs-f8096460bd15d4f13a01cfddf0a30798921fdb42.tar
nixpkgs-f8096460bd15d4f13a01cfddf0a30798921fdb42.tar.gz
nixpkgs-f8096460bd15d4f13a01cfddf0a30798921fdb42.tar.bz2
nixpkgs-f8096460bd15d4f13a01cfddf0a30798921fdb42.tar.lz
nixpkgs-f8096460bd15d4f13a01cfddf0a30798921fdb42.tar.xz
nixpkgs-f8096460bd15d4f13a01cfddf0a30798921fdb42.tar.zst
nixpkgs-f8096460bd15d4f13a01cfddf0a30798921fdb42.zip
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.
-rw-r--r--nixos/modules/services/web-apps/discourse.xml13
-rwxr-xr-xpkgs/servers/web-apps/discourse/update.py55
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,12 +284,23 @@ services.discourse = {
       Ruby dependencies are listed in its
       <filename>plugin.rb</filename> file as function calls to
       <literal>gem</literal>. To construct the corresponding
-      <filename>Gemfile</filename>, run <command>bundle
+      <filename>Gemfile</filename> manually, run <command>bundle
       init</command>, then add the <literal>gem</literal> lines to it
       verbatim.
     </para>
 
     <para>
+      Much of the packaging can be done automatically by the
+      <filename>nixpkgs/pkgs/servers/web-apps/discourse/update.py</filename>
+      script - just add the plugin to the <literal>plugins</literal>
+      list in the <function>update_plugins</function> function and run
+      the script:
+      <programlisting language="bash">
+./update.py update-plugins
+</programlisting>.
+    </para>
+
+    <para>
       Some plugins provide <link
       linkend="module-services-discourse-site-settings">site
       settings</link>. Their defaults can be configured using <xref
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,