summary refs log tree commit diff
diff options
context:
space:
mode:
authorV <v@unfathomable.blue>2022-06-06 15:09:37 +0200
committerV <v@unfathomable.blue>2022-06-20 09:40:50 +0200
commitea030636aa3c14b9c997ad2ad76f01fbb9d4d212 (patch)
treeaad9bf02d5c3a53c50ac9f04bbc92d2e032bca88
parent82faf4bb2e000a84bbe80ccd27bbc03c778cc7ee (diff)
fleet: it's monorepo time!
Change-Id: I4670dd7930a9b6227993c1caf92c5877918f982d
-rw-r--r--fleet/configuration.nix6
-rw-r--r--fleet/hosts/trieste/cgit/default.nix47
-rw-r--r--fleet/hosts/trieste/cgit/monorepo-support.patch153
-rw-r--r--fleet/hosts/trieste/cgit/ripple.svg8
-rw-r--r--fleet/hosts/trieste/git.nix17
-rw-r--r--fleet/hosts/vityaz/git.nix17
-rwxr-xr-xfleet/test3
7 files changed, 185 insertions, 66 deletions
diff --git a/fleet/configuration.nix b/fleet/configuration.nix
index 736e0d5..5271895 100644
--- a/fleet/configuration.nix
+++ b/fleet/configuration.nix
@@ -15,6 +15,12 @@ in {
     (./hosts + "/${host}")
   ] ++ mapAttrsToList (module: _: ./modules + "/${module}") (builtins.readDir ./modules);
 
+  nix.nixPath = [
+    "nixpkgs=/nix/var/nix/profiles/per-user/root/channels/nixos"
+    "nixos-config=/etc/nixos/fleet/configuration.nix"
+    "/nix/var/nix/profiles/per-user/root/channels"
+  ];
+
   nixpkgs.overlays = [ (import ./pkgs/overlay.nix) ];
 
   system.stateVersion = "20.09";
diff --git a/fleet/hosts/trieste/cgit/default.nix b/fleet/hosts/trieste/cgit/default.nix
index 34268e6..e80b275 100644
--- a/fleet/hosts/trieste/cgit/default.nix
+++ b/fleet/hosts/trieste/cgit/default.nix
@@ -7,7 +7,11 @@
 with lib;
 
 let
-  cgit-package = pkgs.cgit-pink;
+  cgit-package = pkgs.cgit-pink.overrideAttrs ({ patches ? [], ... }: {
+    patches = patches ++ [
+      ./monorepo-support.patch
+    ];
+  });
 
   cgit-webroot = pkgs.runCommand "cgit-webroot" {
     extraStyles = ''
@@ -26,7 +30,6 @@ let
     ${pkgs.minify}/bin/minify --type css --bundle ${cgit-package}/cgit/cgit.css $extraStylesPath -o $out/cgit.css
     cp ${./un.svg} $out/un.svg  # TODO(V): remove this variant, apply padding to the Sigil using CSS
     cp ${./unicon.svg} $out/unicon.svg  # This is the same as un.svg, but without any padding
-    cp ${./ripple.svg} $out/ripple.svg  # This is referenced in git.nix (as config.cgit.logo, for Ripple)
     cp ${cgit-package}/cgit/robots.txt $out
   '';
 
@@ -41,31 +44,23 @@ let
     # TODO(V): sort these sanely
     root-title=unfathomable software
     root-desc=sufficiently advanced technology
-    # TODO(V): root-readme? what should go in here, contribution info? info about the server? info about the branch conventions?
-    enable-index-owner=0
 
     logo=/un.svg
     favicon=/unicon.svg
-    # TODO(V): footer=https://src.unfathomable.blue/nixos-config/commit/?id={commit}
+    # TODO(V): footer=https://src.unfathomable.blue/commit/?id={commit}
     mimetype-file=${pkgs.mime-types}/etc/mime.types
-    # TODO(V): repository-sort=age?
-    # TODO(V): robots=none? (same as noindex, nofollow)
     readme=:README.adoc
-    clone-prefix=https://src.unfathomable.blue
-    agefile=info/last-modified
     about-filter=${cgit-about-filter}
     # TODO(edef): commit-filter, for bug tracker links
     source-filter=${cgit-package}/lib/cgit/filters/syntax-highlighting.py
     # TODO(edef): add snapshots once we start releasing things
     # TODO(V): branch-sort=age?
-    enable-git-config=1
 
-    # Has to go last.
-    # Options set after this won't be applied due to how they're evaluated.
-    scan-path=/var/lib/git
-    # TODO(V): section-from-path?
-    # TODO(V): repository-specific logos
-    # TODO(V): other repository-specific options
+    repo.url=basin
+    repo.path=/var/lib/git/basin
+    repo.clone-url=https://src.unfathomable.blue/
+
+    # TODO(V): add per-subtree project description/logo/etc support to cgit
   '';
 in {
   services.cgiserver.instances.cgit = {
@@ -81,11 +76,17 @@ in {
     src.unfathomable.blue {
       import common
 
-      root * ${cgit-webroot}
-      @exists file
-
       route {
+        root * ${cgit-webroot}
+        @exists file
         file_server @exists
+
+        # CGit doesn't currently have a straightforward way of serving
+        # a repository at the root, so we cheat by internally rewriting
+        # all URLs to be relative to a named repository, and patching
+        # CGit to elide this prefix from generated links.
+        rewrite * /basin{path}
+
         reverse_proxy unix//run/cgit/cgit.sock
       }
     }
@@ -97,13 +98,5 @@ in {
     (pkgs.writeShellScript "update-server-info" ''
       git update-server-info
     '')
-
-    # Update the last-modified timestamp that cgit uses to measure freshness
-    (pkgs.writeShellScript "update-agefile" ''
-      git for-each-ref \
-        --sort=-creatordate --count=1 \
-        --format='%(creatordate:iso)' \
-        >info/last-modified
-    '')
   ];
 }
diff --git a/fleet/hosts/trieste/cgit/monorepo-support.patch b/fleet/hosts/trieste/cgit/monorepo-support.patch
new file mode 100644
index 0000000..f634d9c
--- /dev/null
+++ b/fleet/hosts/trieste/cgit/monorepo-support.patch
@@ -0,0 +1,153 @@
+SPDX-FileCopyrightText: V <v@unfathomable.blue>
+SPDX-License-Identifier: OSL-3.0
+diff --git a/cgit.c b/cgit.c
+index dd28a79..1426a72 100644
+--- a/cgit.c
++++ b/cgit.c
+@@ -603,7 +603,7 @@ static int prepare_repo_cmd(int nongit)
+ 		cgit_print_docend();
+ 		return 1;
+ 	}
+-	ctx.page.title = fmtalloc("%s - %s", ctx.repo->name, ctx.repo->desc);
++	ctx.page.title = ctx.cfg.root_title;
+ 
+ 	if (!ctx.repo->defbranch)
+ 		ctx.repo->defbranch = guess_defbranch();
+diff --git a/ui-shared.c b/ui-shared.c
+index 72a1505..d798d99 100644
+--- a/ui-shared.c
++++ b/ui-shared.c
+@@ -129,29 +129,17 @@ const char *cgit_loginurl(void)
+ 
+ char *cgit_repourl(const char *reponame)
+ {
+-	if (ctx.cfg.virtual_root)
+-		return fmtalloc("%s%s/", ctx.cfg.virtual_root, reponame);
+-	else
+-		return fmtalloc("?r=%s", reponame);
++	return fmtalloc("%s/", ctx.cfg.virtual_root);
+ }
+ 
+ char *cgit_fileurl(const char *reponame, const char *pagename,
+ 		   const char *filename, const char *query)
+ {
+ 	struct strbuf sb = STRBUF_INIT;
+-	char *delim;
+-
+-	if (ctx.cfg.virtual_root) {
+-		strbuf_addf(&sb, "%s%s/%s/%s", ctx.cfg.virtual_root, reponame,
+-			    pagename, (filename ? filename:""));
+-		delim = "?";
+-	} else {
+-		strbuf_addf(&sb, "?url=%s/%s/%s", reponame, pagename,
+-			    (filename ? filename : ""));
+-		delim = "&amp;";
+-	}
++	strbuf_addf(&sb, "%s/%s/%s", ctx.cfg.virtual_root,
++		    pagename, (filename ? filename:""));
+ 	if (query)
+-		strbuf_addf(&sb, "%s%s", delim, query);
++		strbuf_addf(&sb, "?%s", query);
+ 	return strbuf_detach(&sb, NULL);
+ }
+ 
+@@ -277,30 +265,12 @@ static char *repolink(const char *title, const char *class, const char *page,
+ 		html("'");
+ 	}
+ 	html(" href='");
+-	if (ctx.cfg.virtual_root) {
+-		html_url_path(ctx.cfg.virtual_root);
+-		html_url_path(ctx.repo->url);
+-		if (ctx.repo->url[strlen(ctx.repo->url) - 1] != '/')
+-			html("/");
+-		if (page) {
+-			html_url_path(page);
+-			html("/");
+-			if (path)
+-				html_url_path(path);
+-		}
+-	} else {
+-		html_url_path(ctx.cfg.script_name);
+-		html("?url=");
+-		html_url_arg(ctx.repo->url);
+-		if (ctx.repo->url[strlen(ctx.repo->url) - 1] != '/')
+-			html("/");
+-		if (page) {
+-			html_url_arg(page);
+-			html("/");
+-			if (path)
+-				html_url_arg(path);
+-		}
+-		delim = "&amp;";
++	html_url_path(ctx.cfg.virtual_root);
++	if (page) {
++		html_url_path(page);
++		html("/");
++		if (path)
++			html_url_path(path);
+ 	}
+ 	if (head && ctx.repo->defbranch && strcmp(head, ctx.repo->defbranch)) {
+ 		html(delim);
+@@ -1001,44 +971,27 @@ static void print_header(void)
+ 	}
+ 
+ 	html("<td class='main'>");
+-	if (ctx.repo) {
+-		cgit_index_link("index", NULL, NULL, NULL, NULL, 0, 1);
+-		html(" : ");
+-		cgit_summary_link(ctx.repo->name, NULL, NULL, NULL);
+-		if (ctx.env.authenticated) {
+-			html("</td><td class='form'>");
+-			html("<form method='get'>\n");
+-			cgit_add_hidden_formfields(0, 1, ctx.qry.page);
+-			html("<select name='h' onchange='this.form.submit();'>\n");
+-			print_this_commit_option();
+-			html("<optgroup label='branches'>");
+-			for_each_branch_ref(print_branch_option, ctx.qry.head);
+-			if (ctx.repo->enable_remote_branches)
+-				for_each_remote_ref(print_branch_option, ctx.qry.head);
+-			html("</optgroup>");
+-			html("</select> ");
+-			html("<input type='submit' value='switch'/>");
+-			html("</form>");
+-		}
+-	} else
+-		html_txt(ctx.cfg.root_title);
++	cgit_index_link(ctx.cfg.root_title, NULL, NULL, NULL, NULL, 0, 1);
++	if (ctx.env.authenticated) {
++		html("</td><td class='form'>");
++		html("<form method='get'>\n");
++		cgit_add_hidden_formfields(0, 1, ctx.qry.page);
++		html("<select name='h' onchange='this.form.submit();'>\n");
++		print_this_commit_option();
++		html("<optgroup label='branches'>");
++		for_each_branch_ref(print_branch_option, ctx.qry.head);
++		if (ctx.repo->enable_remote_branches)
++			for_each_remote_ref(print_branch_option, ctx.qry.head);
++		html("</optgroup>");
++		html("</select> ");
++		html("<input type='submit' value='switch'/>");
++		html("</form>");
++	}
+ 	html("</td></tr>\n");
+ 
+ 	html("<tr><td class='sub'>");
+-	if (ctx.repo) {
+-		html_txt(ctx.repo->desc);
+-		html("</td><td class='sub right'>");
+-		if (ctx.repo->owner_filter) {
+-			cgit_open_filter(ctx.repo->owner_filter);
+-			html_txt(ctx.repo->owner);
+-			cgit_close_filter(ctx.repo->owner_filter);
+-		} else {
+-			html_txt(ctx.repo->owner);
+-		}
+-	} else {
+-		if (ctx.cfg.root_desc)
+-			html_txt(ctx.cfg.root_desc);
+-	}
++	if (ctx.cfg.root_desc)
++		html_txt(ctx.cfg.root_desc);
+ 	html("</td></tr></table>\n");
+ }
+ 
diff --git a/fleet/hosts/trieste/cgit/ripple.svg b/fleet/hosts/trieste/cgit/ripple.svg
deleted file mode 100644
index 243059f..0000000
--- a/fleet/hosts/trieste/cgit/ripple.svg
+++ /dev/null
@@ -1,8 +0,0 @@
-<!-- SPDX-FileCopyrightText: V <v@unfathomable.blue> -->
-<!-- SPDX-License-Identifier: LicenseRef-NONE -->
-
-<svg xmlns="http://www.w3.org/2000/svg" width="64" height="64">
-  <circle cx="32" cy="32" r="8"/>
-  <path d="M17.28 38.2l3.5-2.03A12 12 0 0120 32a12 12 0 0110-11.82v-4.04A16 16 0 0016 32a16 16 0 001.28 6.2zM44.71 41.65l-3.5-2.02A12 12 0 0132 44a12 12 0 01-9.21-4.37l-3.5 2.02A16 16 0 0032 48a16 16 0 0012.71-6.35zM34 16.13v4.04A12 12 0 0144 32a12 12 0 01-.78 4.17l3.5 2.02A16 16 0 0048 32a16 16 0 00-14-15.87z" color="#000"/>
-  <path d="M10.3 42.22l3.51-2.03A20 20 0 0112 32a20 20 0 0118-19.84V8.14A24 24 0 008 32a24 24 0 002.3 10.22zM51.67 45.67l-3.44-1.99A20 20 0 0132 52a20 20 0 01-16.23-8.32l-3.44 1.99A24 24 0 0032 56a24 24 0 0019.67-10.33zM34 8.09v4.01A20 20 0 0152 32a20 20 0 01-1.81 8.2l3.5 2.02A24 24 0 0056 32 24 24 0 0034 8.09z" color="#000"/>
-</svg>
diff --git a/fleet/hosts/trieste/git.nix b/fleet/hosts/trieste/git.nix
index f4d4e0b..bba3f9f 100644
--- a/fleet/hosts/trieste/git.nix
+++ b/fleet/hosts/trieste/git.nix
@@ -28,20 +28,5 @@ in {
     "d ${root} 0750 git git"
   ];
 
-  declarative.git.repositories = {
-    ripple = {
-      description = "A build system for the next decade";
-      config.cgit = {
-        # This is added to the webroot in cgit.nix. It would be nice if we could do that modularly.
-        # Another option is to simply hotlink https://ripple.unfathomable.blue/icon.svg
-        # Yet another option is to keep the SVG in Git, and link to the raw file from trunk.
-        logo = "/ripple.svg";
-
-        homepage = "https://ripple.unfathomable.blue/";
-      };
-    };
-
-    ripple-website.description = "Source code for https://ripple.unfathomable.blue/";
-    nixos-config.description = "NixOS configuration for Unfathomable infrastructure";
-  };
+  declarative.git.repositories.basin = {};
 }
diff --git a/fleet/hosts/vityaz/git.nix b/fleet/hosts/vityaz/git.nix
index 7ef9f9d..19e46bc 100644
--- a/fleet/hosts/vityaz/git.nix
+++ b/fleet/hosts/vityaz/git.nix
@@ -32,29 +32,18 @@ with lib;
   users.groups.git = {};
 
   # TODO(V): Enable the reflog?
-  declarative.git.repositories = flip genAttrs (repo: {
+  declarative.git.repositories.basin = {
     hooks.post-receive = [
       # FIXME(V): There are more than a number of issues with this!
-      # - non-generic (we could use $GIT_DIR or such)
       # - requires an explicit remote (we could add this to the config)
       # - only updates trunk (even if other branches were pushed)
       # - has no way to filter specific branches from being published
       # - does not synchronize tags
       (pkgs.writeShellScript "sync-repository" ''
-        git push trieste:${repo} trunk
+        git push trieste:basin trunk
       '')
     ];
-  }) [
-    # TODO(V): Take the list of public repositories from hosts/trieste/git.nix
-    # (or do the inverse)
-    # (or put this information in a shared location)
-    "ripple"
-    "ripple-website"
-    "nixos-config"
-
-    # Note: private repositories are currently not configured here.
-    # If we find it acceptable to leak their names, they could take advantage of this module as well.
-  ];
+  };
 
   # TODO(V): Linting hooks (honestly, these should just go in CI)
   # - reuse lint
diff --git a/fleet/test b/fleet/test
index 9246526..5b804c0 100755
--- a/fleet/test
+++ b/fleet/test
@@ -1,6 +1,7 @@
-#! /bin/sh
+#! /usr/bin/env bash
 # SPDX-FileCopyrightText: V <v@unfathomable.blue>
 # SPDX-License-Identifier: OSL-3.0
+set -euo pipefail
 
 git add . && git commit -m WIP
 git push -f kaikou trunk && ssh kaikou-root nixos-rebuild test --show-trace