diff --git a/docs/index.md b/docs/index.md index 214fbf3..14f7da3 100644 --- a/docs/index.md +++ b/docs/index.md @@ -9,3 +9,14 @@ 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. 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. diff --git a/lib/VERSION b/lib/VERSION index cb2b00e..fd2a018 100644 --- a/lib/VERSION +++ b/lib/VERSION @@ -1 +1 @@ -3.0.1 +3.1.0 diff --git a/lib/impl/jobPatched.nix b/lib/impl/jobPatched.nix index 73adb38..367a374 100644 --- a/lib/impl/jobPatched.nix +++ b/lib/impl/jobPatched.nix @@ -3,7 +3,7 @@ helpers, }: let inherit (lib) toList optionalAttrs optional; - inherit (helpers) prependToBeforeScript appendToAfterScript; + inherit (helpers) prependToBeforeScript appendToAfterScript filterJobVariables; in { key, @@ -11,28 +11,32 @@ in pipelineName, nixConfig, }: - if ! nixConfig.enable then job else - (builtins.removeAttrs job [ "variables" "cache" ]) - // (prependToBeforeScript [ "source setup_nix_ci \"gitlab-ci:pipeline:${pipelineName}:job-deps:${key}\"" ] job) - // (appendToAfterScript [ "finalize_nix_ci" ] job) - // (let - variables = job.variables or {} // - optionalAttrs nixConfig.enableRunnerCache { - NIX_CI_CACHE_STRATEGY = "runner"; - }; - in - # filter empty variables - optionalAttrs (variables != {}) { - inherit variables; - }) - // (let - cache = (toList (job.cache or [])) ++ - (optional nixConfig.enableRunnerCache { - key = nixConfig.runnerCacheKey; - paths = [ ".nix-cache/" ]; - }); - in - # filter empty cache - optionalAttrs (cache != []) { - inherit cache; - }) + if ! nixConfig.enable + then job + else + (builtins.removeAttrs job ["variables" "cache"]) + // (prependToBeforeScript ["source setup_nix_ci \"gitlab-ci:pipeline:${pipelineName}:job-deps:${key}\""] job) + // (appendToAfterScript ["finalize_nix_ci"] job) + // (let + variables = + (filterJobVariables false job) + // optionalAttrs nixConfig.enableRunnerCache { + NIX_CI_CACHE_STRATEGY = "runner"; + }; + in + # filter empty variables + optionalAttrs (variables != {}) { + inherit variables; + }) + // (let + cache = + (toList (job.cache or [])) + ++ (optional nixConfig.enableRunnerCache { + key = nixConfig.runnerCacheKey; + paths = [".nix-cache/"]; + }); + in + # filter empty cache + optionalAttrs (cache != []) { + inherit cache; + }) diff --git a/lib/impl/modules/job.nix b/lib/impl/modules/job.nix index 295093d..1f99d5b 100644 --- a/lib/impl/modules/job.nix +++ b/lib/impl/modules/job.nix @@ -646,7 +646,7 @@ in rec { }; depsDrv = cilib.mkJobDeps { key = name; - job = config.finalConfig; + inherit job; nixConfig = config.nix; }; runnerDrv = cilib.mkJobRun { diff --git a/nix/repo/ci.nix b/nix/repo/ci.nix index 157ede7..9ef9aac 100644 --- a/nix/repo/ci.nix +++ b/nix/repo/ci.nix @@ -1,5 +1,5 @@ {inputs, ...}: let - inherit (inputs) cilib; + inherit (inputs) cilib pkgs; in cilib.mkCI { config.soonix = { @@ -58,9 +58,25 @@ in }; }; pipelines."default" = { - stages = ["test" "build" "deploy"]; + stages = ["check" "test" "build" "deploy"]; + variables = { + EXAMPLE = "empty"; + CURL = toString pkgs.curl; + }; jobs = { + "check" = { + stage = "check"; + script = [ + "set -euo pipefail" + "echo EXAMPLE=$EXAMPLE CURL=$CURL SAMPLE=$SAMPLE HELLO=$HELLO" + ]; + variables = { + SAMPLE = "working"; + HELLO = toString pkgs.hello; + }; + }; "test" = { + nix.deps = with pkgs; [coreutils nix]; stage = "test"; script = [ "nix run .#tests -- --junit=junit.xml" @@ -73,6 +89,7 @@ in }; "docs" = { stage = "build"; + nix.deps = with pkgs; [coreutils nix]; script = [ # sh '' diff --git a/tests/cilib_test.nix b/tests/cilib_test.nix index 6de4ed6..3b76fb8 100644 --- a/tests/cilib_test.nix +++ b/tests/cilib_test.nix @@ -56,28 +56,26 @@ } { name = "jobPatched nix disabled"; + expected = {}; + actual = mkJobPatched { + key = "test"; + pipelineName = "test"; + job = {}; + nixConfig.enable = false; + }; + } + { + name = "jobPatched nix disabled with variables and cache"; expected = { - cache = { - name = "some"; - paths = [ "this" ]; - }; - variables = { - BASH = toString pkgs.bash; - TEST = "work"; - }; + variables."HELLO" = "world"; + cache = [{key = "example";}]; }; actual = mkJobPatched { key = "test"; pipelineName = "test"; job = { - cache = { - name = "some"; - paths = [ "this" ]; - }; - variables = { - BASH = toString pkgs.bash; - TEST = "work"; - }; + variables."HELLO" = "world"; + cache = [{key = "example";}]; }; nixConfig.enable = false; }; @@ -85,30 +83,13 @@ { name = "jobPatched without runner cache"; expected = { - after_script = [ "finalize_nix_ci" ]; - before_script = [ "source setup_nix_ci \"gitlab-ci:pipeline:test:job-deps:test\"" ]; - variables = { - BASH = toString pkgs.bash; - TEST = "work"; - }; - cache = [{ - name = "some"; - paths = [ "this" ]; - }]; + after_script = ["finalize_nix_ci"]; + before_script = ["source setup_nix_ci \"gitlab-ci:pipeline:test:job-deps:test\""]; }; actual = mkJobPatched { key = "test"; pipelineName = "test"; - job = { - cache = { - name = "some"; - paths = [ "this" ]; - }; - variables = { - BASH = toString pkgs.bash; - TEST = "work"; - }; - }; + job = {}; nixConfig = { enable = true; enableRunnerCache = false; @@ -118,34 +99,20 @@ { name = "jobPatched with runner cache"; expected = { - after_script = [ "finalize_nix_ci" ]; - before_script = [ "source setup_nix_ci \"gitlab-ci:pipeline:test:job-deps:test\"" ]; - cache = [{ - name = "some"; - paths = [ "this" ]; - }{ - key = "test"; - paths = [ ".nix-cache/" ]; - }]; - variables = { - NIX_CI_CACHE_STRATEGY = "runner"; - BASH = toString pkgs.bash; - TEST = "work"; - }; + after_script = ["finalize_nix_ci"]; + before_script = ["source setup_nix_ci \"gitlab-ci:pipeline:test:job-deps:test\""]; + cache = [ + { + key = "test"; + paths = [".nix-cache/"]; + } + ]; + variables."NIX_CI_CACHE_STRATEGY" = "runner"; }; actual = mkJobPatched { key = "test"; pipelineName = "test"; - job = { - cache = { - name = "some"; - paths = [ "this" ]; - }; - variables = { - BASH = toString pkgs.bash; - TEST = "work"; - }; - }; + job = {}; nixConfig = { enable = true; enableRunnerCache = true; @@ -194,110 +161,48 @@ ''; } { - name = "handle store paths in variables without nix config"; + name = "ignore store paths in variables with nix disabled"; expected = { - stages = [ "test" ]; - variables = { - EXAMPLE = "empty"; - CURL = toString pkgs.curl; - }; + stages = ["test"]; test = { stage = "test"; - before_script = [ "./init" ]; - script = [ "echo Hello World!" ]; - after_script = [ "./clean" ]; - cache = { - key = "simple"; - paths = [ "~/random/" ]; - }; - variables = { - SAMPLE = "working"; - HELLO = toString pkgs.hello; - }; + variables."TEST" = "${pkgs.hello}"; }; }; - actual = (mkPipeline { - name = "test"; - nixConfig.enable = false; - pipeline = { - stages = [ "test" ]; - variables = { - EXAMPLE = "empty"; - CURL = toString pkgs.curl; - }; - jobs.test = { - stage = "test"; - before_script = [ "./init" ]; - script = [ "echo Hello World!" ]; - after_script = [ "./clean" ]; - cache = { - key = "simple"; - paths = [ "~/random/" ]; - }; - variables = { - SAMPLE = "working"; - HELLO = toString pkgs.hello; + actual = + (mkPipeline { + name = "test"; + nixConfig.enable = false; + pipeline = { + stages = ["test"]; + jobs.test = { + stage = "test"; + variables."TEST" = "${pkgs.hello}"; }; }; - }; - }).finalConfig; + }).finalConfig; } { - name = "handle store paths in variables with nix config"; + # 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 = { - stages = [ "test" ]; variables = { - EXAMPLE = "empty"; + HELLO = "world"; CURL = toString pkgs.curl; }; - test = { - stage = "test"; - before_script = [ "source setup_nix_ci \"gitlab-ci:pipeline:test:job-deps:test\"" "./init" ]; - script = [ "echo Hello World!" ]; - after_script = [ "./clean" "finalize_nix_ci" ]; - cache = [{ - key = "simple"; - paths = [ "~/random/" ]; - }{ - key = "random"; - paths = [ ".nix-cache/" ]; - }]; - variables = { - SAMPLE = "working"; - HELLO = toString pkgs.hello; - NIX_CI_CACHE_STRATEGY = "runner"; - }; - }; }; - actual = (mkPipeline { - name = "test"; - nixConfig = { - enable = true; - enableRunnerCache = true; - runnerCacheKey = "random"; - }; - pipeline = { - stages = [ "test" ]; - variables = { - EXAMPLE = "empty"; - CURL = toString pkgs.curl; - }; - jobs.test = { - stage = "test"; - before_script = [ "./init" ]; - script = [ "echo Hello World!" ]; - after_script = [ "./clean" ]; - cache = { - key = "simple"; - paths = [ "~/random/" ]; - }; + actual = + (mkPipeline { + name = "test"; + nixConfig.enable = true; + pipeline = { variables = { - SAMPLE = "working"; - HELLO = toString pkgs.hello; + HELLO = "world"; + CURL = toString pkgs.curl; }; + jobs = {}; }; - }; - }).finalConfig; + }).finalConfig; } ]; }; diff --git a/tests/modules_test.nix b/tests/modules_test.nix index e134293..0bd19c6 100644 --- a/tests/modules_test.nix +++ b/tests/modules_test.nix @@ -10,9 +10,17 @@ simplePipeline = cilib.mkCI { pipelines."test" = { stages = ["test"]; + variables = { + EXAMPLE = "empty"; + CURL = toString pkgs.curl; + }; jobs."test" = { stage = "test"; script = ["echo hello world"]; + variables = { + SAMPLE = "working"; + HELLO = toString pkgs.hello; + }; }; }; }; @@ -30,21 +38,29 @@ (cilib.mkCI {}).packages; } { - name = "simple pipeline"; + name = "simple pipeline final config"; expected = { stages = [".pre" "test" ".post"]; + variables = { + EXAMPLE = "empty"; + CURL = toString pkgs.curl; + }; "test" = { image = "$NIX_CI_IMAGE"; stage = "test"; before_script = ["source setup_nix_ci \"gitlab-ci:pipeline:test:job-deps:test\""]; script = ["echo hello world"]; after_script = ["finalize_nix_ci"]; + variables = { + SAMPLE = "working"; + #HELLO = toString pkgs.hello; + }; }; }; actual = simplePipeline.pipelines."test".finalConfig; } { - name = "simple pipeline yaml"; + name = "simple pipeline json"; type = "script"; script = let package = simplePipeline.packages."gitlab-ci:pipeline:test"; @@ -56,25 +72,23 @@ assert_file_contains ${package} 'gitlab-ci:pipeline:test:job-deps:test' assert_file_contains ${package} 'finalize_nix_ci' assert_file_contains ${package} 'echo hello world' + assert_file_contains ${package} '"EXAMPLE":"empty"' + assert_file_contains ${package} '"SAMPLE":"working"' + assert_file_contains ${package} '"CURL":"/nix/store/.*-curl-.*"' ''; } { - name = "dont fail on store paths"; + name = "simple pipeline deps drv"; type = "script"; script = let - package = - (cilib.mkCI { - pipelines."test" = { - variables.EXAMPLE = "${pkgs.hello}"; - }; - }).packages."gitlab-ci:pipeline:test"; + package = simplePipeline.packages."gitlab-ci:pipeline:test:job-deps:test"; in # sh '' ${ntlib.helpers.path [pkgs.gnugrep]} ${ntlib.helpers.scriptHelpers} - assert_file_contains ${package} '[".pre",".post"]' - assert_file_contains ${package} '"EXAMPLE":"/nix/store/.*-hello-.*"' + assert_file_contains ${package} ':$PATH' + assert_file_contains ${package} 'HELLO="/nix/store/.*-hello-.*"' ''; } ];