Compare commits

..

133 commits

Author SHA1 Message Date
097f775cff Merge branch 'typo' into 'main'
docs: fix Soonix URL in README.md

See merge request TECHNOFAB/nix-gitlab-ci!16
2025-12-16 20:26:09 +01:00
asimon
139912d9c6 docs: fix Soonix URL in README.md 2025-12-16 19:12:06 +01:00
8f88a53b54
chore: bump version 2025-12-11 10:17:52 +01:00
555ae3de29
chore: update flakes 2025-12-05 20:21:26 +01:00
8eadfb56ba
fix(modules): fold was deprecated, replace with foldr 2025-12-05 20:16:37 +01:00
8a77208ebe
chore: bump version 2025-12-03 21:02:46 +01:00
1e9ddff300
fix(modules/job): fix variables with nix store paths getting dropped 2025-12-03 20:47:39 +01:00
59f8bd169a
chore: bump version 2025-12-02 15:12:28 +01:00
97fb4fafc3
fix(jobPatched): handle non-nix jobs correctly
fix mkJobPatched removing `cache` and `variables` from non-nix jobs

See !15 for more
2025-12-02 15:10:35 +01:00
1c9e7c77c5
chore: add test and docs for handling nix store paths in global variables 2025-12-02 15:09:27 +01:00
Skryta Istota
96e6fe59bf
ci: fix oci image used for dog fooding & forks 2025-12-02 14:31:27 +01:00
Skryta Istota
d0662e3185
fix(helpers): use builtin nix store location indicator 2025-12-02 14:30:54 +01:00
524bdf9cdc
chore: bump version 2025-11-13 21:44:28 +01:00
f5181b7b61
fix(sandbox_helper): fix comparisons, rename TMPDIR variable, add help
1. fixes comparisons with true for flag variables
2. renames TMPDIR to NGCI_TMPDIR so it doesn't interfere with the
   standardized TMPDIR var (and at some point accidentally deleting /tmp)
3. add small help message when invalid arg/param is passed
4. run `git add .` on copied git repo in /tmp so staged files stay
   staged there aswell
2025-11-13 21:40:24 +01:00
afe1e02310
fix(job): use unmodified job for mkJobRun
otherwise it tries to run "setup_nix_ci" etc. when running locally,
which doesn't make sense here
2025-11-13 21:39:38 +01:00
fa33f6e0b7
chore: alias original pipeline source & document component issue
Closes #27
2025-10-09 14:04:21 +02:00
7cb73d2319
chore: bump version 2025-10-06 17:56:57 +02:00
5e39c4fbcc
Merge branch 'feat/v3' 2025-10-06 17:54:43 +02:00
046656458b
chore: remove old files in preparation for rewrite 2025-10-06 17:53:51 +02:00
d88ada2c41
chore: bump version 2025-09-25 14:50:24 +02:00
0cca02f442
feat: implement all (?) ci yaml keywords 2025-09-25 14:49:46 +02:00
e752f71dd1
docs: use svg logo, add style.css and fix sitemap 2025-09-25 13:18:06 +02:00
428afaf603
chore(repo): update nixmkdocs 2025-09-05 09:02:42 +02:00
00cf5b83c6
chore: bump version 2025-09-04 10:29:56 +02:00
2a0a3f5881
chore(ci): try setting ssl env vars in the test directly (cuz pure mode) 2025-09-04 08:39:37 +02:00
5e2ae29660
chore: better solution for handling store paths in variables 2025-09-04 08:34:25 +02:00
31f0e4ea13
fix(jobPatched): fix variables not being unset if all contain store paths
the goal was to remove "variables" when it's empty, but this resulted in
the original value being used if all of the variables contained store
paths. This is not supposed to happen and thus fixed with this.
2025-09-03 15:17:51 +02:00
a076f0048a
chore(CI): modify cache_files and add ssl ca certs to test job 2025-09-03 14:29:56 +02:00
cf04bf5357
fix(sandbox_helper): fix TMPDIR being initialized too late and thus removing /tmp 2025-09-03 14:14:25 +02:00
4d824900d4
fix(module): default image to $NIX_CI_IMAGE 2025-09-03 10:46:47 +02:00
6cd05e503a
fix(ci): only specify component version once 2025-09-03 10:19:11 +02:00
0c6949f585 Merge branch 'patch-1' into 'main'
feat: customizable CI stages

See merge request TECHNOFAB/nix-gitlab-ci!13
2025-07-09 11:20:38 +02:00
Alessio Caiazza
625fe732b5 feat: customizable CI stages 2025-07-08 09:30:02 +02:00
f121b10dc9 Merge branch 'testing' into 'main'
Tests

Closes #23

See merge request TECHNOFAB/nix-gitlab-ci!12
2025-06-05 13:57:13 +02:00
69e0f7a419 chore(flake): update nixtest 2025-06-03 12:23:51 +02:00
df35d61170 fix(sandbox_helper): remove '' 2025-06-02 22:15:44 +02:00
95d7a950b9 ci: update test snapshots 2025-05-31 23:08:35 +02:00
2f197d2c50 chore: split everything up into their own files & add a bunch of tests 2025-05-31 21:29:54 +02:00
b309fb59db Merge branch 'main' into testing 2025-05-31 16:06:47 +02:00
f9c009c450 feat: improve running jobs locally by adding a simple sandbox 2025-05-31 15:40:53 +02:00
dca2d724c1 fix(flakeModule): use default shell for stdenvMinimal for max compatibility 2025-05-11 16:19:31 +02:00
8e50828a2e ci: add nixtest job 2025-05-10 20:00:30 +02:00
93739ab27c tests: try testing with nixtest 2025-05-10 19:48:20 +02:00
11537ae271 fix(flakeModule): use bash for stdenvMinimal
fixes #24
2025-05-10 19:45:10 +02:00
9ee4ad02b8 Merge branch 'feat/v2' into 'main'
feat: v2

Closes #6, #7, #10, #13, #17, #19, #20, and #21

See merge request TECHNOFAB/nix-gitlab-ci!10
2025-05-03 21:36:37 +02:00
cf80010d07 docs: write docs & improve tooling
Squashed commit of the following:

commit 86eadd3ec42b7bce0dc5716d65798af95d0d8cbc
Author: technofab <admin@technofab.de>
Date:   Fri May 2 17:10:33 2025 +0200

docs(README): fix built with nix badge

commit f50057da69e89974f17bc37b5e140b2ef9f817f6
Author: technofab <admin@technofab.de>
Date:   Fri May 2 16:09:00 2025 +0200

ci: change back rule so docs only get deployed on main

commit ce02b043f4bd83c36285e5620e71701fc3bcc998
Author: technofab <admin@technofab.de>
Date:   Fri May 2 16:08:10 2025 +0200

docs: write docs and improve formatter etc.

commit e996b23cf877d8021759b782aa5996f5e2bf12ac
Author: technofab <admin@technofab.de>
Date:   Fri May 2 16:07:56 2025 +0200

docs: update README

commit 650f97b5608c32cf6cf66cc3fdd0965dc42e4860
Author: technofab <admin@technofab.de>
Date:   Wed Apr 23 21:05:14 2025 +0200

docs: add favicon

commit 67e1bfecbcaf0b8f7dad2eecfaccf774cc560874
Author: technofab <admin@technofab.de>
Date:   Wed Apr 23 20:53:44 2025 +0200

docs: initial setup
2025-05-02 17:30:53 +02:00
fa6c454b14 chore: update nixpkgs 2025-05-02 17:30:53 +02:00
b193df30f4 fix(script): quote NEW_PATHS to preserve newlines
hopefully finally gets rid of spaces which break attic
2025-04-04 22:22:35 +02:00
9cb54b33e8 fix: finalize_nix_ci echo added space to last derivation, fixed with -n 2025-04-04 21:08:36 +02:00
7cbd273de7 fix(image): switch from busybox to coreutils
busybox' diff took precedence over diffutils' which broke attic because
of spaces in the output (/store paths did not match the valid regex anymore)
2025-04-04 20:30:56 +02:00
8dc2e7d772 chore: slim down job-deps as much as possible 2025-04-04 20:30:56 +02:00
14530f8e9e
fix: update flake inputs to be able to fix docker image archs being swapped 2025-04-03 15:40:36 +02:00
a458a21c7b fix(scripts): remove nix substitutions from shell script 2025-03-23 14:55:40 +01:00
2bed4190a4 chore!: remove deprecated template 2025-03-23 14:36:05 +01:00
d734853223 chore(scripts): improve cache strategy handling, see #21 2025-03-22 21:50:33 +01:00
1e978a3edf refactor(flake): move setup and finalize script to separate files 2025-03-22 21:48:54 +01:00
62e465c094 fix(template): overriding default variables in child pipeline 2025-03-07 17:32:49 +01:00
6fa2806219 docs(readme): update usage infos 2025-03-04 16:23:51 +01:00
f1b8b5a210 refactor(template): get rid of rules and work around limitations in a new way 2025-03-04 16:12:51 +01:00
a5fba6d27d chore(flake): collapse nix ci top level section again for less clutter 2025-03-04 16:05:33 +01:00
dab96d0acd fix(module): rename variable 2025-03-04 15:23:46 +01:00
a63376edf1 chore: rename env variables back to non-_ versions
for testing, CI template still needs adjustments
2025-03-04 14:30:06 +01:00
060d8fad47 chore(module): slim down pipeline yaml generation even more 2025-02-28 12:53:17 +01:00
7a40a68a10 chore(template): skip checking if pipeline exists, just fail if not 2025-02-28 11:54:41 +01:00
36c4fc0fd6 fix(module): prevent parameter expansion when generating pipeline config 2025-02-27 11:19:50 +01:00
fa6c098e02 chore: improve nix-ci:build build time by using only builtins.toJSON
removes dependency on remarshal, pkgs.formats.json uses jq to pretty
print so we just use builtins.toJSON directly
2025-02-27 10:52:47 +01:00
85431f78aa chore: improve "default" handling & caching
add new env variables to configure which CI source gets mapped to default
add logic to check if pipeline exists in flake, else build "default"
2025-02-22 21:57:25 +01:00
55f90b4261 fix(ci): update artifact name in trigger job aswell 2025-02-21 22:53:00 +00:00
ebc70d5c18 fix(ci): fix artifact path 2025-02-21 21:26:28 +00:00
244142274d fix(ci): build correct package and hopefully handle cache issues 2025-02-21 18:52:55 +01:00
7569fcd086 fix(ci): work around gitlab's variable substitution limitations 2025-02-21 18:24:23 +01:00
b4071d4171 fix(ci): image seems quite important ngl 2025-02-21 16:36:50 +01:00
9d28984261 fix(ci): install buildah in the correct job 2025-02-21 16:21:11 +01:00
b0d24f753c fix(image): fix digest being different for every arch aswell 2025-02-21 16:04:59 +01:00
786abd917c fix: use new format of specifying version 2025-02-21 12:34:30 +01:00
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
016e6c9dc7
chore!: rename NIX_CI_SKIP_CACHE → NIX_CI_FORCE_BUILD
closes #16
2025-02-15 21:35:36 +01:00
1101989255 fix(ci-component): honor NIX_CI_DISABLE_CACHE correctly 2024-11-30 17:57:31 +01:00
553b829af0 chore(README): bump component version 2024-11-30 15:13:22 +01:00
f229219a26 Merge branch 'chore/use-legacy-packages' into 'main'
chore(module): add packages to legacyPackages instead

Closes #12

See merge request TECHNOFAB/nix-gitlab-ci!7
2024-11-30 14:11:36 +00:00
012efc7aad Merge branch 'chore/update-flake-and-switch-attic' into 'main'
chore: update flake inputs and use attic-client from nixpkgs

Closes #15

See merge request TECHNOFAB/nix-gitlab-ci!9
2024-11-27 14:41:01 +00:00
a9075917cc Merge branch 'chore/nix-copy-from-stdin' into 'main'
chore(image): pass all store paths at once via stdin to nix copy

See merge request TECHNOFAB/nix-gitlab-ci!8
2024-11-27 13:15:50 +00:00
90a4079200 chore(image): pass all store paths at once via stdin to nix copy 2024-11-27 13:15:50 +00:00
026a7549df chore: update flake inputs and use attic-client from nixpkgs 2024-11-26 20:22:11 +01:00
a85c4e49fe chore: add additional NIX_CONFIG var & reformat
closes #11
2024-11-26 14:12:33 +01:00
856924acdf chore(module): add packages to legacyPackages instead 2024-11-26 13:31:04 +01:00
50f0184a7b chore(LICENSE): use markdown for better readability
[skip ci]
2024-10-30 16:11:19 +00:00
691a0aac79 chore: add LICENSE
[skip ci]
2024-10-30 16:10:18 +00:00
25e5b44a6d feat(module): improve ability to run jobs locally
adds the correct PATH and environment variables to run it locally
similar to how it works in CI. Also split up the before_script, script
and after_script with simple echo's inbetween for easier debugging
2024-10-13 18:34:07 +02:00
532fb8002c fix(module): append "finalize_nix_ci" to after_script, not prepend 2024-10-13 18:32:47 +02:00
81b497d976 chore(README): bump component version 2024-10-13 16:35:14 +02:00
67d75bd167 docs(README): document running jobs locally
[skip ci]
2024-10-13 15:50:18 +02:00
a47ec8cbeb chore(CI): use image built in parent pipeline for dogfooding here aswell
remove retries
2024-10-08 12:33:31 +02:00
546eea3006 Merge branch 'ci/improve-dogfood' into 'main'
ci: improve dogfooding by using the CI built images directly

See merge request TECHNOFAB/nix-gitlab-ci!6
2024-10-07 16:59:30 +00:00
a22258583d ci: improve dogfooding by using the CI built images directly 2024-10-07 16:59:30 +00:00
d04325807c Merge branch 'fix/nix-copy-verbosity' into 'main'
fix(basic-image): append ^* to .drv entries to prevent warnings

Closes #5

See merge request TECHNOFAB/nix-gitlab-ci!5
2024-10-07 12:32:24 +00:00
ec279ae31e fix(basic-image): append ^* to .drv entries to prevent warnings
instead print a "." without newline to be able to see progress
2024-10-06 19:19:33 +02:00
28072631e7 chore(README): bump component version 2024-10-02 21:40:26 +02:00
fdb6193ef1 fix(utils): migrate utils to the new syntax aswell 2024-10-02 18:26:14 +02:00
6448bf5916 chore(README): bump component version 2024-09-16 09:41:08 +00:00
0f62d5e822 fix: allow jobs to omit the "nix" option 2024-09-16 09:31:35 +00:00
854dfb6a90 chore(README): bump component version
[skip ci]
2024-09-13 18:44:37 +00:00
edaf08205b Merge branch 'feat/improve-caching' into 'main'
feat: add support for Gitlab CI cache

Closes #2

See merge request TECHNOFAB/nix-gitlab-ci!4
2024-09-13 18:43:56 +00:00
78e6c5e278 feat: improve caching 2024-09-13 18:43:56 +00:00
39748cb380 chore(README): bump component version
[skip ci]
2024-09-13 17:55:05 +00:00
a2a7f7c4ed chore(CI): build image on tag & tag images with short sha instead of date 2024-09-13 17:54:24 +02:00
97f49cbdf6 chore: add treefmt and format files 2024-09-13 17:22:38 +02:00
f30adf88d3 Merge branch 'feat/cicd-component' into 'main'
feat: add CI Component template

See merge request TECHNOFAB/nix-gitlab-ci!3
2024-09-11 15:03:43 +00:00
4e039a6b92 feat: add CI Component template 2024-09-11 15:03:42 +00:00
533bd2eef5 feat: add assertion to check if a job's stage exists 2024-09-10 13:07:48 +00:00
e3b35ec8ae feat: add support for nix store paths in variables
by exporting them at runtime and removing them from the pipeline
definition itself
closes #3
2024-09-10 12:46:13 +00:00
ed80957884 docs(README): adjust input url for new lib flake 2024-07-28 14:53:15 +02:00
6bde7a5dfa Merge branch 'feat/split-flake' into 'main'
feat: split lib and utils into separate flake

See merge request TECHNOFAB/nix-gitlab-ci!2
2024-07-28 12:51:14 +00:00
f361878e13 feat: split lib and utils into separate flake 2024-07-28 12:51:14 +00:00
c272bfd812 fix: allow rules to contain attrs 2024-03-23 21:09:05 +01:00
d26ead5f0b fix: typo 2024-03-23 21:07:26 +01:00
b1117dd620 fix(module): fix before_script not getting appended if it exists
[skip ci]
2024-03-17 21:10:10 +01:00
f460960ce6 chore(utils): fix before_script getting overwritten and add collapsible sections 2024-03-17 18:26:45 +01:00
93baeca411 chore: update gitlab-ci.yml and only load job deps if name was passed to setup_nix_ci 2024-03-17 18:16:34 +01:00
12e55ad0b7 chore: add grep to images 2024-03-17 16:53:03 +01:00
85e18c5766 Merge branch 'cache' into 'main'
feat: caching support

See merge request TECHNOFAB/nix-gitlab-ci!1
2024-03-17 15:44:22 +00:00
3a05d7a128 feat: caching support 2024-03-17 15:44:22 +00:00
426d89702a fix(utils): create ~/.ssh/known_hosts if it does not exist 2024-02-03 16:18:02 +01:00
262729e9bb fix: add most gitlab options 2024-01-27 13:06:34 +01:00
3161819c57 fix: rules are a list of attrs 2024-01-26 15:13:17 +01:00
7cd9c571fe feat: add utilities 2024-01-26 14:55:03 +01:00
3413fc3639 fix: add artifacts option 2024-01-26 12:25:59 +01:00
1b6ecec5c1 fix(image): use nix-flakes to get the newest nix version
nix-unstable-static is outdated? (2.10)
2024-01-14 18:33:54 +01:00
ff363cb165 fix(gitlab-ci-config): filter out any unset (null) values 2024-01-14 18:13:26 +01:00
77fded1940 fix: repository name must be lowercase
add some more job options
2024-01-14 18:02:05 +01:00
f3485837ce fix: add when and start_in option 2024-01-14 17:17:24 +01:00
1b963cb641 chore: add README 2024-01-14 17:09:23 +01:00
0df36ad437 chore: initial commit 2024-01-14 16:45:07 +01:00
23 changed files with 827 additions and 77 deletions

View file

@ -45,10 +45,15 @@ deploy:image:
\ localhost/nix-ci docker://${CI_REGISTRY_IMAGE}/nix-ci:${CI_COMMIT_TAG}\nfi\n"
stage: build-images
include:
- component: $CI_SERVER_FQDN/$CI_PROJECT_PATH/nix-gitlab-ci@$CI_COMMIT_SHA@$CI_COMMIT_SHORT_SHA
- component: $CI_SERVER_FQDN/$CI_PROJECT_PATH/nix-gitlab-ci@$CI_COMMIT_SHORT_SHA
inputs:
cache_files:
- flake.*
- nix/repo/ci.nix
version: $CI_COMMIT_SHORT_SHA
stages:
- build-images
- build
- 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
[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,6 +2,13 @@
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`
- Type: `string`

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 40 KiB

1
docs/images/logo.svg Executable file
View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="240" height="240" fill="none"><rect width="240" height="240" fill="url(#a)" rx="27"/><path fill="#E24329" d="M82.1 61.8c1 0 2 .4 2.7 1 .8.6 1.4 1.4 1.6 2.4l12.2 37.1h49.1l12.1-37.1c.3-1 .9-1.8 1.6-2.4a4.8 4.8 0 0 1 5.5-.3c.9.5 1.5 1.3 1.9 2.2l18 47 .1.4a33.4 33.4 0 0 1-11 38.5l-27.6 20.7-13.6 10.3-8.2 6.2a5.6 5.6 0 0 1-6.7 0l-8.3-6.2L98 171.3l-27.4-20.5-.2-.1A33.4 33.4 0 0 1 59.3 112l.2-.5 18-46.9a4.7 4.7 0 0 1 4.6-3Zm22.5 48c-7.5 0-11.2 3.8-11.2 11.3v21.6c0 7.5 3.7 11.3 11.2 11.3h16.6l5-3.8V144h-21c-.5 0-.7-.3-.7-.8v-22.6c0-.5.2-.7.7-.7h21v-6.2l-5-3.9h-16.6Zm29.8 0V154h11.1v-44.2h-11.1Z"/><path fill="#FC6D26" d="M187 112a33.4 33.4 0 0 1-11.1 38.6v.1l-27.6 20.6-25-18.9 2.9-2.2v-.2l8.2-6.2V154h11.1v-18.6l17-13c7.2-5.3 15.5-9 24.3-10.8l.1.5Z"/><path fill="#FCA326" d="m148.3 171.3-13.6 10.3-8.2 6.2a5.6 5.6 0 0 1-6.7 0l-8.3-6.2L98 171.3l22.9-17.3h.3l2-1.6 25 19Z"/><path fill="#FC6D26" d="M59.5 111.6c8.7 1.8 17 5.5 24.1 10.9l9.8 7.3v13c0 7.4 3.7 11.2 11.2 11.2H121l-23 17.3-27.3-20.5-.2-.1A33.4 33.4 0 0 1 59.3 112l.2-.5ZM112 144h-7c-.4 0-.6-.3-.6-.8v-5l7.6 5.8Z"/><path fill="#FC6D26" d="m209.9 159.2-12.4 22-29.5-.1 14.6 25.5-6.2 10.8h-12.8l-20.1-35 2.1-1.6 12-9 16.8-12.6H210Zm-156-50v.2l-.2.5a39.4 39.4 0 0 0 5.2 37.6L41 178.3l-12.8-21.7L43 131H13.7l-6.3-10.9 6.4-11.1 40.1.1Zm110.5 50-2.5 1.9 2.5-1.9ZM149 48l14.7-25.4h12.6l6.4 11L169 56.9c-1.5-.7-3.2-1-4.9-1h-.4c-2.2 0-4.3.9-6 2.2h-.1v.1a10.8 10.8 0 0 0-3.6 5.2l-7.7 23.8L109 22.6l25.3-.3L149 48Z"/><path fill="url(#b)" d="m209.9 159.2-12.4 22-29.5-.1 14.6 25.5-6.2 10.8h-12.8l-20.1-35 2.1-1.6 12-9 16.8-12.6H210Zm-156-50v.2l-.2.5a39.4 39.4 0 0 0 5.2 37.6L41 178.3l-12.8-21.7L43 131H13.7l-6.3-10.9 6.4-11.1 40.1.1Zm110.5 50-2.5 1.9 2.5-1.9ZM149 48l14.7-25.4h12.6l6.4 11L169 56.9c-1.5-.7-3.2-1-4.9-1h-.4c-2.2 0-4.3.9-6 2.2h-.1v.1a10.8 10.8 0 0 0-3.6 5.2l-7.7 23.8L109 22.6l25.3-.3L149 48Z"/><path fill="#E24329" d="m94.3 176 13.6 10.3 9 6.8 14 24.3-25.1.3L91 192l-14.7 25.4H63.9l-6.5-11 21-36.2-6.1-10.8 22 16.6Zm76.2-21.4-2.7 2 2.8-2Zm-106-9.6a33.3 33.3 0 0 0 .5.5l-.4-.5Zm147.2-61.6L197 109h29.3l6.3 10.9-6.4 11h-31.6c1.2-7 .5-14.2-2-20.9l-.3-.5-8.3-21.8 15-25.9 12.7 21.7Zm-25 28.2.2.5a34.5 34.5 0 0 1 1.5 18.7c1.3-6.3.8-12.7-1.5-18.7l-.1-.5-6.7-17.3 6.7 17.3Zm-89.6-53h30l12.7 22h-42L92 63.4c-.6-2.1-1.8-4-3.5-5.3l-.4-.3a10.8 10.8 0 0 0-5.3-2H82c-2 0-4 .5-5.8 1.6-2 1.2-3.5 3-4.3 5v.1l-7 18H30l12.4-21.9H72L57.3 33.3l6.2-10.8h12.8l20.8 36.2Z"/><path fill="url(#c)" d="m94.3 176 13.6 10.3 9 6.8 14 24.3-25.1.3L91 192l-14.7 25.4H63.9l-6.5-11 21-36.2-6.1-10.8 22 16.6Zm76.2-21.4-2.7 2 2.8-2Zm-106-9.6a33.3 33.3 0 0 0 .5.5l-.4-.5Zm147.2-61.6L197 109h29.3l6.3 10.9-6.4 11h-31.6c1.2-7 .5-14.2-2-20.9l-.3-.5-8.3-21.8 15-25.9 12.7 21.7Zm-25 28.2.2.5a34.5 34.5 0 0 1 1.5 18.7c1.3-6.3.8-12.7-1.5-18.7l-.1-.5-6.7-17.3 6.7 17.3Zm-89.6-53h30l12.7 22h-42L92 63.4c-.6-2.1-1.8-4-3.5-5.3l-.4-.3a10.8 10.8 0 0 0-5.3-2H82c-2 0-4 .5-5.8 1.6-2 1.2-3.5 3-4.3 5v.1l-7 18H30l12.4-21.9H72L57.3 33.3l6.2-10.8h12.8l20.8 36.2Z"/><defs><linearGradient id="b" x1="181.2" x2="141" y1="114.6" y2="45.1" gradientUnits="userSpaceOnUse"><stop stop-color="#699AD7"/><stop offset=".2" stop-color="#7EB1DD"/><stop offset="1" stop-color="#7EBAE4"/></linearGradient><linearGradient id="c" x1="151.1" x2="191.8" y1="167.7" y2="98.7" gradientUnits="userSpaceOnUse"><stop stop-color="#415E9A"/><stop offset=".2" stop-color="#4A6BAF"/><stop offset="1" stop-color="#5277C3"/></linearGradient><radialGradient id="a" cx="0" cy="0" r="1" gradientTransform="rotate(90 0 120) scale(120)" gradientUnits="userSpaceOnUse"><stop offset=".5" stop-color="#091A3D"/><stop offset="1" stop-color="#000819"/></radialGradient></defs></svg>

After

Width:  |  Height:  |  Size: 3.6 KiB

View file

@ -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.

15
docs/style.css Normal file
View file

@ -0,0 +1,15 @@
.md-header__button.md-logo {
margin: 0;
padding-top: .2rem;
padding-bottom: .2rem;
}
[dir="ltr"] .md-header__title {
margin-left: 0;
}
.md-header__button.md-logo img,
.md-header__button.md-logo svg {
height: 2rem;
}

12
flake.lock generated
View file

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

View file

@ -1 +1 @@
3.0.0-alpha.1
3.1.2

View file

@ -2,7 +2,21 @@
pkgs,
lib,
} @ args: let
inherit (lib) types isAttrs filterAttrs mapAttrs mkOption mkOptionType isType literalExpression pipe;
inherit
(lib)
types
isAttrs
filterAttrs
mapAttrs
mkOption
mkOptionType
isType
literalExpression
pipe
hasInfix
concatMapAttrs
optionalAttrs
;
in rec {
prepend = key: arr: job: {
${key} = arr ++ (job.${key} or []);
@ -33,10 +47,10 @@ in rec {
# filter job's variables to either only those containing store paths
# or those that do not
filterJobVariables = nix: job:
lib.concatMapAttrs (
filterJobVariables = shouldContain: job:
concatMapAttrs (
name: value:
lib.optionalAttrs ((lib.hasInfix "/nix/store/" value) == nix) {
optionalAttrs ((hasInfix builtins.storeDir value) == shouldContain) {
${name} = value;
}
)
@ -70,7 +84,7 @@ in rec {
unsetOr = typ:
(types.either unsetType typ)
// {
inherit (typ) description;
inherit (typ) description getSubOptions;
};
mkUnsetOption = opts:
mkOption (opts
@ -79,6 +93,14 @@ in rec {
default = opts.default or unset;
defaultText = literalExpression "unset";
});
eitherWithSubOptions = typ_one: typ_two:
(types.either typ_one typ_two)
// {
getSubOptions =
if (typ_one.getSubOptions "test" != {})
then typ_one.getSubOptions
else typ_two.getSubOptions;
};
filterUnset = value:
if builtins.isAttrs value && !builtins.hasAttr "_type" value

View file

@ -11,13 +11,13 @@ in
pipelineName,
nixConfig,
}:
job
// (optionalAttrs nixConfig.enable (
(prependToBeforeScript ["source setup_nix_ci \"gitlab-ci:pipeline:${pipelineName}:job-deps:${key}\""] job)
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)
))
// optionalAttrs nixConfig.enable (
(let
// (let
variables =
(filterJobVariables false job)
// optionalAttrs nixConfig.enableRunnerCache {
@ -40,4 +40,3 @@ in
optionalAttrs (cache != []) {
inherit cache;
})
)

View file

@ -4,7 +4,7 @@
...
}: let
inherit (lib) mkOption types filterAttrs;
inherit (cilib.helpers) filterUnset mkUnsetOption;
inherit (cilib.helpers) filterUnset mkUnsetOption eitherWithSubOptions;
in rec {
jobConfigSubmodule = {pipelineConfig, ...}: {
options = {
@ -53,42 +53,539 @@ in rec {
# GITLAB OPTIONS
#
gitlabOptions = {
stage = mkOption {
# see https://docs.gitlab.com/ci/yaml/
after_script = mkUnsetOption {
type = types.listOf types.str;
description = ''
Pipeline stage to run this job in.
Override a set of commands that are executed after job.
[Docs](https://docs.gitlab.com/ci/yaml/#after_script)
'';
type = types.str;
};
image = mkUnsetOption {
allow_failure = mkUnsetOption {
type = eitherWithSubOptions types.bool (types.submodule {
options = {
exit_codes = mkUnsetOption {
type = types.either types.number (types.listOf types.number);
description = ''
Use `allow_failure.exit_codes` to control when a job should be allowed to fail.
The job is `allow_failure = true` for any of the listed exit codes, and `allow_failure = false` for any other exit code.
'';
};
};
});
description = ''
Allow job to fail. A failed job does not cause the pipeline to fail.
[Docs](https://docs.gitlab.com/ci/yaml/#allow_failure)
'';
};
artifacts = mkUnsetOption {
# TODO: can be used in pipeline.default aswell
type = types.submodule {
options = {
paths = mkUnsetOption {
type = types.listOf types.str;
description = ''
Paths are relative to the project directory (`$CI_PROJECT_DIR`) and cant directly link outside it.
'';
};
excludes = mkUnsetOption {
type = types.listOf types.str;
description = ''
Use `exclude` to prevent files from being added to an artifacts archive.
'';
};
expire_in = mkUnsetOption {
type = types.str;
description = ''
Use `expire_in` to specify how long [job artifacts](https://docs.gitlab.com/ci/jobs/job_artifacts/) are stored before they expire and are deleted.
'';
};
expose_as = mkUnsetOption {
type = types.str;
description = ''
Use the `expose_as` keyword to [expose artifacts in the merge request UI](https://docs.gitlab.com/ci/jobs/job_artifacts/#link-to-job-artifacts-in-the-merge-request-ui).
'';
};
name = mkUnsetOption {
type = types.str;
description = ''
Use the `name` keyword to define the name of the created artifacts archive. You can specify a unique name for every archive.
'';
};
public = mkUnsetOption {
type = types.bool;
description = ''
Use `public` to determine whether the job artifacts should be publicly available.
'';
};
access = mkUnsetOption {
type = types.enum [
"all"
"developer"
"maintainer"
"none"
];
description = ''
Use `access` to determine who can access the job artifacts from the GitLab UI or API.
This option does not prevent you from forwarding artifacts to downstream pipelines.
'';
};
reports = mkUnsetOption {
type = types.attrs;
description = ''
Use `reports` to collect artifacts generated by included templates in jobs.
'';
};
untracked = mkUnsetOption {
type = types.bool;
description = ''
Use `untracked` to add all Git untracked files as artifacts (along with the paths defined in `paths`).
`untracked` ignores configuration in the repositorys .gitignore, so matching artifacts in .gitignore are included.
'';
};
when = mkUnsetOption {
type = types.enum [
"on_success"
"on_failure"
"always"
];
description = ''
Use `when` to upload artifacts on job failure or despite the failure.
'';
};
};
};
description = ''
List of files and directories to attach to a job on success.
[Docs](https://docs.gitlab.com/ci/yaml/#artifacts)
'';
};
before_script = mkUnsetOption {
type = types.listOf types.str;
description = ''
Override a set of commands that are executed before job.
[Docs](https://docs.gitlab.com/ci/yaml/#before_script)
'';
};
cache = mkUnsetOption {
# could be more granular
type = types.either (types.listOf types.attrs) types.attrs;
description = ''
List of files that should be cached between subsequent runs.
[Docs](https://docs.gitlab.com/ci/yaml/#cache)
'';
};
coverage = mkUnsetOption {
type = types.str;
description = ''
Code coverage settings for a given job.
[Docs](https://docs.gitlab.com/ci/yaml/#coverage)
'';
};
dast_configuration = mkUnsetOption {
type = types.attrs;
description = ''
Use configuration from DAST profiles on a job level.
[Docs](https://docs.gitlab.com/ci/yaml/#dast_configuration)
'';
};
dependencies = mkUnsetOption {
type = types.listOf types.str;
description = ''
Restrict which artifacts are passed to a specific job by providing a list of jobs to fetch artifacts from.
[Docs](https://docs.gitlab.com/ci/yaml/#dependencies)
'';
};
environment = mkUnsetOption {
type = eitherWithSubOptions types.str (types.submodule {
options = {
name = mkUnsetOption {
type = types.str;
example = "production";
description = ''
Set a name for an environment.
'';
};
url = mkUnsetOption {
type = types.str;
example = "https://prod.example.com";
description = ''
Set a URL for an environment.
'';
};
on_stop = mkUnsetOption {
type = types.str;
example = "down";
description = ''
Closing (stopping) environments can be achieved with the `on_stop` keyword defined under `environment`.
It declares a different job that runs to close the environment.
'';
};
action = mkUnsetOption {
type = types.enum ["start" "prepare" "stop" "verify" "access"];
description = ''
Use the `action` keyword to specify how the job interacts with the environment.
'';
};
auto_stop_in = mkUnsetOption {
type = types.str;
description = ''
The `auto_stop_in` keyword specifies the lifetime of the environment.
When an environment expires, GitLab automatically stops it.
'';
};
kubernetes = mkUnsetOption {
type = types.attrs; # no we don't go that deep :D
description = ''
Use the `kubernetes` keyword to configure the
[dashboard for Kubernetes](https://docs.gitlab.com/ci/environments/kubernetes_dashboard/) and
[GitLab-managed Kubernetes resources](https://docs.gitlab.com/user/clusters/agent/managed_kubernetes_resources/)
for an environment.
'';
};
deployment_tier = mkUnsetOption {
type = types.enum [
"production"
"staging"
"testing"
"development"
"other"
];
description = ''
Use the `deployment_tier` keyword to specify the tier of the deployment environment.
'';
};
};
});
description = ''
Name of an environment to which the job deploys.
See the implementation for nested options, or check out the docs:
[Docs](https://docs.gitlab.com/ci/yaml/#environment)
'';
example = {
name = "review/$CI_COMMIT_REF_SLUG";
url = "https://$CI_COMMIT_REF_SLUG.review.example.com";
action = "stop";
auto_stop_in = "1 day";
deployment_tier = "staging";
};
};
extends = mkUnsetOption {
type = types.either types.str (types.listOf types.str);
description = ''
Configuration entries that this job inherits from.
[Docs](https://docs.gitlab.com/ci/yaml/#extends)
'';
};
hooks = mkUnsetOption {
type = types.attrs;
description = ''
Use `hooks` to specify lists of commands to execute on the runner at certain stages of job execution,
like before retrieving the Git repository.
[Docs](https://docs.gitlab.com/ci/yaml/#hooks)
'';
};
identity = mkUnsetOption {
type = types.str;
description = ''
Authenticate with third party services using identity federation.
[Docs](https://docs.gitlab.com/ci/yaml/#identity)
'';
};
id_tokens = mkUnsetOption {
type = types.attrs;
description = ''
Use `id_tokens` to create [ID tokens](https://docs.gitlab.com/ci/secrets/id_token_authentication/) to authenticate with third party services
[Docs](https://docs.gitlab.com/ci/yaml/#id_tokens)
'';
example = {
ID_TOKEN_1.aud = "https://vault.example.com";
ID_TOKEN_2.aud = [
"https://gcp.com"
"https://aws.com"
];
SIGSTORE_ID_TOKEN.aud = "sigstore";
};
};
image = mkOption {
# could be more granular
type = types.either types.str types.attrs;
description = ''
Container/OCI image to use for this job.
!!! warning
Setting this will mess with Nix-GitLab-CI, so be careful and only use for non-nix jobs.
'';
default = "$NIX_CI_IMAGE";
example = {
name = "super/sql:experimental";
entrypoint = [""];
pull_policy = "if-not-present";
docker = {
platform = "arm64/v8";
user = "dave";
};
kubernetes.user = "1001";
};
};
"inherit" = mkUnsetOption {
type = types.submodule {
options = {
default = mkUnsetOption {
type = types.either types.bool (types.listOf types.str);
description = ''
Use `inherit.default` to control the inheritance of [default keywords](https://docs.gitlab.com/ci/yaml/#default).
'';
};
variables = mkUnsetOption {
type = types.either types.bool (types.listOf types.str);
description = ''
Use `inherit.variables` to control the inheritance of [default variables](https://docs.gitlab.com/ci/yaml/#default-variables).
'';
};
};
};
description = ''
Select which global defaults all jobs inherit.
[Docs](https://docs.gitlab.com/ci/yaml/#inherit)
'';
};
interruptible = mkUnsetOption {
type = types.bool;
description = ''
Defines if a job can be canceled when made redundant by a newer run.
[Docs](https://docs.gitlab.com/ci/yaml/#interruptible)
'';
};
manual_confirmation = mkUnsetOption {
type = types.str;
description = ''
Define a custom confirmation message for a manual job.
[Docs](https://docs.gitlab.com/ci/yaml/#manual_confirmation)
'';
};
variables = mkUnsetOption {
type = types.attrsOf types.str;
needs = mkUnsetOption {
# could be done more granular
type = types.listOf (types.either types.str types.attrs);
description = ''
Execute jobs earlier than the stage ordering.
[Docs](https://docs.gitlab.com/ci/yaml/#needs)
'';
};
before_script = mkUnsetOption {
type = types.listOf types.str;
pages = mkUnsetOption {
type = eitherWithSubOptions types.bool (types.submodule {
options = {
publish = mkUnsetOption {
type = types.str;
description = ''
Use `pages.publish` to configure the content directory of a [`pages` job](https://docs.gitlab.com/ci/yaml/#pages).
'';
};
path_prefix = mkUnsetOption {
type = types.str;
description = ''
Use `pages.path_prefix` to configure a path prefix for [parallel deployments](https://docs.gitlab.com/user/project/pages/#parallel-deployments) of GitLab Pages.
'';
};
expire_in = mkUnsetOption {
type = types.str;
description = ''
Use `expire_in` to specify how long a deployment should be available before it expires.
After the deployment is expired, its deactivated by a cron job running every 10 minutes.
'';
};
};
});
description = ''
Upload the result of a job to use with GitLab Pages.
[Docs](https://docs.gitlab.com/ci/yaml/#pages)
'';
};
parallel = mkUnsetOption {
type = eitherWithSubOptions types.number (types.listOf (types.submodule {
options = {
matrix = mkUnsetOption {
type = types.attrs;
description = ''
Use `parallel.matrix` to run a job multiple times in parallel in a single pipeline, but with different variable values for each instance of the job.
'';
};
};
}));
description = ''
How many instances of a job should be run in parallel.
[Docs](https://docs.gitlab.com/ci/yaml/#parallel)
'';
example = {
matrix = [
{
PROVIDER = "aws";
STACK = [
"monitoring"
"app1"
"app2"
];
}
{
PROVIDER = "ovh";
STACK = ["monitoring" "backup" "app"];
}
{
PROVIDER = ["gcp" "vultr"];
STACK = ["data" "processing"];
}
];
};
};
release = mkUnsetOption {
# could be more granular
type = types.attrs;
description = ''
Instructs the runner to generate a [release](https://docs.gitlab.com/user/project/releases/) object.
[Docs](https://docs.gitlab.com/ci/yaml/#release)
'';
};
resource_group = mkUnsetOption {
type = types.str;
description = ''
Limit job concurrency.
[Docs](https://docs.gitlab.com/ci/yaml/#resource_group)
'';
};
retry = mkUnsetOption {
type = eitherWithSubOptions (types.ints.between 0 2) (types.submodule {
options = {
exit_codes = mkUnsetOption {
type = types.either types.int (types.listOf types.int);
description = ''
Use `retry.exit_codes` with `retry.max` to retry jobs for only specific failure cases.
'';
};
when = mkUnsetOption {
type = types.either types.str (types.listOf types.str);
description = ''
Use `retry.when` with `retry.max` to retry jobs for only specific failure cases.
'';
};
max = mkUnsetOption {
type = types.ints.between 0 2;
description = ''
`retry.max` is the maximum number of retries, like retry, and can be 0, 1, or 2.
'';
};
};
});
description = ''
When and how many times a job can be auto-retried in case of a failure.
[Docs](https://docs.gitlab.com/ci/yaml/#retry)
'';
};
rules = mkUnsetOption {
# could be more granular
type = types.listOf types.attrs;
description = ''
List of conditions to evaluate and determine selected attributes of a job, and whether or not its created.
[Docs](https://docs.gitlab.com/ci/yaml/#rules)
'';
};
script = mkOption {
type = types.listOf types.str;
description = ''
Shell script that is executed by a runner.
[Docs](https://docs.gitlab.com/ci/yaml/#script)
'';
};
after_script = mkUnsetOption {
secrets = mkUnsetOption {
# could be more granular
type = types.attrs;
description = ''
The CI/CD secrets the job needs.
[Docs](https://docs.gitlab.com/ci/yaml/#secrets)
'';
};
services = mkUnsetOption {
# could be more granular
type = types.attrs;
description = ''
Use Docker services images.
[Docs](https://docs.gitlab.com/ci/yaml/#services)
'';
};
stage = mkOption {
type = types.str;
description = ''
Defines a job stage.
[Docs](https://docs.gitlab.com/ci/yaml/#stage)
'';
};
tags = mkUnsetOption {
type = types.listOf types.str;
description = ''
List of tags that are used to select a runner.
[Docs](https://docs.gitlab.com/ci/yaml/#tags)
'';
};
artifacts = mkUnsetOption {
type = types.attrs; # TODO: more granular
description = '''';
timeout = mkUnsetOption {
type = types.str;
description = ''
Define a custom job-level timeout that takes precedence over the project-wide setting.
[Docs](https://docs.gitlab.com/ci/yaml/#timeout)
'';
};
rules = mkUnsetOption {
type = types.listOf types.attrs;
trigger = mkUnsetOption {
# could be more granular
type = types.either types.str types.attrs;
description = ''
Defines a downstream pipeline trigger.
[Docs](https://docs.gitlab.com/ci/yaml/#trigger)
'';
};
allow_failure = mkUnsetOption {
type = types.bool;
when = mkUnsetOption {
type = types.enum ["on_success" "on_failure" "never" "always" "manual" "delayed"];
description = ''
When to run job. See also [`manual_confirmation`](#pipelinesnamejobsnamemanual_confirmation)
[Docs](https://docs.gitlab.com/ci/yaml/#when)
'';
};
variables = mkUnsetOption {
type = types.attrsOf types.str;
description = ''
You can use job variables in commands in the jobs `script`, `before_script`, or `after_script` sections, and also with some job keywords.
Check the **Supported values** section of each job keyword to see if it supports variables.
[Docs](https://docs.gitlab.com/ci/yaml/#job-variables)
'';
};
};
in {
@ -140,22 +637,22 @@ in rec {
// gitlabOptions;
config = let
attrsToKeep = builtins.attrNames gitlabOptions;
job = filterUnset (filterAttrs (n: _v: builtins.elem n attrsToKeep) config);
in {
finalConfig = cilib.mkJobPatched {
key = name;
job = filterUnset (filterAttrs (n: _v: builtins.elem n attrsToKeep) config);
nixConfig = config.nix;
inherit pipelineName;
inherit job pipelineName;
};
depsDrv = cilib.mkJobDeps {
key = name;
job = config.finalConfig;
nixConfig = config.nix;
inherit job;
};
runnerDrv = cilib.mkJobRun {
key = name;
job = config.finalConfig;
jobDeps = config.depsDrv;
inherit job;
};
packages = {
"gitlab-ci:pipeline:${pipelineName}:job-deps:${name}" = config.depsDrv;

View file

@ -4,8 +4,8 @@
jobSubmodule,
...
}: let
inherit (lib) mkOption types filterAttrs mergeAttrsList mapAttrs;
inherit (cilib.helpers) filterUnset mkUnsetOption toYaml toYamlPretty;
inherit (lib) mkOption types filterAttrs mergeAttrsList mapAttrs mkRenamedOptionModule literalExpression;
inherit (cilib.helpers) filterUnset unset mkUnsetOption toYaml toYamlPretty eitherWithSubOptions;
pipelineConfigSubmodule = {rootConfig, ...}: {
options = {
@ -30,19 +30,143 @@
# GITLAB OPTIONS
#
gitlabOptions = {
default = mkOption {
type = types.submodule {
# allow other keys aswell, maybe define them in the future? https://docs.gitlab.com/ci/yaml/#default
freeformType = types.anything;
options = {
image = mkUnsetOption {
type = types.str;
description = ''
Default image to use for this entire pipeline.
!!! note
Moved from top level to `default`: [GitLab Docs](https://docs.gitlab.com/ci/yaml/deprecated_keywords/).
'';
};
services = mkUnsetOption {
type = types.listOf types.anything;
description = ''
!!! note
Moved from top level to `default`: [GitLab Docs](https://docs.gitlab.com/ci/yaml/deprecated_keywords/).
'';
};
cache = mkUnsetOption {
# could be more granular
type = types.either (types.listOf types.attrs) types.attrs;
description = ''
!!! note
Moved from top level to `default`: [GitLab Docs](https://docs.gitlab.com/ci/yaml/deprecated_keywords/).
'';
};
before_script = mkUnsetOption {
type = types.listOf types.str;
description = ''
!!! note
Moved from top level to `default`: [GitLab Docs](https://docs.gitlab.com/ci/yaml/deprecated_keywords/).
'';
};
after_script = mkUnsetOption {
type = types.listOf types.str;
description = ''
!!! note
Moved from top level to `default`: [GitLab Docs](https://docs.gitlab.com/ci/yaml/deprecated_keywords/).
'';
};
};
};
# required for it to show up in the docs, but not in the config
default = unset;
defaultText = literalExpression "unset";
description = ''
Custom default values for job keywords.
'';
};
include = mkUnsetOption {
type = types.attrs;
description = ''
Import configuration from other YAML files.
[Docs](https://docs.gitlab.com/ci/yaml/#include)
'';
};
stages = mkOption {
type = types.listOf types.str;
default = [];
# .pre and .post always exist
apply = val: [".pre"] ++ val ++ [".post"];
description = ''
The names and order of the pipeline stages.
[Docs](https://docs.gitlab.com/ci/yaml/#stages)
!!! note
`.pre` and `.post` are added automatically.
'';
};
variables = mkUnsetOption {
type = types.attrsOf types.str;
description = '''';
# default/global variables can have descriptions etc.
type = types.attrsOf (eitherWithSubOptions types.str (types.submodule {
options = {
description = mkUnsetOption {
type = types.str;
description = ''
Use the `description` keyword to define a description for a default variable.
'';
};
value = mkUnsetOption {
type = types.str;
description = ''
Use the `value` keyword to define a pipeline-level (default) variables value.
'';
};
options = mkUnsetOption {
type = types.listOf types.str;
description = ''
Use `options` to define an array of values that are [selectable in the UI when running a pipeline manually](https://docs.gitlab.com/ci/pipelines/#configure-a-list-of-selectable-prefilled-variable-values).
'';
};
expand = mkUnsetOption {
type = types.bool;
description = ''
Use the `expand` keyword to configure a variable to be expandable or not.
'';
};
};
}));
description = ''
Define default CI/CD variables for all jobs in the pipeline.
Supports strings or attrs as values, for more info see [here](https://docs.gitlab.com/ci/yaml/#variablesdescription).
[Docs](https://docs.gitlab.com/ci/yaml/#default-variables)
'';
};
workflow = mkUnsetOption {
type = types.attrs;
description = ''
Control what types of pipeline run.
[Docs](https://docs.gitlab.com/ci/yaml/#workflow)
'';
};
};
in {
_file = ./pipeline.nix;
# from https://docs.gitlab.com/ci/yaml/#default
imports = builtins.map (val: mkRenamedOptionModule [val] ["default" val]) [
"after_script"
"artifacts"
"before_script"
"cache"
"hooks"
"id_tokens"
"image"
"interruptible"
"retry"
"services"
"tags"
"timeout"
];
options =
{
nix = mkOption {

View file

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

View file

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

View file

@ -3,12 +3,14 @@
in
cilib.mkCI {
config.soonix = {
componentUrl = "$CI_SERVER_FQDN/$CI_PROJECT_PATH/nix-gitlab-ci@$CI_COMMIT_SHA";
componentUrl = "$CI_SERVER_FQDN/$CI_PROJECT_PATH/nix-gitlab-ci";
componentVersion = "$CI_COMMIT_SHORT_SHA";
componentInputs.cache_files = ["flake.*" "nix/repo/ci.nix"];
# bootstrapping still needs to be done in the gitlab-ci.yml directly,
# the child pipeline can then use the built images to test them
extraData = {
stages = ["build-images" "build" "trigger"];
variables.NIX_CI_IMAGE = "$CI_REGISTRY_IMAGE/nix-ci:$CI_COMMIT_SHORT_SHA";
"build:image" = {
stage = "build-images";
parallel.matrix = [

View file

@ -38,12 +38,14 @@ in
};
config = {
site_name = "Nix-GitLab-CI";
site_url = "https://nix-gitlab-ci.projects.tf";
repo_name = "TECHNOFAB/nix-gitlab-ci";
repo_url = "https://gitlab.com/TECHNOFAB/nix-gitlab-ci";
extra_css = ["style.css"];
theme = {
logo = "images/logo.png";
logo = "images/logo.svg";
icon.repo = "simple/gitlab";
favicon = "images/favicon.png";
favicon = "images/logo.svg";
};
nav = [
{"Introduction" = "index.md";}

30
nix/repo/flake.lock generated
View file

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

View file

@ -62,6 +62,7 @@ nix-ci:build:
|| NIX_CI_PIPELINE_NAME="$CI_PIPELINE_SOURCE";
fi
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
# (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

View file

@ -64,6 +64,22 @@
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";
expected = {
@ -129,7 +145,7 @@
# sh
''
set -euo pipefail
${ntlib.helpers.path [pkgs.jq pkgs.gnugrep pkgs.coreutils]}
${ntlib.helpers.path (with pkgs; [jq gnugrep coreutils])}
echo "two keys, one json one pretty"
jq 'keys | length == 2' "${pipeline}" | grep -q true
echo "key[0] is exactly 'gitlab-ci:pipeline:test'"
@ -145,7 +161,7 @@
'';
}
{
name = "handle store paths in variables";
name = "ignore store paths in variables with nix disabled";
expected = {
stages = ["test"];
test = {
@ -166,6 +182,28 @@
};
}).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

@ -14,6 +14,8 @@
''
${ntlib.helpers.scriptHelpers}
${ntlib.helpers.path (with pkgs; [coreutils nix gnused gnugrep jq])}
export SSL_CERT_FILE=${pkgs.cacert}/etc/ssl/certs/ca-bundle.crt
export NIX_SSL_CERT_FILE=${pkgs.cacert}/etc/ssl/certs/ca-bundle.crt
repo_path=${../.}
cp ${./fixtures/flake_parts}/* .

View file

@ -34,6 +34,7 @@
expected = {
stages = [".pre" "test" ".post"];
"test" = {
image = "$NIX_CI_IMAGE";
stage = "test";
before_script = ["source setup_nix_ci \"gitlab-ci:pipeline:test:job-deps:test\""];
script = ["echo hello world"];
@ -76,6 +77,27 @@
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-.*"'
'';
}
];
};
}