Compare commits

..

No commits in common. "main" and "v3.0.0" have entirely different histories.
main ... v3.0.0

16 changed files with 49 additions and 134 deletions

View file

@ -55,5 +55,3 @@ stages:
- build-images - build-images
- build - build
- trigger - trigger
variables:
NIX_CI_IMAGE: $CI_REGISTRY_IMAGE/nix-ci:$CI_COMMIT_SHORT_SHA

View file

@ -108,4 +108,4 @@ There is also `.#gitlab-ci:pipeline:<pipeline name>:job-deps:<name>` which gener
Some parts of this implementation are adapted/inspired from https://gitlab.com/Cynerd/gitlab-ci-nix Some parts of this implementation are adapted/inspired from https://gitlab.com/Cynerd/gitlab-ci-nix
[docs-soonix]: https://nix-gitlab-ci.projects.tf/soonix "Soonix Integration" [docs-soonix]: https://nix-gitlab-ci.projects,tf/soonix "Soonix Integration"

View file

@ -2,13 +2,6 @@
The CI/CD Component has some inputs which configure defaults for Nix GitLab CI. The CI/CD Component has some inputs which configure defaults for Nix GitLab CI.
!!! WARNING
If you get errors like `the component path is not supported` it might be related to
[this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/437996#note_1775337668).
See [here](https://gitlab.com/TECHNOFAB/nix-gitlab-ci/-/issues/27) for more.
## `version` ## `version`
- Type: `string` - Type: `string`

View file

@ -9,14 +9,3 @@ This project provides a Nix flake module that allows you to generate your `.gitl
- **Modularity:** Define and manage your CI configurations in a structured and modular way using Nix modules, making it easier to share and reuse CI logic across multiple projects. - **Modularity:** Define and manage your CI configurations in a structured and modular way using Nix modules, making it easier to share and reuse CI logic across multiple projects.
This documentation will guide you through setting up and using Nix GitLab CI for your projects. This documentation will guide you through setting up and using Nix GitLab CI for your projects.
## Warnings
To save you from frantically searching these docs if something doesn't work as expected, here are the most important warnings ;)
!!! warning
Do not put Nix store paths into global/pipeline variables. They will simply be passed through,
resulting in bad portability (if two runners have different archs for example, one cannot find the path).
If you need any Nix store path in env variables, always do it on the job level, there
it will automatically be computed at runtime, thus will always work no matter which runner it runs on.

12
flake.lock generated
View file

@ -2,11 +2,11 @@
"nodes": { "nodes": {
"nixpkgs": { "nixpkgs": {
"locked": { "locked": {
"lastModified": 1764667669, "lastModified": 1756542300,
"narHash": "sha256-7WUCZfmqLAssbDqwg9cUDAXrSoXN79eEEq17qhTNM/Y=", "narHash": "sha256-tlOn88coG5fzdyqz6R93SQL5Gpq+m/DsWpekNFhqPQk=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "418468ac9527e799809c900eda37cbff999199b6", "rev": "d7600c775f877cd87b4f5a831c28aa94137377aa",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -37,11 +37,11 @@
}, },
"locked": { "locked": {
"dir": "lib", "dir": "lib",
"lastModified": 1758738378, "lastModified": 1756370106,
"narHash": "sha256-NjzqdvQCDDdObEBH8x/vdhbdhrIB+N9E570uCdksGHY=", "narHash": "sha256-l84ojcHuQWBwn4BRxQsMMfQpcq/Az/sHh/hSqFgVtyg=",
"owner": "rensa-nix", "owner": "rensa-nix",
"repo": "core", "repo": "core",
"rev": "abe19f9f13aff41de2b63304545c87d193d19ef4", "rev": "9c1a29fa9ba7cbbb78b9e47eb8afbcd29303a3b4",
"type": "gitlab" "type": "gitlab"
}, },
"original": { "original": {

View file

@ -1 +1 @@
3.1.2 3.0.0

View file

@ -50,7 +50,7 @@ in rec {
filterJobVariables = shouldContain: job: filterJobVariables = shouldContain: job:
concatMapAttrs ( concatMapAttrs (
name: value: name: value:
optionalAttrs ((hasInfix builtins.storeDir value) == shouldContain) { optionalAttrs ((hasInfix "/nix/store/" value) == shouldContain) {
${name} = value; ${name} = value;
} }
) )

View file

@ -11,13 +11,13 @@ in
pipelineName, pipelineName,
nixConfig, nixConfig,
}: }:
if ! nixConfig.enable (builtins.removeAttrs job ["variables" "cache"])
then job // (optionalAttrs nixConfig.enable (
else (prependToBeforeScript ["source setup_nix_ci \"gitlab-ci:pipeline:${pipelineName}:job-deps:${key}\""] job)
(builtins.removeAttrs job ["variables" "cache"])
// (prependToBeforeScript ["source setup_nix_ci \"gitlab-ci:pipeline:${pipelineName}:job-deps:${key}\""] job)
// (appendToAfterScript ["finalize_nix_ci"] job) // (appendToAfterScript ["finalize_nix_ci"] job)
// (let ))
// optionalAttrs nixConfig.enable (
(let
variables = variables =
(filterJobVariables false job) (filterJobVariables false job)
// optionalAttrs nixConfig.enableRunnerCache { // optionalAttrs nixConfig.enableRunnerCache {
@ -40,3 +40,4 @@ in
optionalAttrs (cache != []) { optionalAttrs (cache != []) {
inherit cache; inherit cache;
}) })
)

View file

@ -637,22 +637,22 @@ in rec {
// gitlabOptions; // gitlabOptions;
config = let config = let
attrsToKeep = builtins.attrNames gitlabOptions; attrsToKeep = builtins.attrNames gitlabOptions;
job = filterUnset (filterAttrs (n: _v: builtins.elem n attrsToKeep) config);
in { in {
finalConfig = cilib.mkJobPatched { finalConfig = cilib.mkJobPatched {
key = name; key = name;
job = filterUnset (filterAttrs (n: _v: builtins.elem n attrsToKeep) config);
nixConfig = config.nix; nixConfig = config.nix;
inherit job pipelineName; inherit pipelineName;
}; };
depsDrv = cilib.mkJobDeps { depsDrv = cilib.mkJobDeps {
key = name; key = name;
job = config.finalConfig;
nixConfig = config.nix; nixConfig = config.nix;
inherit job;
}; };
runnerDrv = cilib.mkJobRun { runnerDrv = cilib.mkJobRun {
key = name; key = name;
job = config.finalConfig;
jobDeps = config.depsDrv; jobDeps = config.depsDrv;
inherit job;
}; };
packages = { packages = {
"gitlab-ci:pipeline:${pipelineName}:job-deps:${name}" = config.depsDrv; "gitlab-ci:pipeline:${pipelineName}:job-deps:${name}" = config.depsDrv;

View file

@ -4,7 +4,7 @@
pipelineSubmodule, pipelineSubmodule,
... ...
}: let }: let
inherit (lib) mkOption types foldr; inherit (lib) mkOption types;
in rec { in rec {
configSubmodule = { configSubmodule = {
options = { options = {
@ -65,7 +65,7 @@ in rec {
}; };
}; };
config = { config = {
packages = foldr (pipeline: acc: acc // pipeline) {} ( packages = lib.fold (pipeline: acc: acc // pipeline) {} (
map (pipeline: pipeline.packages) (builtins.attrValues config.pipelines) map (pipeline: pipeline.packages) (builtins.attrValues config.pipelines)
); );
soonix = config.config.soonix.finalConfig; soonix = config.config.soonix.finalConfig;

View file

@ -28,19 +28,18 @@ while [[ $# -gt 0 ]]; do
;; ;;
*) *)
echo "Unknown option: $1" >&2 echo "Unknown option: $1" >&2
echo "use --include-dirty, --no-sandbox, --keep-tmp and --keep-env <ENV>" >&2
exit 1 exit 1
;; ;;
esac esac
done done
if [ $NO_SANDBOX = false ]; then if [ "$NO_SANDBOX" = false ]; then
echo "Running with simple sandboxing" echo "Running with simple sandboxing"
NGCI_TMPDIR=$(mktemp -dt "nix-gitlab-ci.XXX") TMPDIR=$(mktemp -dt "nix-gitlab-ci.XXX")
if [ $KEEP_TMP = false ]; then if [ "$KEEP_TMP" = false ]; then
trap "rm -rf '$NGCI_TMPDIR'" EXIT trap "rm -rf '$TMPDIR'" EXIT
else else
echo "Temp dir will be preserved at: $NGCI_TMPDIR" echo "Temp dir will be preserved at: $TMPDIR"
fi fi
# check if dirty # check if dirty
@ -51,15 +50,14 @@ if [ $NO_SANDBOX = false ]; then
git diff --staged > "$DIRTY_PATCH" git diff --staged > "$DIRTY_PATCH"
trap "rm -f '$DIRTY_PATCH'" EXIT trap "rm -f '$DIRTY_PATCH'" EXIT
fi fi
git clone . $NGCI_TMPDIR git clone . $TMPDIR
pushd $NGCI_TMPDIR >/dev/null pushd $TMPDIR >/dev/null
if [[ ! -z "$DIRTY_PATCH" && $INCLUDE_DIRTY = true ]]; then if [[ ! -z "$DIRTY_PATCH" && "$INCLUDE_DIRTY" = true ]]; then
echo "Copying dirty changes..." echo "Copying dirty changes..."
git apply "$DIRTY_PATCH" 2>/dev/null || echo "Failed to copy dirty changes" git apply "$DIRTY_PATCH" 2>/dev/null || echo "Failed to copy dirty changes"
git add . # required so the files are staged again
fi fi
echo "Running job in $NGCI_TMPDIR" echo "Running job in $TMPDIR"
env -i $( env -i $(
if [[ -n "$KEEP_ENV" ]]; then if [[ -n "$KEEP_ENV" ]]; then
IFS=',' read -ra VARS <<< "$KEEP_ENV" IFS=',' read -ra VARS <<< "$KEEP_ENV"

View file

@ -10,7 +10,6 @@ in
# the child pipeline can then use the built images to test them # the child pipeline can then use the built images to test them
extraData = { extraData = {
stages = ["build-images" "build" "trigger"]; stages = ["build-images" "build" "trigger"];
variables.NIX_CI_IMAGE = "$CI_REGISTRY_IMAGE/nix-ci:$CI_COMMIT_SHORT_SHA";
"build:image" = { "build:image" = {
stage = "build-images"; stage = "build-images";
parallel.matrix = [ parallel.matrix = [

30
nix/repo/flake.lock generated
View file

@ -3,11 +3,11 @@
"devshell-lib": { "devshell-lib": {
"locked": { "locked": {
"dir": "lib", "dir": "lib",
"lastModified": 1758204313, "lastModified": 1755673398,
"narHash": "sha256-ainbY0Oajb1HMdvy+A8QxF/P5qwcbEzJGEY5pzKdDdc=", "narHash": "sha256-51MmR+Eo1+bKDd/Ss77wwTqi4yAR2xgmyCSEbKWSpj0=",
"owner": "rensa-nix", "owner": "rensa-nix",
"repo": "devshell", "repo": "devshell",
"rev": "7d0c4bc78d9f017a739b0c7eb2f4e563118353e6", "rev": "e76bef387e8a4574f9b6d37b1a424e706491af08",
"type": "gitlab" "type": "gitlab"
}, },
"original": { "original": {
@ -20,11 +20,11 @@
"nixmkdocs-lib": { "nixmkdocs-lib": {
"locked": { "locked": {
"dir": "lib", "dir": "lib",
"lastModified": 1763481845, "lastModified": 1757055638,
"narHash": "sha256-Bp0+9rDmlPWMcnKqGx+BG4+o5KO8FuDAOvXRnXrm3Fo=", "narHash": "sha256-KHYSkEreFe4meXzSdEbknC/HwaQSNClQkc8vzHlAsMM=",
"owner": "TECHNOFAB", "owner": "TECHNOFAB",
"repo": "nixmkdocs", "repo": "nixmkdocs",
"rev": "73d59093df94a894d25bc4bf71880b6f00faa62f", "rev": "7840a5febdbeaf2da90babf6c94b3d0929d2bf74",
"type": "gitlab" "type": "gitlab"
}, },
"original": { "original": {
@ -37,11 +37,11 @@
"nixtest-lib": { "nixtest-lib": {
"locked": { "locked": {
"dir": "lib", "dir": "lib",
"lastModified": 1759340550, "lastModified": 1756812148,
"narHash": "sha256-EH9heYb/nHHzCpUGQGqVQnuyVGQ7D6MVMgJmzNvvmJ8=", "narHash": "sha256-0g8KNk4zoLApA51PBHOWqPLRYpprjrQuSzNCjfBQgu8=",
"owner": "TECHNOFAB", "owner": "TECHNOFAB",
"repo": "nixtest", "repo": "nixtest",
"rev": "5a7053afcbb211b9cf8fe87f7892bb9f6b76b678", "rev": "5741109cc9ec2b6d41b56abd3f5bc51ed7a9a228",
"type": "gitlab" "type": "gitlab"
}, },
"original": { "original": {
@ -63,11 +63,11 @@
"soonix-lib": { "soonix-lib": {
"locked": { "locked": {
"dir": "lib", "dir": "lib",
"lastModified": 1763323017, "lastModified": 1756797658,
"narHash": "sha256-MJyg37d+VMfRoFiVUj16FW+zkEwQXbgK9LoFF/SHoxA=", "narHash": "sha256-4rkyP4oaoqG/FFVL7W8U+8hGer4tOBPff/2SeN5tJYQ=",
"owner": "TECHNOFAB", "owner": "TECHNOFAB",
"repo": "soonix", "repo": "soonix",
"rev": "078034b01e4eaf1f9436d46721f7cbe0d96eb8b4", "rev": "3baef660cf8b87391d475a0455dd66fae0e60008",
"type": "gitlab" "type": "gitlab"
}, },
"original": { "original": {
@ -80,11 +80,11 @@
"treefmt-nix": { "treefmt-nix": {
"flake": false, "flake": false,
"locked": { "locked": {
"lastModified": 1762938485, "lastModified": 1756662192,
"narHash": "sha256-AlEObg0syDl+Spi4LsZIBrjw+snSVU4T8MOeuZJUJjM=", "narHash": "sha256-F1oFfV51AE259I85av+MAia221XwMHCOtZCMcZLK2Jk=",
"owner": "numtide", "owner": "numtide",
"repo": "treefmt-nix", "repo": "treefmt-nix",
"rev": "5b4ee75aeefd1e2d5a1cc43cf6ba65eba75e83e4", "rev": "1aabc6c05ccbcbf4a635fb7a90400e44282f61c4",
"type": "github" "type": "github"
}, },
"original": { "original": {

View file

@ -62,7 +62,6 @@ nix-ci:build:
|| NIX_CI_PIPELINE_NAME="$CI_PIPELINE_SOURCE"; || NIX_CI_PIPELINE_NAME="$CI_PIPELINE_SOURCE";
fi fi
echo "NIX_CI_GENERATED_PIPELINE_NAME=$NIX_CI_PIPELINE_NAME" >> trigger.env echo "NIX_CI_GENERATED_PIPELINE_NAME=$NIX_CI_PIPELINE_NAME" >> trigger.env
echo "ORIGINAL_CI_PIPELINE_SOURCE=$CI_PIPELINE_SOURCE" >> trigger.env
# inheritance of pipeline variables is a bit weird, so explicitly override them # inheritance of pipeline variables is a bit weird, so explicitly override them
# (ctx: setting any of these in the project variables would only apply correctly # (ctx: setting any of these in the project variables would only apply correctly
# in this pipeline, not the child pipeline, instead weirdly enough the default # in this pipeline, not the child pipeline, instead weirdly enough the default

View file

@ -64,22 +64,6 @@
nixConfig.enable = false; nixConfig.enable = false;
}; };
} }
{
name = "jobPatched nix disabled with variables and cache";
expected = {
variables."HELLO" = "world";
cache = [{key = "example";}];
};
actual = mkJobPatched {
key = "test";
pipelineName = "test";
job = {
variables."HELLO" = "world";
cache = [{key = "example";}];
};
nixConfig.enable = false;
};
}
{ {
name = "jobPatched without runner cache"; name = "jobPatched without runner cache";
expected = { expected = {
@ -145,7 +129,7 @@
# sh # sh
'' ''
set -euo pipefail set -euo pipefail
${ntlib.helpers.path (with pkgs; [jq gnugrep coreutils])} ${ntlib.helpers.path [pkgs.jq pkgs.gnugrep pkgs.coreutils]}
echo "two keys, one json one pretty" echo "two keys, one json one pretty"
jq 'keys | length == 2' "${pipeline}" | grep -q true jq 'keys | length == 2' "${pipeline}" | grep -q true
echo "key[0] is exactly 'gitlab-ci:pipeline:test'" echo "key[0] is exactly 'gitlab-ci:pipeline:test'"
@ -161,13 +145,10 @@
''; '';
} }
{ {
name = "ignore store paths in variables with nix disabled"; name = "handle store paths in variables";
expected = { expected = {
stages = ["test"]; stages = ["test"];
test = { test.stage = "test";
stage = "test";
variables."TEST" = "${pkgs.hello}";
};
}; };
actual = actual =
(mkPipeline { (mkPipeline {
@ -182,28 +163,6 @@
}; };
}).finalConfig; }).finalConfig;
} }
{
# it doesn't make much sense to have any nix store path in variables, but we ignore it for global variables
name = "ignore store paths in global variables";
expected = {
variables = {
HELLO = "world";
CURL = toString pkgs.curl;
};
};
actual =
(mkPipeline {
name = "test";
nixConfig.enable = true;
pipeline = {
variables = {
HELLO = "world";
CURL = toString pkgs.curl;
};
jobs = {};
};
}).finalConfig;
}
]; ];
}; };
} }

View file

@ -77,27 +77,6 @@
assert_file_contains ${package} '"EXAMPLE":"/nix/store/.*-hello-.*"' assert_file_contains ${package} '"EXAMPLE":"/nix/store/.*-hello-.*"'
''; '';
} }
{
name = "correctly inject variables containing nix store paths at runtime";
type = "script";
script = let
package =
(cilib.mkCI {
pipelines."test".jobs."test" = {
stage = ".pre";
variables.EXAMPLE = "${pkgs.hello}";
script = [];
};
}).packages."gitlab-ci:pipeline:test:job-deps:test";
in
# sh
''
${ntlib.helpers.path [pkgs.gnugrep]}
${ntlib.helpers.scriptHelpers}
assert_file_contains ${package} 'export PATH=":$PATH";'
assert_file_contains ${package} 'export EXAMPLE="/nix/store/.*-hello-.*"'
'';
}
]; ];
}; };
} }