nix-gitlab-ci/flake.nix
technofab 586fb88b9d feat(v2): initial v2 implementation
add multi-arch (arm & x64) image
add multiple pipelines (ci now creates the "default" pipeline as a shorthand)
simplify devenv flake input
merge all cache options together, now $NIX_CI_CACHE_STRATEGY decides how the cache works
setup_nix_ci and finalize_nix_ci are now flake packages and work standalone
the specific image is not needed anymore, any image with the right dependencies works
runner cache is not the default anymore (because it sucked most of the time)
the pipeline is selected by $NIX_CI_PIPELINE_NAME or if empty by $CI_PIPELINE_SOURCE,
so for the old behaviour $NIX_CI_PIPELINE_NAME=default is needed, future
work will be needed to handle this more nicely
2025-02-21 12:24:54 +01:00

230 lines
8.4 KiB
Nix

{
outputs = {
flake-parts,
systems,
...
} @ inputs:
flake-parts.lib.mkFlake {inherit inputs;} {
imports = [
inputs.devenv.flakeModule
inputs.treefmt-nix.flakeModule
./lib/flakeModule.nix
];
systems = import systems;
flake = {};
perSystem = {
pkgs,
inputs',
config,
...
}: rec {
treefmt = {
projectRootFile = "flake.nix";
programs = {
alejandra.enable = true;
mdformat.enable = true;
yamlfmt.enable = true;
};
};
devenv.shells.default = {
containers = pkgs.lib.mkForce {};
packages = with pkgs; [dive skopeo];
pre-commit = {
hooks = {
treefmt = {
enable = true;
packageOverrides.treefmt = config.treefmt.build.wrapper;
};
};
};
};
# should set the "default" pipeline
ci = {
stages = ["test"];
jobs = {
"test" = {
stage = "test";
nix = {
deps = [pkgs.hello pkgs.curl];
enable-runner-cache = true;
};
variables = {
TEST = "test";
TEST_WITH_DERIVATION = "${pkgs.hello}/test";
};
script = [
"hello"
"curl google.de"
"echo $TEST $TEST_WITH_DERIVATION"
];
};
"test-default" = {
stage = "test";
nix.deps = [pkgs.hello];
script = ["hello"];
};
"test-non-nix" = {
nix.enable = false;
stage = "test";
image = "alpine:latest";
script = [
"echo \"This job will not be modified to use nix\""
];
};
};
};
pipelines."non-default" = {
stages = ["test"];
jobs = {
"test" = {
stage = "test";
script = [
"echo Hello from another pipeline"
];
};
};
};
packages = let
setupScript = pkgs.writeShellScriptBin "setup_nix_ci" ''
echo -e "\\e[0Ksection_start:`date +%s`:nix_setup\\r\\e[0KSetting up Nix CI"
nix path-info --all > /tmp/nix-store-before
if [ -z "$_NIX_CI_DISABLE_CACHE" ]; then
echo -e "\\e[0Ksection_start:`date +%s`:cache_setup[collapsed=true]\\r\\e[0KConfiguring cache ($_NIX_CI_CACHE_STRATEGY)"
case "$_NIX_CI_CACHE_STRATEGY" in
"runner")
export RUNNER_CACHE=''${RUNNER_CACHE:-"file://$(pwd)/.nix-cache"}
echo "Runner Cache: $RUNNER_CACHE"
export NIX_CONFIG="$NIX_CONFIG
extra-trusted-substituters = $RUNNER_CACHE?priority=10&trusted=true
extra-substituters = $RUNNER_CACHE?priority=10&trusted=true
"
;;
"attic")
echo "Attic Cache: $ATTIC_CACHE"
attic login --set-default ci "$ATTIC_SERVER" "$ATTIC_TOKEN" || true
attic use "$ATTIC_CACHE" || true
;;
"cachix")
echo "Cachix Cache: $CACHIX_CACHE"
cachix use "$CACHIX_CACHE" || true
;;
"none")
echo "Cache strategy is none, doing nothing..."
;;
*)
echo "WARNING: Invalid cache strategy set: '$_NIX_CI_CACHE_STRATEGY'"
;;
esac
echo -e "\\e[0Ksection_end:`date +%s`:cache_setup\\r\\e[0K"
else
echo "Caching disabled (NIX_CI_DISABLE_CACHE), skipping cache configuration..."
fi
# load the job's deps only if the name was passed
if [[ ! -z $1 ]]; then
echo -e "\\e[0Ksection_start:`date +%s`:nix_deps[collapsed=true]\\r\\e[0KFetching Nix dependencies for job"
nix build .#$1
source $(readlink -f result)
echo -e "\\e[0Ksection_end:`date +%s`:nix_deps\\r\\e[0K"
fi
echo -e "\\e[0Ksection_end:`date +%s`:nix_setup\\r\\e[0K"
'';
finalizeScript = pkgs.writeShellScriptBin "finalize_nix_ci" ''
echo -e "\\e[0Ksection_start:`date +%s`:finalize_nix_ci\\r\\e[0KFinalizing Nix CI..."
nix path-info --all > /tmp/nix-store-after
echo "Finding new paths..."
NEW_PATHS=$(${pkgs.diffutils}/bin/diff --new-line-format="%L" \
--old-line-format="" --unchanged-line-format="" \
/tmp/nix-store-before /tmp/nix-store-after)
COUNT=$(${pkgs.busybox}/bin/wc -l <<<"$NEW_PATHS")
if [ -z "$_NIX_CI_DISABLE_CACHE" ]; then
echo -e "\\e[0Ksection_start:`date +%s`:cache_push[collapsed=true]\\r\\e[0KPushing $COUNT new store paths to cache ($_NIX_CI_CACHE_STRATEGY)"
echo $NEW_PATHS | {
case "$_NIX_CI_CACHE_STRATEGY" in
"runner")
export RUNNER_CACHE=''${RUNNER_CACHE:-"file://$(pwd)/.nix-cache"}
# add ^* to all store paths ending in .drv (prevent warning log spam)
${pkgs.gnused}/bin/sed '/\.drv$/s/$/^*/' | nix copy --quiet --to "$RUNNER_CACHE" --stdin || true
;;
"attic")
attic push --stdin ci:$ATTIC_CACHE || true
;;
"cachix")
cachix push $CACHIX_CACHE || true
;;
"none")
echo "Cache strategy is none, doing nothing..."
;;
*)
echo "WARNING: Invalid cache strategy set: '$_NIX_CI_CACHE_STRATEGY'"
;;
esac
}
echo -e "\\e[0Ksection_end:`date +%s`:cache_push\\r\\e[0K"
else
echo "Caching disabled, not uploading $COUNT new store entries..."
fi
echo -e "\\e[0Ksection_end:`date +%s`:finalize_nix_ci\\r\\e[0K"
'';
in {
setup-script = setupScript;
finalize-script = finalizeScript;
image = pkgs.dockerTools.buildImage {
name = "nix-ci";
fromImage = pkgs.dockerTools.pullImage {
imageName = "nixpkgs/nix-flakes";
# nix run nixpkgs#nix-prefetch-docker -- --image-name nixpkgs/nix-flakes --image-tag latest --arch <amd64/arm64> --os linux
imageDigest = "sha256:95bce4317c15dfab3babac5a6d19d3ed41e31a02a8aaf3d4f6639778cb763b0a";
sha256 =
if pkgs.stdenv.hostPlatform.isAarch64
then "DMlSaP+ZVqxd9NxdFydGyfkuJdmOW5jt5iM/7cDyTEM="
else "mfTNlGOpThanLlLQ2lL1RTcHqZJWdqUafYDZMeZPWEk=";
finalImageName = "nixpkgs/nix-flakes";
finalImageTag = "latest";
};
copyToRoot = pkgs.buildEnv {
name = "image-root";
paths = [
pkgs.gitMinimal
pkgs.gnugrep
pkgs.cachix
pkgs.attic-client
setupScript
finalizeScript
];
pathsToLink = ["/bin"];
};
};
};
checks = packages;
};
};
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
# flake & devenv related
flake-parts.url = "github:hercules-ci/flake-parts";
systems.url = "github:nix-systems/default-linux";
devenv.url = "github:cachix/devenv";
treefmt-nix.url = "github:numtide/treefmt-nix";
};
nixConfig = {
extra-substituters = [
"https://cache.nixos.org/"
"https://nix-community.cachix.org"
"https://devenv.cachix.org"
];
extra-trusted-public-keys = [
"cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY="
"nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs="
"devenv.cachix.org-1:w1cLUi8dv3hnoSPGAuibQv+f9TZLr6cv/Hm9XgU50cw="
];
};
}