diff --git a/hosts/gerrit01/default.nix b/hosts/gerrit01/default.nix index 49e93ae..de3a056 100755 --- a/hosts/gerrit01/default.nix +++ b/hosts/gerrit01/default.nix @@ -39,6 +39,61 @@ data = "/gerrit-data"; }; + age.secrets.ows-deploy-key = { + file = ../../secrets/ows-deploy-key.age; + mode = "0600"; + owner = "git"; + group = "git"; + }; + bagel.nixpkgs.one-way-sync = + let + mkNixpkgsJob = { timer, branchName }: { + name = "nixpkgs-${branchName}"; + fromUri = "https://github.com/NixOS/nixpkgs"; + fromRefspec = branchName; + localRefspec = "refs/remotes/origin/${branchName}"; + inherit timer; + }; + in + { + enable = true; + + pushUrl = "ssh://ows_bot@cl.forkos.org:29418/nixpkgs"; + deployKeyPath = config.age.secrets.ows-deploy-key.path; + + branches."refs/heads/master" = mkNixpkgsJob { + timer = "hourly"; + branchName = "master"; + }; + + branches."refs/heads/release-24.05" = mkNixpkgsJob { + timer = "hourly"; + branchName = "release-24.05"; + }; + + branches."refs/heads/release-23.11" = mkNixpkgsJob { + timer = "hourly"; + branchName = "release-23.11"; + }; + + # Testing jobs for personal sandbox branches + branches."refs/heads/sandbox/raito/raito-unstable-small" = { + name = "raito-unstable-sync"; + fromUri = "https://github.com/NixOS/nixpkgs"; + fromRefspec = "nixos-unstable-small"; + localRefspec = "refs/remotes/origin/sandbox/raito/raito-unstable-small"; + timer = "*-*-* 12:00:00"; + }; + + branches."refs/heads/sandbox/raito/raito-nixos-24.05" = { + name = "raito-release-sync"; + fromUri = "https://github.com/NixOS/nixpkgs"; + fromRefspec = "nixos-24.05"; + localRefspec = "refs/remotes/origin/sandbox/raito/raito-nixos-24.05"; + timer = "daily"; + }; + }; + i18n.defaultLocale = "fr_FR.UTF-8"; system.stateVersion = "24.05"; diff --git a/secrets.nix b/secrets.nix index badeab9..8e83190 100644 --- a/secrets.nix +++ b/secrets.nix @@ -26,6 +26,8 @@ let # These are the same password, but nginx wants it in htpasswd format metrics-push-htpasswd = [ machines.meta01 ]; metrics-push-password = builtins.attrValues machines; + + ows-deploy-key = [ machines.gerrit01 ]; }; in builtins.listToAttrs ( diff --git a/secrets/ows-deploy-key.age b/secrets/ows-deploy-key.age new file mode 100644 index 0000000..d2791d7 Binary files /dev/null and b/secrets/ows-deploy-key.age differ diff --git a/services/gerrit/default.nix b/services/gerrit/default.nix index 61e7ca8..7b2c72b 100644 --- a/services/gerrit/default.nix +++ b/services/gerrit/default.nix @@ -36,6 +36,7 @@ in imports = [ ./www.nix + ./one-way-sync.nix ]; config = mkIf cfg.enable { diff --git a/services/gerrit/one-way-sync.nix b/services/gerrit/one-way-sync.nix new file mode 100644 index 0000000..dfd0a4a --- /dev/null +++ b/services/gerrit/one-way-sync.nix @@ -0,0 +1,121 @@ +{ lib, config, pkgs, ... }: +let + cfg = config.bagel.nixpkgs.one-way-sync; + inherit (lib) mkIf mkOption mkEnableOption types mapAttrs'; + + mkSyncTimer = { name, timer, ... }: { + wantedBy = [ "timers.target" ]; + + timerConfig = { + OnCalendar = timer; + Persistent = true; + Unit = "ows-${name}.service"; + }; + }; + mkSyncService = targetRef: { name, fromUri, fromRefspec, localRefspec, ... }: { + path = [ pkgs.gitFull pkgs.openssh ]; + script = '' + set -x + trap "git worktree prune && git worktree remove -f ${name}" EXIT + + if [ ! -d "/var/lib/onewaysync/nixpkgs" ]; then + echo "First run, synchronizing nixpkgs..." + git clone https://cl.forkos.org/nixpkgs /var/lib/onewaysync/nixpkgs + fi + + cd /var/lib/onewaysync/nixpkgs + echo "Syncing ${fromUri}:${fromRefspec} to /var/lib/onewaysync/nixpkgs:${targetRef}" + echo "Current ref: $EXPECTED_REF" + git worktree add -f ${cfg.workingDir}/${name} ${localRefspec} + cd ${cfg.workingDir}/${name} + git pull origin ${fromRefspec} + EXPECTED_REF=$(git rev-list ${localRefspec} | head -1) + git fetch ${fromUri} ${fromRefspec} + git rebase FETCH_HEAD + GIT_SSH_COMMAND='ssh -i ${cfg.deployKeyPath}' git push ${cfg.pushUrl} HEAD:${targetRef} --force-with-lease=${targetRef}:$EXPECTED_REF --force-if-includes + ''; + serviceConfig = { + User = "git"; + Group = "git"; + Type = "oneshot"; + RuntimeDirectory = "onewaysync"; + WorkingDirectory = cfg.workingDir; + StateDirectory = "onewaysync"; + }; + }; +in +{ + options.bagel.nixpkgs.one-way-sync = { + enable = mkEnableOption "the one-way sync from GitHub repositories"; + + referenceDir = mkOption { + type = types.str; + default = "/var/lib/gerrit/git/nixpkgs.git"; + description = "Local repository reference"; + }; + + workingDir = mkOption { + type = types.str; + default = "/run/onewaysync/"; + description = "Working directory for the service"; + }; + + pushUrl = mkOption { + type = types.str; + example = "ssh://..."; + description = "Push URL for the target repository"; + }; + + deployKeyPath = mkOption { + type = types.path; + example = "/run/agenix.d/ows-priv-key"; + description = "Deployment private SSH key to push to the repository"; + }; + + branches = mkOption { + type = types.attrsOf (types.submodule ({ ... }: + { + options = { + name = mkOption { + type = types.str; + description = "User-friendly name"; + }; + + fromUri = mkOption { + type = types.str; + description = "Git URI from which we need to sync"; + }; + + fromRefspec = mkOption { + type = types.str; + description = "refspec for the fetch"; + }; + + localRefspec = mkOption { + type = types.str; + default = "local refspec in the local repository to get the expected reference and avoid stale info"; + }; + + timer = mkOption { + type = types.str; + description = "Calendar format everytime we need to run the sync"; + }; + }; + })); + + description = "Set of branches mapping from cl.forkos.org to other Git repositories"; + }; + }; + + config = mkIf cfg.enable { + systemd.timers = mapAttrs' (name: value: { + name = "ows-${value.name}"; + value = mkSyncTimer value; + }) cfg.branches; + + systemd.services = mapAttrs' (name: value: { + name = "ows-${value.name}"; + value = mkSyncService name value; + }) cfg.branches; + }; +}