infra/services/gerrit/one-way-sync.nix
raito 112f60afd1 feat(ows): support moving away onewaysync
We are running into too many out of disk space situations with OWS on
the main disk.

This way, we can reuse the Gerrit disk for all that data, which
hopefully, is quite shared with Gerrit.

Signed-off-by: Raito Bezarius <masterancpp@gmail.com>
2024-12-14 14:42:22 +00:00

143 lines
4.4 KiB
Nix

{ 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 = name: { fromUri, fromRefspec, localRefspec, ... }: {
path = [ pkgs.gitFull pkgs.openssh pkgs.lix ];
script = ''
set -xe
RUNTIME_DIRECTORY="/run/onewaysync-${name}"
trap "git worktree remove -f "$RUNTIME_DIRECTORY"/${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 ${cfg.pushUrl}:refs/heads/${localRefspec}"
echo "Current ref: $EXPECTED_REF"
git worktree add -f "$RUNTIME_DIRECTORY"/${name} refs/remotes/origin/${localRefspec}
cd "$RUNTIME_DIRECTORY"/${name}
git pull origin ${localRefspec} --no-rebase
EXPECTED_REF=$(git rev-list refs/remotes/origin/${localRefspec} | head -1)
git config user.name Fork-o-Tron
git config user.email noreply@forkos.org
git fetch ${fromUri} ${fromRefspec}
'' + lib.optionalString (!(lib.hasInfix "staging" localRefspec)) ''
OLD_STDENV=$(nix eval -f . stdenv.outPath --store "$RUNTIME_DIRECTORY")
'' + ''
git merge FETCH_HEAD
'' + lib.optionalString (!(lib.hasInfix "staging" localRefspec)) ''
NEW_STDENV=$(nix eval -f . stdenv.outPath --store "$RUNTIME_DIRECTORY")
# Do not allow auto-merging a staging iteration
test "$OLD_STDENV" = "$NEW_STDENV"
'' + ''
GIT_SSH_COMMAND='ssh -i ${cfg.deployKeyPath}' git push ${cfg.pushUrl} HEAD:refs/heads/${localRefspec}
'';
serviceConfig = {
User = "git";
Group = "git";
Type = "oneshot";
RuntimeDirectory = "onewaysync-${name}";
WorkingDirectory = "/run/onewaysync-${name}";
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";
};
stateDirectory = mkOption {
type = types.str;
default = "/var/lib/onewaysync";
description = "State directory where the copies of nixpkgs are stored";
};
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 {
fileSystems."/var/lib/onewaysync" = mkIf (cfg.stateDirectory != "/var/lib/onewaysync") {
device = cfg.stateDirectory;
options = [ "bind" ];
};
systemd.timers = mapAttrs' (name: value: {
name = "ows-${name}";
value = mkSyncTimer name value;
}) cfg.branches;
systemd.services = mapAttrs' (name: value: {
name = "ows-${name}";
value = mkSyncService name value;
}) cfg.branches;
};
}