2024-07-04 13:18:21 +00:00
|
|
|
{ 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, ... }: {
|
2024-07-19 22:31:54 +00:00
|
|
|
path = [ pkgs.gitFull pkgs.openssh pkgs.lix ];
|
2024-07-04 13:18:21 +00:00
|
|
|
script = ''
|
2024-07-19 22:31:54 +00:00
|
|
|
set -xe
|
2024-07-22 13:41:47 +00:00
|
|
|
RUNTIME_DIRECTORY="/run/onewaysync-${name}"
|
|
|
|
trap "git worktree remove -f "$RUNTIME_DIRECTORY"/${name}" EXIT
|
2024-07-04 13:18:21 +00:00
|
|
|
|
|
|
|
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"
|
2024-07-22 13:41:47 +00:00
|
|
|
git worktree add -f "$RUNTIME_DIRECTORY"/${name} refs/remotes/origin/${localRefspec}
|
|
|
|
cd "$RUNTIME_DIRECTORY"/${name}
|
2024-08-08 08:39:00 +00:00
|
|
|
git pull origin ${localRefspec} --no-rebase
|
2024-07-22 13:41:47 +00:00
|
|
|
EXPECTED_REF=$(git rev-list refs/remotes/origin/${localRefspec} | head -1)
|
2024-07-19 21:25:26 +00:00
|
|
|
git config user.name Fork-o-Tron
|
|
|
|
git config user.email noreply@forkos.org
|
2024-07-04 13:18:21 +00:00
|
|
|
git fetch ${fromUri} ${fromRefspec}
|
2024-07-19 22:31:54 +00:00
|
|
|
'' + lib.optionalString (!(lib.hasInfix "staging" localRefspec)) ''
|
2024-07-22 13:41:47 +00:00
|
|
|
OLD_STDENV=$(nix eval -f . stdenv.outPath --store "$RUNTIME_DIRECTORY")
|
2024-07-19 22:31:54 +00:00
|
|
|
'' + ''
|
2024-07-19 21:13:20 +00:00
|
|
|
git merge FETCH_HEAD
|
2024-07-19 22:31:54 +00:00
|
|
|
'' + lib.optionalString (!(lib.hasInfix "staging" localRefspec)) ''
|
2024-07-22 13:41:47 +00:00
|
|
|
NEW_STDENV=$(nix eval -f . stdenv.outPath --store "$RUNTIME_DIRECTORY")
|
2024-07-19 22:31:54 +00:00
|
|
|
# Do not allow auto-merging a staging iteration
|
|
|
|
test "$OLD_STDENV" = "$NEW_STDENV"
|
|
|
|
'' + ''
|
2024-07-19 21:13:20 +00:00
|
|
|
GIT_SSH_COMMAND='ssh -i ${cfg.deployKeyPath}' git push ${cfg.pushUrl} HEAD:${targetRef}
|
2024-07-04 13:18:21 +00:00
|
|
|
'';
|
|
|
|
serviceConfig = {
|
|
|
|
User = "git";
|
|
|
|
Group = "git";
|
|
|
|
Type = "oneshot";
|
2024-07-22 13:41:47 +00:00
|
|
|
RuntimeDirectory = "onewaysync-${name}";
|
|
|
|
WorkingDirectory = "/run/onewaysync-${name}";
|
2024-07-04 13:18:21 +00:00
|
|
|
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;
|
|
|
|
};
|
|
|
|
}
|