mirror of
https://gitlab.com/TECHNOFAB/nix-gitlab-ci.git
synced 2025-12-12 02:00:13 +01:00
Compare commits
27 commits
0c6949f585
...
7cb73d2319
| Author | SHA1 | Date | |
|---|---|---|---|
| 7cb73d2319 | |||
| 5e39c4fbcc | |||
| 046656458b | |||
| d88ada2c41 | |||
| 0cca02f442 | |||
| e752f71dd1 | |||
| 428afaf603 | |||
| 00cf5b83c6 | |||
| 2a0a3f5881 | |||
| 5e2ae29660 | |||
| 31f0e4ea13 | |||
| a076f0048a | |||
| cf04bf5357 | |||
| 4d824900d4 | |||
| 6cd05e503a | |||
| c4a439b839 | |||
| 436e2fde25 | |||
| 0bd75fd1bb | |||
| f147295418 | |||
| cad40720a6 | |||
| e7f7043012 | |||
| aa1abf945e | |||
| 46bb4fe455 | |||
| 537d5c7c87 | |||
| 6e4347af69 | |||
| e074d716c4 | |||
| 0952ab4145 |
65 changed files with 2772 additions and 1296 deletions
3
.envrc
3
.envrc
|
|
@ -1 +1,2 @@
|
|||
use flake . --impure --accept-flake-config
|
||||
source $(fetchurl https://gitlab.com/rensa-nix/direnv/-/raw/v0.3.0/direnvrc "sha256-u7+KEz684NnIZ+Vh5x5qLrt8rKdnUNexewBoeTcEVHQ=")
|
||||
use ren //repo/devShells/default
|
||||
|
|
|
|||
6
.gitignore
vendored
6
.gitignore
vendored
|
|
@ -1,6 +1,2 @@
|
|||
.idea
|
||||
.devenv
|
||||
.direnv
|
||||
.pre-commit-config.yaml
|
||||
.ren/
|
||||
result
|
||||
*.xml
|
||||
|
|
|
|||
|
|
@ -1,49 +1,57 @@
|
|||
include:
|
||||
- component: $CI_SERVER_FQDN/$CI_PROJECT_PATH/nix-gitlab-ci@$CI_COMMIT_SHA
|
||||
inputs:
|
||||
version: $CI_COMMIT_SHORT_SHA
|
||||
stages:
|
||||
- build-images
|
||||
- build
|
||||
- trigger
|
||||
# Generated by soonix, DO NOT EDIT
|
||||
build:image:
|
||||
stage: build-images
|
||||
parallel:
|
||||
matrix:
|
||||
- ARCH: ["x86_64-linux", "aarch64-linux"]
|
||||
image: nixpkgs/nix-flakes:latest
|
||||
script:
|
||||
- nix build .#image --system $ARCH
|
||||
after_script:
|
||||
- install -D result dist/nix-ci-$ARCH.tar.gz
|
||||
- install -D result dist/nix-ci-$ARCH.tar.gz
|
||||
artifacts:
|
||||
paths:
|
||||
- dist
|
||||
deploy:image:
|
||||
- dist
|
||||
image: nixpkgs/nix-flakes:latest
|
||||
parallel:
|
||||
matrix:
|
||||
- ARCH:
|
||||
- x86_64-linux
|
||||
- aarch64-linux
|
||||
script:
|
||||
- nix build .#image --system $ARCH
|
||||
stage: build-images
|
||||
deploy:image:
|
||||
before_script:
|
||||
- 'nix profile install nixpkgs#buildah
|
||||
|
||||
export PATH="$PATH:$HOME/.nix-profile/bin"
|
||||
|
||||
export REGISTRY_AUTH_FILE=${HOME}/auth.json
|
||||
|
||||
echo "$CI_REGISTRY_PASSWORD" | buildah login -u "$CI_REGISTRY_USER" --password-stdin
|
||||
$CI_REGISTRY
|
||||
|
||||
mkdir -p /etc/containers && echo ''{"default":[{"type":"insecureAcceptAnything"}]}''
|
||||
> /etc/containers/policy.json
|
||||
|
||||
mkdir -p /var/tmp
|
||||
|
||||
'
|
||||
image: nixpkgs/nix-flakes:latest
|
||||
needs:
|
||||
- build:image
|
||||
before_script:
|
||||
- nix profile install nixpkgs#buildah
|
||||
- export PATH="$PATH:$HOME/.nix-profile/bin"
|
||||
- export REGISTRY_AUTH_FILE=''${HOME}/auth.json
|
||||
- echo "$CI_REGISTRY_PASSWORD" | buildah login -u "$CI_REGISTRY_USER" --password-stdin $CI_REGISTRY
|
||||
- mkdir -p /etc/containers && echo '{"default":[{"type":"insecureAcceptAnything"}]}' > /etc/containers/policy.json
|
||||
- mkdir -p /var/tmp
|
||||
- build:image
|
||||
script:
|
||||
- export NORMALIZED_BRANCH=${CI_COMMIT_BRANCH/\//-}
|
||||
- buildah manifest create localhost/nix-ci
|
||||
- buildah manifest add localhost/nix-ci docker-archive:dist/nix-ci-x86_64-linux.tar.gz
|
||||
- buildah manifest add localhost/nix-ci docker-archive:dist/nix-ci-aarch64-linux.tar.gz
|
||||
- buildah manifest push --all localhost/nix-ci docker://''${CI_REGISTRY_IMAGE}/nix-ci:${CI_COMMIT_SHORT_SHA}
|
||||
# branches
|
||||
- |
|
||||
if [ -z "$CI_COMMIT_TAG" ]; then
|
||||
buildah manifest push --all localhost/nix-ci docker://''${CI_REGISTRY_IMAGE}/nix-ci:${NORMALIZED_BRANCH/main/latest}
|
||||
fi
|
||||
# tags
|
||||
- |
|
||||
if [ -n "$CI_COMMIT_TAG" ]; then
|
||||
buildah manifest push --all localhost/nix-ci docker://''${CI_REGISTRY_IMAGE}/nix-ci:${CI_COMMIT_TAG}
|
||||
fi
|
||||
- "export NORMALIZED_BRANCH=${CI_COMMIT_BRANCH/\\//-}\nbuildah manifest create localhost/nix-ci\n\
|
||||
buildah manifest add localhost/nix-ci docker-archive:dist/nix-ci-x86_64-linux.tar.gz\n\
|
||||
buildah manifest add localhost/nix-ci docker-archive:dist/nix-ci-aarch64-linux.tar.gz\n\
|
||||
buildah manifest push --all localhost/nix-ci docker://${CI_REGISTRY_IMAGE}/nix-ci:${CI_COMMIT_SHORT_SHA}\n\
|
||||
# branches\nif [ -z \"$CI_COMMIT_TAG\" ]; then\n buildah manifest push --all\
|
||||
\ localhost/nix-ci docker://${CI_REGISTRY_IMAGE}/nix-ci:${NORMALIZED_BRANCH/main/latest}\n\
|
||||
fi\n# tags\nif [ -n \"$CI_COMMIT_TAG\" ]; then\n buildah manifest push --all\
|
||||
\ 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_SHORT_SHA
|
||||
inputs:
|
||||
cache_files:
|
||||
- flake.*
|
||||
- nix/repo/ci.nix
|
||||
version: $CI_COMMIT_SHORT_SHA
|
||||
stages:
|
||||
- build-images
|
||||
- build
|
||||
- trigger
|
||||
|
|
|
|||
52
README.md
52
README.md
|
|
@ -13,7 +13,7 @@ This allows easily using any Nix package in CI.
|
|||
|
||||
Also makes it possible to split CI parts in a separate module which can be imported in multiple projects.
|
||||
|
||||
## Usage
|
||||
## Usage (with flake-parts)
|
||||
|
||||
```nix
|
||||
# flake.nix
|
||||
|
|
@ -28,23 +28,27 @@ Also makes it possible to split CI parts in a separate module which can be impor
|
|||
...
|
||||
|
||||
perSystem = {pkgs, ...}: {
|
||||
# ci is a shortcut and creates a "default" pipeline
|
||||
ci = {
|
||||
stages = ["test"];
|
||||
jobs = {
|
||||
"test" = {
|
||||
stage = "test";
|
||||
nix.deps = [pkgs.unixtools.ping];
|
||||
script = [
|
||||
"ping -c 5 8.8.8.8"
|
||||
];
|
||||
config = {
|
||||
# configure Nix-GitLab-CI here, see docs for options
|
||||
};
|
||||
pipelines."default" = {
|
||||
stages = ["test"];
|
||||
jobs = {
|
||||
"test" = {
|
||||
stage = "test";
|
||||
nix.deps = [pkgs.unixtools.ping];
|
||||
script = [
|
||||
"ping -c 5 8.8.8.8"
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
# runs on a merge request for example
|
||||
pipelines."merge_request_event" = {
|
||||
stages = ["some_stage"];
|
||||
jobs = { ... };
|
||||
# runs on a merge request for example
|
||||
pipelines."merge_request_event" = {
|
||||
stages = ["some_stage"];
|
||||
jobs = { ... };
|
||||
};
|
||||
};
|
||||
...
|
||||
}
|
||||
|
|
@ -52,6 +56,9 @@ Also makes it possible to split CI parts in a separate module which can be impor
|
|||
}
|
||||
```
|
||||
|
||||
Now either use this in your .gitlab-ci.yml or setup Soonix to auto generate this
|
||||
file for you with the right version (see the [docs][docs-soonix] for more).
|
||||
|
||||
```yaml
|
||||
# .gitlab-ci.yml
|
||||
include:
|
||||
|
|
@ -60,6 +67,19 @@ include:
|
|||
version: <version> # docker image tag, use the same version as a above
|
||||
```
|
||||
|
||||
## Usage (directly)
|
||||
|
||||
```nix
|
||||
let
|
||||
cilib = inputs.nix-gitlab-ci.lib {inherit pkgs;};
|
||||
in
|
||||
cilib.mkCI {
|
||||
config = ...;
|
||||
pipelines."default" = ...;
|
||||
};
|
||||
# exposes `soonix` for the soonix hook and `packages` which contain the configs, jobs etc.
|
||||
```
|
||||
|
||||
## Utilities
|
||||
|
||||
### Disable Caching temporarily
|
||||
|
|
@ -87,3 +107,5 @@ There is also `.#gitlab-ci:pipeline:<pipeline name>:job-deps:<name>` which gener
|
|||
## Thanks to
|
||||
|
||||
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"
|
||||
|
|
|
|||
|
|
@ -1,16 +1,11 @@
|
|||
# Example Configs
|
||||
|
||||
## V2
|
||||
|
||||
- [TECHNOFAB/nix-gitlab-ci](https://gitlab.com/TECHNOFAB/nix-gitlab-ci)
|
||||
See `flake.nix` for some random example jobs.
|
||||
- [TECHNOFAB/nixlets](https://gitlab.com/TECHNOFAB/nixlets)
|
||||
- [TECHNOFAB/nixible](https://gitlab.com/TECHNOFAB/nixible)
|
||||
- [TECHNOFAB/nixmkdocs](https://gitlab.com/TECHNOFAB/nixmkdocs)
|
||||
- [TECHNOFAB/tofunix](https://gitlab.com/TECHNOFAB/tofunix)
|
||||
|
||||
## Old / V1
|
||||
|
||||
- [TECHNOFAB/coder-templates](https://gitlab.com/TECHNOFAB/coder-templates)
|
||||
- [TECHNOFAB/nixtest](https://gitlab.com/TECHNOFAB/nixtest)
|
||||
|
||||
!!! note
|
||||
|
||||
|
|
|
|||
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
1
docs/images/logo.svg
Executable 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 |
3
docs/options.md
Normal file
3
docs/options.md
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
# Options
|
||||
|
||||
{% include 'options.md' %}
|
||||
|
|
@ -36,8 +36,7 @@ flake module within your `flake-parts` configuration.
|
|||
|
||||
perSystem = { pkgs, ... }: {
|
||||
# define your CI pipelines
|
||||
# ci = { ... };
|
||||
# pipelines."merge_request_event" = { ... };
|
||||
# ci.pipelines."merge_request_event" = { ... };
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
@ -73,3 +72,10 @@ include:
|
|||
Again, ensure `<version>` matches the version used in your `flake.nix`.
|
||||
This component includes a job (`build:nix-ci`) that will evaluate your Nix
|
||||
configuration and generate the `.gitlab-ci.yml` used for the pipeline run.
|
||||
|
||||
!!! note
|
||||
|
||||
Since V3 [Soonix](https://soonix.projects.tf) is supported, this can
|
||||
automatically generate the `.gitlab-ci.yml` for you, with the version
|
||||
automatically following the flake.
|
||||
See [Soonix Integration](./soonix.md) for more.
|
||||
|
|
|
|||
20
docs/soonix.md
Normal file
20
docs/soonix.md
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
# Soonix Integration
|
||||
|
||||
[Soonix](https://soonix.projects.tf) can be used to automatically generate the
|
||||
`.gitlab-ci.yml` for you.
|
||||
This will by default include the CI/CD component with the same version as the
|
||||
flake (using the `VERSION` file in this repo).
|
||||
|
||||
You can specify some options to configure this, like changing the component URL
|
||||
or adding extra data to your `.gitlab-ci.yml` (like this repo does to bootstrap
|
||||
Nix-GitLab-CI). See [Options](./options.md#configsoonix) for all the config options.
|
||||
|
||||
You can use it like this:
|
||||
|
||||
```nix
|
||||
let
|
||||
ci = cilib.mkCI { ... };
|
||||
in {
|
||||
soonix.hooks."ci" = ci.soonix;
|
||||
}
|
||||
```
|
||||
15
docs/style.css
Normal file
15
docs/style.css
Normal 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;
|
||||
}
|
||||
|
||||
|
|
@ -1,33 +1,73 @@
|
|||
# Usage
|
||||
|
||||
To create a basic pipeline, configure it by setting `ci` in `perSystem`.
|
||||
The schema is similar to the `.gitlab-ci.yml`, only jobs are defined differently:
|
||||
## Usage (with flake-parts)
|
||||
|
||||
```nix
|
||||
ci = {
|
||||
# Nix GitLab CI specific config, see `configType` in `flakeModule.nix`
|
||||
config = {};
|
||||
jobs = {
|
||||
"job-a" = {};
|
||||
"job-b" = {};
|
||||
};
|
||||
};
|
||||
# flake.nix
|
||||
{
|
||||
...
|
||||
inputs.nix-gitlab-ci.url = "gitlab:TECHNOFAB/nix-gitlab-ci/<version>?dir=lib"; # recommendation: pin to the latest release/version
|
||||
|
||||
outputs = {...}: flake-parts.lib.mkFlake {...} {
|
||||
imports = [
|
||||
inputs.nix-gitlab-ci.flakeModule
|
||||
];
|
||||
...
|
||||
|
||||
perSystem = {pkgs, ...}: {
|
||||
ci = {
|
||||
config = {
|
||||
# configure Nix-GitLab-CI here, see docs for options
|
||||
};
|
||||
pipelines."default" = {
|
||||
stages = ["test"];
|
||||
jobs = {
|
||||
"test" = {
|
||||
stage = "test";
|
||||
nix.deps = [pkgs.unixtools.ping];
|
||||
script = [
|
||||
"ping -c 5 8.8.8.8"
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
# runs on a merge request for example
|
||||
pipelines."merge_request_event" = {
|
||||
stages = ["some_stage"];
|
||||
jobs = { ... };
|
||||
};
|
||||
};
|
||||
...
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
For every job, there are a couple of settings you can adjust aswell:
|
||||
Now either use this in your .gitlab-ci.yml or setup Soonix to auto generate this
|
||||
file for you with the right version (see the [docs][docs-soonix] for more).
|
||||
|
||||
```yaml
|
||||
# .gitlab-ci.yml
|
||||
include:
|
||||
- component: gitlab.com/TECHNOFAB/nix-gitlab-ci/nix-gitlab-ci@<version> # recommendation: pin to the latest release/version (don't use "main" etc.)
|
||||
inputs:
|
||||
version: <version> # docker image tag, use the same version as a above
|
||||
```
|
||||
|
||||
## Usage (directly)
|
||||
|
||||
```nix
|
||||
"job-a" = {
|
||||
# see `jobType` in `flakeModule.nix`
|
||||
nix = {
|
||||
enable = true; # is this a nix-based job?
|
||||
deps = []; # dependencies to install for this job
|
||||
# for gitlab runner cache:
|
||||
enable-runner-cache = false;
|
||||
runner-cache-key = "";
|
||||
let
|
||||
cilib = inputs.nix-gitlab-ci.lib {inherit pkgs;};
|
||||
in
|
||||
cilib.mkCI {
|
||||
config = ...;
|
||||
pipelines."default" = ...;
|
||||
};
|
||||
};
|
||||
# exposes `soonix` for the soonix hook and `packages` which contain the configs, jobs etc.
|
||||
```
|
||||
|
||||
______________________________________________________________________
|
||||
|
||||
Since V2 multiple pipelines are supported.
|
||||
See [Multiple Pipelines](./multi_pipeline.md) for more.
|
||||
|
|
|
|||
|
|
@ -57,3 +57,8 @@ correctly resolved across different architectures).
|
|||
|
||||
You can use this to inspect the environment that would be set up for a job without
|
||||
running the full script.
|
||||
|
||||
## Viewing generated config in YAML
|
||||
|
||||
Since the GitLab CI config is generated simply using JSON, it's hard to read and
|
||||
debug. For debugging V3 now adds another package `gitlab-ci:pipeline:<pipeline name>:pretty`.
|
||||
|
|
|
|||
95
examples/flake-parts/flake.lock
generated
Normal file
95
examples/flake-parts/flake.lock
generated
Normal file
|
|
@ -0,0 +1,95 @@
|
|||
{
|
||||
"nodes": {
|
||||
"flake-parts": {
|
||||
"inputs": {
|
||||
"nixpkgs-lib": "nixpkgs-lib"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1756770412,
|
||||
"narHash": "sha256-+uWLQZccFHwqpGqr2Yt5VsW/PbeJVTn9Dk6SHWhNRPw=",
|
||||
"owner": "hercules-ci",
|
||||
"repo": "flake-parts",
|
||||
"rev": "4524271976b625a4a605beefd893f270620fd751",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "hercules-ci",
|
||||
"repo": "flake-parts",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nix-gitlab-ci": {
|
||||
"locked": {
|
||||
"dir": "lib",
|
||||
"lastModified": 1752052838,
|
||||
"narHash": "sha256-EqP4xB8YTVXWPCCchnVtQbuq0bKa79TUEcPF3hjuX/k=",
|
||||
"owner": "TECHNOFAB",
|
||||
"repo": "nix-gitlab-ci",
|
||||
"rev": "0c6949f585a2c1ea2cf85fc01445496f7c75faae",
|
||||
"type": "gitlab"
|
||||
},
|
||||
"original": {
|
||||
"dir": "lib",
|
||||
"owner": "TECHNOFAB",
|
||||
"repo": "nix-gitlab-ci",
|
||||
"type": "gitlab"
|
||||
}
|
||||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1756696532,
|
||||
"narHash": "sha256-6FWagzm0b7I/IGigOv9pr6LL7NQ86mextfE8g8Q6HBg=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "58dcbf1ec551914c3756c267b8b9c8c86baa1b2f",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"ref": "nixpkgs-unstable",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs-lib": {
|
||||
"locked": {
|
||||
"lastModified": 1754788789,
|
||||
"narHash": "sha256-x2rJ+Ovzq0sCMpgfgGaaqgBSwY+LST+WbZ6TytnT9Rk=",
|
||||
"owner": "nix-community",
|
||||
"repo": "nixpkgs.lib",
|
||||
"rev": "a73b9c743612e4244d865a2fdee11865283c04e6",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-community",
|
||||
"repo": "nixpkgs.lib",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"root": {
|
||||
"inputs": {
|
||||
"flake-parts": "flake-parts",
|
||||
"nix-gitlab-ci": "nix-gitlab-ci",
|
||||
"nixpkgs": "nixpkgs",
|
||||
"systems": "systems"
|
||||
}
|
||||
},
|
||||
"systems": {
|
||||
"locked": {
|
||||
"lastModified": 1689347949,
|
||||
"narHash": "sha256-12tWmuL2zgBgZkdoB6qXZsgJEH9LR3oUgpaQq2RbI80=",
|
||||
"owner": "nix-systems",
|
||||
"repo": "default-linux",
|
||||
"rev": "31732fcf5e8fea42e59c2488ad31a0e651500f68",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-systems",
|
||||
"repo": "default-linux",
|
||||
"type": "github"
|
||||
}
|
||||
}
|
||||
},
|
||||
"root": "root",
|
||||
"version": 7
|
||||
}
|
||||
39
examples/flake-parts/flake.nix
Normal file
39
examples/flake-parts/flake.nix
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
{
|
||||
outputs = {
|
||||
flake-parts,
|
||||
systems,
|
||||
...
|
||||
} @ inputs:
|
||||
flake-parts.lib.mkFlake {inherit inputs;} {
|
||||
imports = [
|
||||
inputs.nix-gitlab-ci.flakeModule
|
||||
];
|
||||
systems = import systems;
|
||||
flake = {};
|
||||
perSystem = _: {
|
||||
ci = {
|
||||
pipelines = {
|
||||
"default" = {
|
||||
stages = ["example"];
|
||||
jobs."example" = {
|
||||
stage = "example";
|
||||
script = ["echo hello world"];
|
||||
};
|
||||
};
|
||||
"test".jobs."example" = {
|
||||
stage = ".pre";
|
||||
script = ["echo hello world"];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
inputs = {
|
||||
nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
|
||||
flake-parts.url = "github:hercules-ci/flake-parts";
|
||||
systems.url = "github:nix-systems/default-linux";
|
||||
# NOTE: better pin to a version
|
||||
nix-gitlab-ci.url = "gitlab:TECHNOFAB/nix-gitlab-ci?dir=lib";
|
||||
};
|
||||
}
|
||||
63
examples/rensa-nix/flake.lock
generated
Normal file
63
examples/rensa-nix/flake.lock
generated
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
{
|
||||
"nodes": {
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1756542300,
|
||||
"narHash": "sha256-tlOn88coG5fzdyqz6R93SQL5Gpq+m/DsWpekNFhqPQk=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "d7600c775f877cd87b4f5a831c28aa94137377aa",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"ref": "nixos-unstable",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs-lib": {
|
||||
"locked": {
|
||||
"lastModified": 1754184128,
|
||||
"narHash": "sha256-AjhoyBL4eSyXf01Bmc6DiuaMrJRNdWopmdnMY0Pa/M0=",
|
||||
"owner": "nix-community",
|
||||
"repo": "nixpkgs.lib",
|
||||
"rev": "02e72200e6d56494f4a7c0da8118760736e41b60",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-community",
|
||||
"repo": "nixpkgs.lib",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"ren": {
|
||||
"inputs": {
|
||||
"nixpkgs-lib": "nixpkgs-lib"
|
||||
},
|
||||
"locked": {
|
||||
"dir": "lib",
|
||||
"lastModified": 1756370106,
|
||||
"narHash": "sha256-l84ojcHuQWBwn4BRxQsMMfQpcq/Az/sHh/hSqFgVtyg=",
|
||||
"owner": "rensa-nix",
|
||||
"repo": "core",
|
||||
"rev": "9c1a29fa9ba7cbbb78b9e47eb8afbcd29303a3b4",
|
||||
"type": "gitlab"
|
||||
},
|
||||
"original": {
|
||||
"dir": "lib",
|
||||
"owner": "rensa-nix",
|
||||
"repo": "core",
|
||||
"type": "gitlab"
|
||||
}
|
||||
},
|
||||
"root": {
|
||||
"inputs": {
|
||||
"nixpkgs": "nixpkgs",
|
||||
"ren": "ren"
|
||||
}
|
||||
}
|
||||
},
|
||||
"root": "root",
|
||||
"version": 7
|
||||
}
|
||||
30
examples/rensa-nix/flake.nix
Normal file
30
examples/rensa-nix/flake.nix
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
{
|
||||
inputs = {
|
||||
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
||||
ren.url = "gitlab:rensa-nix/core?dir=lib";
|
||||
};
|
||||
|
||||
outputs = {
|
||||
self,
|
||||
ren,
|
||||
...
|
||||
} @ inputs:
|
||||
ren.buildWith
|
||||
{
|
||||
inherit inputs;
|
||||
cellsFrom = ./nix;
|
||||
transformInputs = system: i:
|
||||
i
|
||||
// {
|
||||
pkgs = import i.nixpkgs {inherit system;};
|
||||
};
|
||||
cellBlocks = with ren.blocks; [
|
||||
(simple "ci")
|
||||
];
|
||||
}
|
||||
{
|
||||
packages = ren.select self [
|
||||
["repo" "ci" "packages"]
|
||||
];
|
||||
};
|
||||
}
|
||||
18
examples/rensa-nix/nix/repo/ci.nix
Normal file
18
examples/rensa-nix/nix/repo/ci.nix
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
{inputs, ...}: let
|
||||
inherit (inputs) cilib;
|
||||
in
|
||||
cilib.mkCI {
|
||||
pipelines = {
|
||||
"default" = {
|
||||
stages = ["example"];
|
||||
jobs."example" = {
|
||||
stage = "example";
|
||||
script = ["echo hello world"];
|
||||
};
|
||||
};
|
||||
"test".jobs."example" = {
|
||||
stage = ".pre";
|
||||
script = ["echo hello world"];
|
||||
};
|
||||
};
|
||||
}
|
||||
28
examples/rensa-nix/nix/repo/flake.lock
generated
Normal file
28
examples/rensa-nix/nix/repo/flake.lock
generated
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
{
|
||||
"nodes": {
|
||||
"nix-gitlab-ci-lib": {
|
||||
"locked": {
|
||||
"dir": "lib",
|
||||
"lastModified": 1752052838,
|
||||
"narHash": "sha256-EqP4xB8YTVXWPCCchnVtQbuq0bKa79TUEcPF3hjuX/k=",
|
||||
"owner": "TECHNOFAB",
|
||||
"repo": "nix-gitlab-ci",
|
||||
"rev": "0c6949f585a2c1ea2cf85fc01445496f7c75faae",
|
||||
"type": "gitlab"
|
||||
},
|
||||
"original": {
|
||||
"dir": "lib",
|
||||
"owner": "TECHNOFAB",
|
||||
"repo": "nix-gitlab-ci",
|
||||
"type": "gitlab"
|
||||
}
|
||||
},
|
||||
"root": {
|
||||
"inputs": {
|
||||
"nix-gitlab-ci-lib": "nix-gitlab-ci-lib"
|
||||
}
|
||||
}
|
||||
},
|
||||
"root": "root",
|
||||
"version": 7
|
||||
}
|
||||
10
examples/rensa-nix/nix/repo/flake.nix
Normal file
10
examples/rensa-nix/nix/repo/flake.nix
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
inputs = {
|
||||
nix-gitlab-ci-lib.url = "gitlab:TECHNOFAB/nix-gitlab-ci?dir=lib";
|
||||
};
|
||||
outputs = i:
|
||||
i
|
||||
// {
|
||||
cilib = i.nix-gitlab-ci-lib.lib {inherit (i.parent) pkgs;};
|
||||
};
|
||||
}
|
||||
371
flake.lock
generated
371
flake.lock
generated
|
|
@ -1,246 +1,12 @@
|
|||
{
|
||||
"nodes": {
|
||||
"cachix": {
|
||||
"inputs": {
|
||||
"devenv": [
|
||||
"devenv"
|
||||
],
|
||||
"flake-compat": [
|
||||
"devenv"
|
||||
],
|
||||
"git-hooks": [
|
||||
"devenv"
|
||||
],
|
||||
"nixpkgs": "nixpkgs"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1737621947,
|
||||
"narHash": "sha256-8HFvG7fvIFbgtaYAY2628Tb89fA55nPm2jSiNs0/Cws=",
|
||||
"owner": "cachix",
|
||||
"repo": "cachix",
|
||||
"rev": "f65a3cd5e339c223471e64c051434616e18cc4f5",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "cachix",
|
||||
"ref": "latest",
|
||||
"repo": "cachix",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"devenv": {
|
||||
"inputs": {
|
||||
"cachix": "cachix",
|
||||
"flake-compat": "flake-compat",
|
||||
"git-hooks": "git-hooks",
|
||||
"nix": "nix",
|
||||
"nixpkgs": "nixpkgs_3"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1743687534,
|
||||
"narHash": "sha256-QIh5jKWE0aZ4N77Zu3kz0RjA22zqqy5p6PfJnOW5rPE=",
|
||||
"owner": "cachix",
|
||||
"repo": "devenv",
|
||||
"rev": "efd5d68a6483573410565d0b940e1a67b6f92591",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "cachix",
|
||||
"repo": "devenv",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"flake-compat": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1733328505,
|
||||
"narHash": "sha256-NeCCThCEP3eCl2l/+27kNNK7QrwZB1IJCrXfrbv5oqU=",
|
||||
"owner": "edolstra",
|
||||
"repo": "flake-compat",
|
||||
"rev": "ff81ac966bb2cae68946d5ed5fc4994f96d0ffec",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "edolstra",
|
||||
"repo": "flake-compat",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"flake-parts": {
|
||||
"inputs": {
|
||||
"nixpkgs-lib": [
|
||||
"devenv",
|
||||
"nix",
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1712014858,
|
||||
"narHash": "sha256-sB4SWl2lX95bExY2gMFG5HIzvva5AVMJd4Igm+GpZNw=",
|
||||
"owner": "hercules-ci",
|
||||
"repo": "flake-parts",
|
||||
"rev": "9126214d0a59633752a136528f5f3b9aa8565b7d",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "hercules-ci",
|
||||
"repo": "flake-parts",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"flake-parts_2": {
|
||||
"inputs": {
|
||||
"nixpkgs-lib": "nixpkgs-lib"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1743550720,
|
||||
"narHash": "sha256-hIshGgKZCgWh6AYJpJmRgFdR3WUbkY04o82X05xqQiY=",
|
||||
"owner": "hercules-ci",
|
||||
"repo": "flake-parts",
|
||||
"rev": "c621e8422220273271f52058f618c94e405bb0f5",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "hercules-ci",
|
||||
"repo": "flake-parts",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"git-hooks": {
|
||||
"inputs": {
|
||||
"flake-compat": [
|
||||
"devenv"
|
||||
],
|
||||
"gitignore": "gitignore",
|
||||
"nixpkgs": [
|
||||
"devenv",
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1740849354,
|
||||
"narHash": "sha256-oy33+t09FraucSZ2rZ6qnD1Y1c8azKKmQuCvF2ytUko=",
|
||||
"owner": "cachix",
|
||||
"repo": "git-hooks.nix",
|
||||
"rev": "4a709a8ce9f8c08fa7ddb86761fe488ff7858a07",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "cachix",
|
||||
"repo": "git-hooks.nix",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"gitignore": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
"devenv",
|
||||
"git-hooks",
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1709087332,
|
||||
"narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=",
|
||||
"owner": "hercules-ci",
|
||||
"repo": "gitignore.nix",
|
||||
"rev": "637db329424fd7e46cf4185293b9cc8c88c95394",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "hercules-ci",
|
||||
"repo": "gitignore.nix",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"libgit2": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1697646580,
|
||||
"narHash": "sha256-oX4Z3S9WtJlwvj0uH9HlYcWv+x1hqp8mhXl7HsLu2f0=",
|
||||
"owner": "libgit2",
|
||||
"repo": "libgit2",
|
||||
"rev": "45fd9ed7ae1a9b74b957ef4f337bc3c8b3df01b5",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "libgit2",
|
||||
"repo": "libgit2",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"mkdocs-material-umami": {
|
||||
"locked": {
|
||||
"lastModified": 1745840856,
|
||||
"narHash": "sha256-1Ad1JTMQMP6YsoIKAA+SBCE15qWrYkGue9/lXOLnu9I=",
|
||||
"owner": "technofab",
|
||||
"repo": "mkdocs-material-umami",
|
||||
"rev": "3ac9b194450f6b779c37b8d16fec640198e5cd0a",
|
||||
"type": "gitlab"
|
||||
},
|
||||
"original": {
|
||||
"owner": "technofab",
|
||||
"repo": "mkdocs-material-umami",
|
||||
"type": "gitlab"
|
||||
}
|
||||
},
|
||||
"nix": {
|
||||
"inputs": {
|
||||
"flake-compat": [
|
||||
"devenv"
|
||||
],
|
||||
"flake-parts": "flake-parts",
|
||||
"libgit2": "libgit2",
|
||||
"nixpkgs": "nixpkgs_2",
|
||||
"nixpkgs-23-11": [
|
||||
"devenv"
|
||||
],
|
||||
"nixpkgs-regression": [
|
||||
"devenv"
|
||||
],
|
||||
"pre-commit-hooks": [
|
||||
"devenv"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1741798497,
|
||||
"narHash": "sha256-E3j+3MoY8Y96mG1dUIiLFm2tZmNbRvSiyN7CrSKuAVg=",
|
||||
"owner": "domenkozar",
|
||||
"repo": "nix",
|
||||
"rev": "f3f44b2baaf6c4c6e179de8cbb1cc6db031083cd",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "domenkozar",
|
||||
"ref": "devenv-2.24",
|
||||
"repo": "nix",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nix-mkdocs": {
|
||||
"locked": {
|
||||
"dir": "lib",
|
||||
"lastModified": 1745175318,
|
||||
"narHash": "sha256-eJOTw3SK4psqBPP2hNJ4D/13/oi/FLoM0tYKoCGVFP8=",
|
||||
"owner": "technofab",
|
||||
"repo": "nixmkdocs",
|
||||
"rev": "6d6e0139060c896ae14de4b9c82335655a384643",
|
||||
"type": "gitlab"
|
||||
},
|
||||
"original": {
|
||||
"dir": "lib",
|
||||
"owner": "technofab",
|
||||
"repo": "nixmkdocs",
|
||||
"type": "gitlab"
|
||||
}
|
||||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1733212471,
|
||||
"narHash": "sha256-M1+uCoV5igihRfcUKrr1riygbe73/dzNnzPsmaLCmpo=",
|
||||
"lastModified": 1756542300,
|
||||
"narHash": "sha256-tlOn88coG5fzdyqz6R93SQL5Gpq+m/DsWpekNFhqPQk=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "55d15ad12a74eb7d4646254e13638ad0c4128776",
|
||||
"rev": "d7600c775f877cd87b4f5a831c28aa94137377aa",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
|
@ -252,11 +18,11 @@
|
|||
},
|
||||
"nixpkgs-lib": {
|
||||
"locked": {
|
||||
"lastModified": 1743296961,
|
||||
"narHash": "sha256-b1EdN3cULCqtorQ4QeWgLMrd5ZGOjLSLemfa00heasc=",
|
||||
"lastModified": 1754184128,
|
||||
"narHash": "sha256-AjhoyBL4eSyXf01Bmc6DiuaMrJRNdWopmdnMY0Pa/M0=",
|
||||
"owner": "nix-community",
|
||||
"repo": "nixpkgs.lib",
|
||||
"rev": "e4822aea2a6d1cdd36653c134cacfd64c97ff4fa",
|
||||
"rev": "02e72200e6d56494f4a7c0da8118760736e41b60",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
|
@ -265,131 +31,30 @@
|
|||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs_2": {
|
||||
"locked": {
|
||||
"lastModified": 1717432640,
|
||||
"narHash": "sha256-+f9c4/ZX5MWDOuB1rKoWj+lBNm0z0rs4CK47HBLxy1o=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "88269ab3044128b7c2f4c7d68448b2fb50456870",
|
||||
"type": "github"
|
||||
"ren": {
|
||||
"inputs": {
|
||||
"nixpkgs-lib": "nixpkgs-lib"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"ref": "release-24.05",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs_3": {
|
||||
"locked": {
|
||||
"lastModified": 1733477122,
|
||||
"narHash": "sha256-qamMCz5mNpQmgBwc8SB5tVMlD5sbwVIToVZtSxMph9s=",
|
||||
"owner": "cachix",
|
||||
"repo": "devenv-nixpkgs",
|
||||
"rev": "7bd9e84d0452f6d2e63b6e6da29fe73fac951857",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "cachix",
|
||||
"ref": "rolling",
|
||||
"repo": "devenv-nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs_4": {
|
||||
"locked": {
|
||||
"lastModified": 1745377448,
|
||||
"narHash": "sha256-jhZDfXVKdD7TSEGgzFJQvEEZ2K65UMiqW5YJ2aIqxMA=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "507b63021ada5fee621b6ca371c4fca9ca46f52c",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"ref": "nixpkgs-unstable",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs_5": {
|
||||
"locked": {
|
||||
"lastModified": 1735554305,
|
||||
"narHash": "sha256-zExSA1i/b+1NMRhGGLtNfFGXgLtgo+dcuzHzaWA6w3Q=",
|
||||
"owner": "nixos",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "0e82ab234249d8eee3e8c91437802b32c74bb3fd",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nixos",
|
||||
"ref": "nixpkgs-unstable",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixtest": {
|
||||
"locked": {
|
||||
"dir": "lib",
|
||||
"lastModified": 1748945995,
|
||||
"narHash": "sha256-OWflapMq78nCUT7N0vS/AuK4E8y7p8oh0zjnDioJ4Lw=",
|
||||
"owner": "technofab",
|
||||
"repo": "nixtest",
|
||||
"rev": "392e8796f386373a36aecd3216925accf2714a1a",
|
||||
"lastModified": 1756370106,
|
||||
"narHash": "sha256-l84ojcHuQWBwn4BRxQsMMfQpcq/Az/sHh/hSqFgVtyg=",
|
||||
"owner": "rensa-nix",
|
||||
"repo": "core",
|
||||
"rev": "9c1a29fa9ba7cbbb78b9e47eb8afbcd29303a3b4",
|
||||
"type": "gitlab"
|
||||
},
|
||||
"original": {
|
||||
"dir": "lib",
|
||||
"owner": "technofab",
|
||||
"ref": "1.0.0",
|
||||
"repo": "nixtest",
|
||||
"owner": "rensa-nix",
|
||||
"repo": "core",
|
||||
"type": "gitlab"
|
||||
}
|
||||
},
|
||||
"root": {
|
||||
"inputs": {
|
||||
"devenv": "devenv",
|
||||
"flake-parts": "flake-parts_2",
|
||||
"mkdocs-material-umami": "mkdocs-material-umami",
|
||||
"nix-mkdocs": "nix-mkdocs",
|
||||
"nixpkgs": "nixpkgs_4",
|
||||
"nixtest": "nixtest",
|
||||
"systems": "systems",
|
||||
"treefmt-nix": "treefmt-nix"
|
||||
}
|
||||
},
|
||||
"systems": {
|
||||
"locked": {
|
||||
"lastModified": 1689347949,
|
||||
"narHash": "sha256-12tWmuL2zgBgZkdoB6qXZsgJEH9LR3oUgpaQq2RbI80=",
|
||||
"owner": "nix-systems",
|
||||
"repo": "default-linux",
|
||||
"rev": "31732fcf5e8fea42e59c2488ad31a0e651500f68",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-systems",
|
||||
"repo": "default-linux",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"treefmt-nix": {
|
||||
"inputs": {
|
||||
"nixpkgs": "nixpkgs_5"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1743677901,
|
||||
"narHash": "sha256-eWZln+k+L/VHO69tUTzEmgeDWNQNKIpSUa9nqQgBrSE=",
|
||||
"owner": "numtide",
|
||||
"repo": "treefmt-nix",
|
||||
"rev": "57dabe2a6255bd6165b2437ff6c2d1f6ee78421a",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "numtide",
|
||||
"repo": "treefmt-nix",
|
||||
"type": "github"
|
||||
"nixpkgs": "nixpkgs",
|
||||
"ren": "ren"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
|||
327
flake.nix
327
flake.nix
|
|
@ -1,304 +1,37 @@
|
|||
{
|
||||
inputs = {
|
||||
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
||||
ren.url = "gitlab:rensa-nix/core?dir=lib";
|
||||
};
|
||||
|
||||
outputs = {
|
||||
flake-parts,
|
||||
systems,
|
||||
self,
|
||||
ren,
|
||||
...
|
||||
} @ inputs:
|
||||
flake-parts.lib.mkFlake {inherit inputs;} {
|
||||
imports = [
|
||||
inputs.devenv.flakeModule
|
||||
inputs.treefmt-nix.flakeModule
|
||||
inputs.nix-mkdocs.flakeModule
|
||||
inputs.nixtest.flakeModule
|
||||
./lib/flakeModule.nix
|
||||
ren.buildWith
|
||||
{
|
||||
inherit inputs;
|
||||
cellsFrom = ./nix;
|
||||
transformInputs = system: i:
|
||||
i
|
||||
// {
|
||||
pkgs = import i.nixpkgs {inherit system;};
|
||||
};
|
||||
cellBlocks = with ren.blocks; [
|
||||
(simple "devShells")
|
||||
(simple "pkgs")
|
||||
(simple "tests")
|
||||
(simple "docs")
|
||||
(simple "ci")
|
||||
];
|
||||
}
|
||||
{
|
||||
packages = ren.select self [
|
||||
["repo" "tests"]
|
||||
["repo" "docs"]
|
||||
["repo" "ci" "packages"]
|
||||
["packages" "pkgs"]
|
||||
];
|
||||
systems = import systems;
|
||||
flake = {};
|
||||
perSystem = {
|
||||
pkgs,
|
||||
config,
|
||||
system,
|
||||
...
|
||||
}: rec {
|
||||
imports = [
|
||||
./tests
|
||||
];
|
||||
treefmt = {
|
||||
projectRootFile = "flake.nix";
|
||||
programs = {
|
||||
alejandra.enable = true;
|
||||
mdformat.enable = true;
|
||||
yamlfmt.enable = true;
|
||||
};
|
||||
settings.formatter = {
|
||||
yamlfmt.excludes = ["templates/nix-gitlab-ci.yml"];
|
||||
mdformat.command = let
|
||||
pkg = pkgs.python3.withPackages (p: [
|
||||
p.mdformat
|
||||
p.mdformat-mkdocs
|
||||
]);
|
||||
in "${pkg}/bin/mdformat";
|
||||
};
|
||||
};
|
||||
devenv.shells.default = {
|
||||
containers = pkgs.lib.mkForce {};
|
||||
packages = with pkgs; [dive skopeo];
|
||||
|
||||
pre-commit = {
|
||||
hooks = {
|
||||
treefmt = {
|
||||
enable = true;
|
||||
packageOverrides.treefmt = config.treefmt.build.wrapper;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
doc = {
|
||||
path = ./docs;
|
||||
deps = pp: [
|
||||
pp.mkdocs-material
|
||||
(pp.callPackage inputs.mkdocs-material-umami {})
|
||||
];
|
||||
config = {
|
||||
site_name = "Nix GitLab CI";
|
||||
repo_name = "TECHNOFAB/nix-gitlab-ci";
|
||||
repo_url = "https://gitlab.com/TECHNOFAB/nix-gitlab-ci";
|
||||
edit_uri = "edit/main/docs/";
|
||||
theme = {
|
||||
name = "material";
|
||||
features = ["content.code.copy" "content.action.edit"];
|
||||
icon.repo = "simple/gitlab";
|
||||
logo = "images/logo.png";
|
||||
favicon = "images/favicon.png";
|
||||
palette = [
|
||||
{
|
||||
scheme = "default";
|
||||
media = "(prefers-color-scheme: light)";
|
||||
primary = "deep orange";
|
||||
accent = "orange";
|
||||
toggle = {
|
||||
icon = "material/brightness-7";
|
||||
name = "Switch to dark mode";
|
||||
};
|
||||
}
|
||||
{
|
||||
scheme = "slate";
|
||||
media = "(prefers-color-scheme: dark)";
|
||||
primary = "deep orange";
|
||||
accent = "orange";
|
||||
toggle = {
|
||||
icon = "material/brightness-4";
|
||||
name = "Switch to light mode";
|
||||
};
|
||||
}
|
||||
];
|
||||
};
|
||||
plugins = ["search" "material-umami"];
|
||||
nav = [
|
||||
{"Introduction" = "index.md";}
|
||||
{"Setup" = "setup.md";}
|
||||
{"Usage" = "usage.md";}
|
||||
{"CI/CD Component" = "cicd_component.md";}
|
||||
{"Environment Variables" = "environment_variables.md";}
|
||||
{"Caching" = "caching.md";}
|
||||
{"Multiple Pipelines" = "multi_pipeline.md";}
|
||||
{"Utilities" = "utilities.md";}
|
||||
{"Kubernetes Runner Example" = "kubernetes_runner.md";}
|
||||
{"Example Configs" = "examples.md";}
|
||||
];
|
||||
markdown_extensions = [
|
||||
{
|
||||
"pymdownx.highlight".pygments_lang_class = true;
|
||||
}
|
||||
"pymdownx.inlinehilite"
|
||||
"pymdownx.snippets"
|
||||
"pymdownx.superfences"
|
||||
"fenced_code"
|
||||
"admonition"
|
||||
];
|
||||
extra.analytics = {
|
||||
provider = "umami";
|
||||
site_id = "28f7c904-db22-4c2b-9ee4-ed42e14b6db9";
|
||||
src = "https://analytics.tf/umami";
|
||||
domains = "nix-gitlab-ci.projects.tf";
|
||||
feedback = {
|
||||
title = "Was this page helpful?";
|
||||
ratings = [
|
||||
{
|
||||
icon = "material/thumb-up-outline";
|
||||
name = "This page is helpful";
|
||||
data = "good";
|
||||
note = "Thanks for your feedback!";
|
||||
}
|
||||
{
|
||||
icon = "material/thumb-down-outline";
|
||||
name = "This page could be improved";
|
||||
data = "bad";
|
||||
note = "Thanks for your feedback! Please leave feedback by creating an issue :)";
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
# should set the "default" pipeline
|
||||
ci = {
|
||||
stages = ["test" "nixtest" "build" "deploy"];
|
||||
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\""
|
||||
];
|
||||
};
|
||||
# -- actually useful jobs --
|
||||
"docs" = {
|
||||
stage = "build";
|
||||
script = [
|
||||
# sh
|
||||
''
|
||||
nix build .#docs:default
|
||||
mkdir -p public
|
||||
cp -r result/. public/
|
||||
''
|
||||
];
|
||||
artifacts.paths = ["public"];
|
||||
};
|
||||
"pages" = {
|
||||
nix.enable = false;
|
||||
image = "alpine:latest";
|
||||
stage = "deploy";
|
||||
script = ["true"];
|
||||
artifacts.paths = ["public"];
|
||||
rules = [
|
||||
{
|
||||
"if" = "$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH";
|
||||
}
|
||||
];
|
||||
};
|
||||
"nixtest" = {
|
||||
stage = "nixtest";
|
||||
script = [
|
||||
# sh
|
||||
"nix run .#nixtests:run -- --junit=junit.xml --pure"
|
||||
];
|
||||
allow_failure = true;
|
||||
artifacts = {
|
||||
when = "always";
|
||||
reports.junit = "junit.xml";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
pipelines."non-default" = {
|
||||
stages = ["test"];
|
||||
jobs = {
|
||||
"test" = {
|
||||
stage = "test";
|
||||
script = [
|
||||
"echo Hello from another pipeline"
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
packages = let
|
||||
setupScript = pkgs.writeShellScriptBin "setup_nix_ci" (builtins.readFile ./scripts/setup_nix_ci.sh);
|
||||
finalizeScript = pkgs.writeShellScriptBin "finalize_nix_ci" (builtins.readFile ./scripts/finalize_nix_ci.sh);
|
||||
in {
|
||||
setup-script = setupScript;
|
||||
finalize-script = finalizeScript;
|
||||
image = pkgs.dockerTools.buildImage {
|
||||
name = "nix-ci";
|
||||
fromImage = let
|
||||
hashes = {
|
||||
"x86_64-linux" = "sha256-kJ7dqje5o1KPr3RDZ7/THbhMSoiCU1C/7HshDrNfwnM=";
|
||||
"aarch64-linux" = "sha256-jz+Z3Ji+hy5d9ImOh/YOKCqy9P9/cseSov+5J/O95bg=";
|
||||
};
|
||||
# check digest of tags like nixos-24.11-aarch64-linux etc.
|
||||
digests = {
|
||||
"x86_64-linux" = "sha256:345f210dea4cbd049e2d01d13159c829066dfb6e273cdd49ea878186d17b19f7";
|
||||
"aarch64-linux" = "sha256:66163fdf446d851416dd4e9be28c0794d9c2550214a57a846957699a3f5747f6";
|
||||
};
|
||||
hash = hashes.${system} or (throw "Unsupported system");
|
||||
imageDigest = digests.${system} or (throw "Unsupported system");
|
||||
in
|
||||
pkgs.dockerTools.pullImage {
|
||||
imageName = "nixpkgs/nix-flakes";
|
||||
inherit hash imageDigest;
|
||||
};
|
||||
copyToRoot = pkgs.buildEnv {
|
||||
name = "image-root";
|
||||
paths = with pkgs;
|
||||
[
|
||||
gitMinimal
|
||||
gnugrep
|
||||
gnused
|
||||
coreutils
|
||||
diffutils
|
||||
cachix
|
||||
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";
|
||||
nix-mkdocs.url = "gitlab:technofab/nixmkdocs?dir=lib";
|
||||
mkdocs-material-umami.url = "gitlab:technofab/mkdocs-material-umami";
|
||||
nixtest.url = "gitlab:technofab/nixtest/1.0.0?dir=lib";
|
||||
};
|
||||
|
||||
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="
|
||||
];
|
||||
};
|
||||
}
|
||||
|
|
|
|||
1
lib/VERSION
Normal file
1
lib/VERSION
Normal file
|
|
@ -0,0 +1 @@
|
|||
3.0.0
|
||||
|
|
@ -1,8 +1,29 @@
|
|||
args: {
|
||||
helpers = import ./helpers.nix args;
|
||||
jobDeps = import ./jobDeps.nix args;
|
||||
jobRun = import ./jobRun.nix args;
|
||||
jobPatch = import ./jobPatch.nix args;
|
||||
pipeline = import ./pipeline.nix args;
|
||||
utils = import ./utils.nix args;
|
||||
}
|
||||
args: let
|
||||
# allow passing just pkgs aswell for convenience
|
||||
lib = args.lib or args.pkgs.lib;
|
||||
# makes it optional to pass if it's not explicitly needed
|
||||
pkgs = args.pkgs or (throw "[nix-gitlab-ci] pkgs argument was used but not set, please pass it");
|
||||
inherit (lib) evalModules trimWith;
|
||||
|
||||
impl = import ./impl {inherit lib pkgs cilib;};
|
||||
|
||||
cilib = {
|
||||
inherit (impl) helpers modules mkPipeline mkJobRun mkJobDeps mkJobPatched;
|
||||
utils = import ./utils.nix {inherit pkgs;};
|
||||
version = trimWith {
|
||||
start = true;
|
||||
end = true;
|
||||
} (builtins.readFile ./VERSION);
|
||||
|
||||
mkCI = config:
|
||||
(evalModules {
|
||||
modules = [
|
||||
cilib.modules.nixCiSubmodule
|
||||
{
|
||||
inherit config;
|
||||
}
|
||||
];
|
||||
}).config;
|
||||
};
|
||||
in
|
||||
cilib
|
||||
|
|
|
|||
|
|
@ -1,8 +1,6 @@
|
|||
{
|
||||
description = "Nix-GitLab-CI lib";
|
||||
|
||||
outputs = {...}: {
|
||||
flakeModule = import ./flakeModule.nix;
|
||||
lib = import ./default.nix;
|
||||
outputs = _i: {
|
||||
lib = import ./.;
|
||||
flakeModule = ./flakeModule.nix;
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,163 +10,15 @@
|
|||
...
|
||||
}: let
|
||||
cilib = import ./. {inherit lib pkgs;};
|
||||
inherit (cilib.pipeline) mkPipeline;
|
||||
inherit (lib) types mkOption;
|
||||
|
||||
cfg = config.ci.config;
|
||||
|
||||
subType = options: types.submodule {inherit options;};
|
||||
mkNullOption = type:
|
||||
mkOption {
|
||||
default = null;
|
||||
type = types.nullOr type;
|
||||
};
|
||||
|
||||
configType = subType {
|
||||
nix-jobs-by-default = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = "Handle jobs nix-based by default or via opt-in (in a job set nix.enable = true) if false";
|
||||
};
|
||||
};
|
||||
jobType = subType {
|
||||
# nix ci opts
|
||||
nix = mkOption {
|
||||
type = subType {
|
||||
enable = mkOption {
|
||||
type = types.bool;
|
||||
default = cfg.nix-jobs-by-default;
|
||||
description = "Handle this job as a nix job";
|
||||
};
|
||||
deps = mkOption {
|
||||
type = types.listOf types.package;
|
||||
default = [];
|
||||
description = "Dependencies/packages to install for this job";
|
||||
};
|
||||
enable-runner-cache = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Cache this job using the GitLab Runner cache.
|
||||
Warning: useful for tiny jobs, but most of the time it just takes an eternity.
|
||||
'';
|
||||
};
|
||||
runner-cache-key = mkOption {
|
||||
type = types.str;
|
||||
default = "$CI_JOB_NAME-$CI_COMMIT_REF_SLUG";
|
||||
description = "Cache key to use for the runner nix cache. Requires enable-runner-cache = true";
|
||||
};
|
||||
};
|
||||
default = {};
|
||||
description = "Configure Nix Gitlab CI for each job individually";
|
||||
};
|
||||
# gitlab opts
|
||||
script = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [];
|
||||
};
|
||||
stage = mkOption {
|
||||
type = types.str;
|
||||
default = "test";
|
||||
};
|
||||
image = mkOption {
|
||||
type = types.str;
|
||||
default = "$NIX_CI_IMAGE";
|
||||
};
|
||||
after_script = mkNullOption (types.listOf types.str);
|
||||
allow_failure = mkNullOption (types.either types.attrs types.bool);
|
||||
artifacts = mkNullOption (types.attrs);
|
||||
before_script = mkNullOption (types.listOf types.str);
|
||||
cache = mkNullOption (types.either (types.listOf types.attrs) types.attrs);
|
||||
coverage = mkNullOption (types.str);
|
||||
dependencies = mkNullOption (types.listOf types.str);
|
||||
environment = mkNullOption (types.either types.attrs types.str);
|
||||
extends = mkNullOption (types.str);
|
||||
hooks = mkNullOption (types.attrs);
|
||||
id_tokens = mkNullOption (types.attrs);
|
||||
"inherit" = mkNullOption (types.attrs);
|
||||
interruptible = mkNullOption (types.bool);
|
||||
needs = mkNullOption (types.listOf (types.either types.str types.attrs));
|
||||
publish = mkNullOption (types.str);
|
||||
pages = mkNullOption (types.attrs);
|
||||
parallel = mkNullOption (types.either types.int types.attrs);
|
||||
release = mkNullOption (types.attrs);
|
||||
retry = mkNullOption (types.either types.int types.attrs);
|
||||
rules = mkNullOption (types.listOf types.attrs);
|
||||
resource_group = mkNullOption (types.str);
|
||||
secrets = mkNullOption (types.attrs);
|
||||
services = mkNullOption (types.listOf types.attrs);
|
||||
start_in = mkNullOption (types.str);
|
||||
tags = mkNullOption (types.listOf types.str);
|
||||
timeout = mkNullOption (types.str);
|
||||
variables = mkNullOption (types.attrs);
|
||||
when = mkNullOption (types.str);
|
||||
};
|
||||
|
||||
ciType = subType {
|
||||
config = mkOption {
|
||||
type = configType;
|
||||
description = ''
|
||||
Configuration options for the nix part itself
|
||||
'';
|
||||
default = {};
|
||||
};
|
||||
image = mkNullOption (types.str);
|
||||
variables = mkNullOption (types.attrs);
|
||||
default = mkNullOption (types.attrs);
|
||||
stages = mkNullOption (types.listOf types.str);
|
||||
include = mkNullOption (types.attrs);
|
||||
workflow = mkNullOption (types.attrs);
|
||||
jobs = mkOption {
|
||||
type = types.lazyAttrsOf jobType;
|
||||
default = {};
|
||||
};
|
||||
};
|
||||
in {
|
||||
options = {
|
||||
pipelines = mkOption {
|
||||
type = types.lazyAttrsOf ciType;
|
||||
description = ''
|
||||
Create multiple GitLab CI pipelines.
|
||||
|
||||
See README.md for more information about how a pipeline is selected.
|
||||
'';
|
||||
default = {};
|
||||
apply = op: let
|
||||
# NOTE: show warning if "default" is set and config.ci is not {}
|
||||
legacyMode = config.ci != {};
|
||||
defaultExists = builtins.hasAttr "default" op;
|
||||
value =
|
||||
{
|
||||
"default" = config.ci;
|
||||
}
|
||||
// op;
|
||||
in
|
||||
if defaultExists && legacyMode
|
||||
then builtins.trace "Warning: config.ci is overwritten by pipelines.default" value
|
||||
else value;
|
||||
};
|
||||
ci = mkOption {
|
||||
type = ciType;
|
||||
description = ''
|
||||
Note: this is a shorthand for writing `pipelines."default"`
|
||||
|
||||
Generate a Gitlab CI configuration which can be used to trigger a child pipeline.
|
||||
This will inject code which pre-downloads the nix deps before each job and adds them to PATH.
|
||||
'';
|
||||
type = types.submodule cilib.modules.nixCiSubmodule;
|
||||
default = {};
|
||||
};
|
||||
};
|
||||
|
||||
config.legacyPackages = lib.fold (pipeline: acc: acc // pipeline) {} (
|
||||
map (
|
||||
pipeline_name:
|
||||
(mkPipeline {
|
||||
pipeline = config.pipelines."${pipeline_name}";
|
||||
name = pipeline_name;
|
||||
}).packages
|
||||
) (builtins.attrNames config.pipelines)
|
||||
);
|
||||
config.legacyPackages = config.ci.packages;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,49 +0,0 @@
|
|||
{lib, ...} @ args: let
|
||||
inherit (lib) isAttrs filterAttrs mapAttrs;
|
||||
in rec {
|
||||
prepend = key: arr: job:
|
||||
job
|
||||
// lib.optionalAttrs (job.nix.enable or false) {
|
||||
${key} =
|
||||
arr
|
||||
++ (job.${key} or []);
|
||||
};
|
||||
append = key: arr: job:
|
||||
job
|
||||
// lib.optionalAttrs (job.nix.enable or false) {
|
||||
${key} = (job.${key} or []) ++ arr;
|
||||
};
|
||||
prependToBeforeScript = prepend "before_script";
|
||||
appendToAfterScript = append "after_script";
|
||||
|
||||
# json is also valid yaml and this removes dependency on jq and/or remarshal
|
||||
# (used in pkgs.formats.json and pkgs.formats.yaml respectively)
|
||||
toYaml = name: value: builtins.toFile name (builtins.toJSON value);
|
||||
|
||||
customMapAttrs = cb: set: builtins.listToAttrs (builtins.map (key: cb key (builtins.getAttr key set)) (builtins.attrNames set));
|
||||
|
||||
filterAttrsRec = pred: v:
|
||||
if isAttrs v
|
||||
then filterAttrs pred (mapAttrs (path: filterAttrsRec pred) v)
|
||||
else v;
|
||||
|
||||
# filter job's variables to either only those containing store paths
|
||||
# or those that do not
|
||||
filterJobVariables = nix: job:
|
||||
lib.concatMapAttrs (
|
||||
name: value:
|
||||
lib.optionalAttrs ((lib.hasInfix "/nix/store/" value) == nix) {
|
||||
${name} = value;
|
||||
}
|
||||
)
|
||||
(job.variables or {});
|
||||
|
||||
# args.pkgs so "pkgs" does not need to be passed all the time
|
||||
stdenvMinimal = args.pkgs.stdenvNoCC.override {
|
||||
cc = null;
|
||||
preHook = "";
|
||||
allowedRequisites = null;
|
||||
initialPath = with args.pkgs; [coreutils findutils];
|
||||
extraNativeBuildInputs = [];
|
||||
};
|
||||
}
|
||||
12
lib/impl/default.nix
Normal file
12
lib/impl/default.nix
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
pkgs,
|
||||
lib,
|
||||
cilib,
|
||||
}: rec {
|
||||
helpers = import ./helpers.nix {inherit lib pkgs;};
|
||||
mkJobDeps = import ./jobDeps.nix {inherit lib helpers;};
|
||||
mkJobRun = import ./jobRun.nix {inherit lib pkgs helpers;};
|
||||
mkJobPatched = import ./jobPatched.nix {inherit lib helpers;};
|
||||
mkPipeline = import ./pipeline.nix {inherit lib helpers mkJobDeps mkJobRun mkJobPatched;};
|
||||
modules = import ./modules {inherit lib cilib;};
|
||||
}
|
||||
123
lib/impl/helpers.nix
Normal file
123
lib/impl/helpers.nix
Normal file
|
|
@ -0,0 +1,123 @@
|
|||
{
|
||||
pkgs,
|
||||
lib,
|
||||
} @ args: let
|
||||
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 []);
|
||||
};
|
||||
append = key: arr: job: {
|
||||
${key} = (job.${key} or []) ++ arr;
|
||||
};
|
||||
prependToBeforeScript = prepend "before_script";
|
||||
appendToAfterScript = append "after_script";
|
||||
|
||||
# json is also valid yaml and this removes dependency on jq and/or remarshal
|
||||
# (used in pkgs.formats.json and pkgs.formats.yaml respectively)
|
||||
toYaml = name: value:
|
||||
pipe value [
|
||||
builtins.toJSON
|
||||
builtins.unsafeDiscardOutputDependency
|
||||
builtins.unsafeDiscardStringContext
|
||||
(builtins.toFile name)
|
||||
];
|
||||
toYamlPretty = (pkgs.formats.yaml {}).generate;
|
||||
|
||||
customMapAttrs = cb: set: builtins.listToAttrs (builtins.map (key: cb key (builtins.getAttr key set)) (builtins.attrNames set));
|
||||
|
||||
filterAttrsRec = pred: v:
|
||||
if isAttrs v
|
||||
then filterAttrs pred (mapAttrs (_path: filterAttrsRec pred) v)
|
||||
else v;
|
||||
|
||||
# filter job's variables to either only those containing store paths
|
||||
# or those that do not
|
||||
filterJobVariables = shouldContain: job:
|
||||
concatMapAttrs (
|
||||
name: value:
|
||||
optionalAttrs ((hasInfix "/nix/store/" value) == shouldContain) {
|
||||
${name} = value;
|
||||
}
|
||||
)
|
||||
(job.variables or {});
|
||||
|
||||
deepMerge = lhs: rhs:
|
||||
lhs
|
||||
// rhs
|
||||
// (builtins.mapAttrs (
|
||||
rName: rValue: let
|
||||
lValue = lhs.${rName} or null;
|
||||
in
|
||||
if builtins.isAttrs lValue && builtins.isAttrs rValue
|
||||
then deepMerge lValue rValue
|
||||
else if builtins.isList lValue && builtins.isList rValue
|
||||
then lValue ++ rValue
|
||||
else rValue
|
||||
)
|
||||
rhs);
|
||||
|
||||
unsetType = mkOptionType {
|
||||
name = "unset";
|
||||
description = "unset";
|
||||
descriptionClass = "noun";
|
||||
check = _value: true;
|
||||
};
|
||||
unset = {
|
||||
_type = "unset";
|
||||
};
|
||||
isUnset = isType "unset";
|
||||
unsetOr = typ:
|
||||
(types.either unsetType typ)
|
||||
// {
|
||||
inherit (typ) description getSubOptions;
|
||||
};
|
||||
mkUnsetOption = opts:
|
||||
mkOption (opts
|
||||
// {
|
||||
type = unsetOr opts.type;
|
||||
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
|
||||
then let
|
||||
filteredAttrs = builtins.mapAttrs (_n: filterUnset) value;
|
||||
in
|
||||
filterAttrs (_name: value: (!isUnset value)) filteredAttrs
|
||||
else if builtins.isList value
|
||||
then builtins.filter (elem: !isUnset elem) (map filterUnset value)
|
||||
else value;
|
||||
|
||||
# args.pkgs so "pkgs" does not need to be passed all the time
|
||||
stdenvMinimal = args.pkgs.stdenvNoCC.override {
|
||||
cc = null;
|
||||
preHook = "";
|
||||
allowedRequisites = null;
|
||||
initialPath = with args.pkgs; [coreutils findutils];
|
||||
extraNativeBuildInputs = [];
|
||||
};
|
||||
}
|
||||
|
|
@ -1,21 +1,21 @@
|
|||
{
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
helpers,
|
||||
}: let
|
||||
cilib = import ./. {inherit lib pkgs;};
|
||||
inherit (cilib.helpers) filterJobVariables stdenvMinimal;
|
||||
in {
|
||||
mkJobDeps = {
|
||||
inherit (lib) concatLines mapAttrsToList makeBinPath;
|
||||
inherit (helpers) filterJobVariables stdenvMinimal;
|
||||
in
|
||||
{
|
||||
key,
|
||||
job,
|
||||
nixConfig,
|
||||
}: let
|
||||
variablesWithStorePaths = filterJobVariables true job;
|
||||
variableExports = lib.concatLines (
|
||||
lib.mapAttrsToList (name: value: "export ${name}=\"${value}\"") variablesWithStorePaths
|
||||
variableExports = concatLines (
|
||||
mapAttrsToList (name: value: "export ${name}=\"${value}\"") variablesWithStorePaths
|
||||
);
|
||||
script = ''
|
||||
export PATH="${lib.makeBinPath (job.nix.deps or [])}:$PATH";
|
||||
export PATH="${makeBinPath (nixConfig.deps or [])}:$PATH";
|
||||
# variables containing nix derivations:
|
||||
${variableExports}
|
||||
'';
|
||||
|
|
@ -32,5 +32,4 @@ in {
|
|||
passthru = {
|
||||
inherit script;
|
||||
};
|
||||
};
|
||||
}
|
||||
}
|
||||
43
lib/impl/jobPatched.nix
Normal file
43
lib/impl/jobPatched.nix
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
{
|
||||
lib,
|
||||
helpers,
|
||||
}: let
|
||||
inherit (lib) toList optionalAttrs optional;
|
||||
inherit (helpers) prependToBeforeScript appendToAfterScript filterJobVariables;
|
||||
in
|
||||
{
|
||||
key,
|
||||
job,
|
||||
pipelineName,
|
||||
nixConfig,
|
||||
}:
|
||||
(builtins.removeAttrs job ["variables" "cache"])
|
||||
// (optionalAttrs nixConfig.enable (
|
||||
(prependToBeforeScript ["source setup_nix_ci \"gitlab-ci:pipeline:${pipelineName}:job-deps:${key}\""] job)
|
||||
// (appendToAfterScript ["finalize_nix_ci"] job)
|
||||
))
|
||||
// optionalAttrs nixConfig.enable (
|
||||
(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;
|
||||
})
|
||||
)
|
||||
|
|
@ -1,19 +1,19 @@
|
|||
{
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
helpers,
|
||||
}: let
|
||||
cilib = import ./. {inherit lib pkgs;};
|
||||
inherit (cilib.helpers) filterJobVariables;
|
||||
in {
|
||||
mkJobRun = {
|
||||
inherit (lib) concatLines mapAttrsToList getExe;
|
||||
inherit (helpers) filterJobVariables;
|
||||
in
|
||||
{
|
||||
key,
|
||||
job,
|
||||
jobDeps,
|
||||
}: let
|
||||
variablesWithoutStorePaths = filterJobVariables false job;
|
||||
variableExports = lib.concatLines (
|
||||
lib.mapAttrsToList (name: value: "export ${name}=\"${value}\"") variablesWithoutStorePaths
|
||||
variableExports = concatLines (
|
||||
mapAttrsToList (name: value: "export ${name}=\"${value}\"") variablesWithoutStorePaths
|
||||
);
|
||||
sandboxHelper = pkgs.writeShellScriptBin "gitlab-ci-job-sandbox-helper" (builtins.readFile ./sandbox_helper.sh);
|
||||
actualJobScript = pkgs.writeShellScript "gitlab-ci-job:${key}:raw" ''
|
||||
|
|
@ -24,25 +24,24 @@ in {
|
|||
# run before_script, script and after_script
|
||||
echo -e "\e[32mRunning before_script...\e[0m"
|
||||
set -x
|
||||
${lib.concatLines (job.before_script or [])}
|
||||
${concatLines (job.before_script or [])}
|
||||
{ set +x; } 2>/dev/null
|
||||
echo -e "\e[32mRunning script...\e[0m"
|
||||
set -x
|
||||
${lib.concatLines job.script}
|
||||
${concatLines job.script}
|
||||
{ set +x; } 2>/dev/null
|
||||
echo -e "\e[32mRunning after_script...\e[0m"
|
||||
set -x
|
||||
${lib.concatLines (job.after_script or [])}
|
||||
${concatLines (job.after_script or [])}
|
||||
{ set +x; } 2>/dev/null
|
||||
'';
|
||||
in
|
||||
# this way the sandbox helper just needs to be built once
|
||||
pkgs.writeShellScriptBin "gitlab-ci-job:${key}" ''
|
||||
exec ${lib.getExe sandboxHelper} ${actualJobScript} $@
|
||||
exec ${getExe sandboxHelper} ${actualJobScript} $@
|
||||
''
|
||||
// {
|
||||
passthru = {
|
||||
inherit jobDeps actualJobScript;
|
||||
};
|
||||
};
|
||||
}
|
||||
}
|
||||
32
lib/impl/modules/default.nix
Normal file
32
lib/impl/modules/default.nix
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
{
|
||||
lib,
|
||||
cilib,
|
||||
}: rec {
|
||||
inherit
|
||||
(import ./root.nix {
|
||||
inherit lib pipelineSubmodule soonixSubmodule;
|
||||
})
|
||||
configSubmodule
|
||||
nixCiSubmodule
|
||||
;
|
||||
inherit
|
||||
(import ./pipeline.nix {
|
||||
inherit lib cilib jobSubmodule;
|
||||
})
|
||||
pipelineConfigSubmodule
|
||||
pipelineSubmodule
|
||||
;
|
||||
inherit
|
||||
(import ./job.nix {
|
||||
inherit lib cilib;
|
||||
})
|
||||
jobConfigSubmodule
|
||||
jobSubmodule
|
||||
;
|
||||
inherit
|
||||
(import ./soonix.nix {
|
||||
inherit lib cilib;
|
||||
})
|
||||
soonixSubmodule
|
||||
;
|
||||
}
|
||||
663
lib/impl/modules/job.nix
Normal file
663
lib/impl/modules/job.nix
Normal file
|
|
@ -0,0 +1,663 @@
|
|||
{
|
||||
lib,
|
||||
cilib,
|
||||
...
|
||||
}: let
|
||||
inherit (lib) mkOption types filterAttrs;
|
||||
inherit (cilib.helpers) filterUnset mkUnsetOption eitherWithSubOptions;
|
||||
in rec {
|
||||
jobConfigSubmodule = {pipelineConfig, ...}: {
|
||||
options = {
|
||||
enable = mkOption {
|
||||
description = ''
|
||||
Transform this job to a nix-configured one.
|
||||
'';
|
||||
type = types.bool;
|
||||
default = pipelineConfig.nixJobsByDefault;
|
||||
};
|
||||
deps = mkOption {
|
||||
description = ''
|
||||
Dependencies to inject into the job before running it.
|
||||
'';
|
||||
type = types.listOf types.package;
|
||||
default = [];
|
||||
};
|
||||
enableRunnerCache = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Cache this job using the GitLab Runner cache.
|
||||
|
||||
!!! warning
|
||||
useful for tiny jobs, but most of the time it just takes an eternity.
|
||||
'';
|
||||
};
|
||||
runnerCacheKey = mkOption {
|
||||
type = types.str;
|
||||
default = "$CI_JOB_NAME-$CI_COMMIT_REF_SLUG";
|
||||
description = ''
|
||||
Cache key to use for the runner nix cache. Requires [`enableRunnerCache = true`](#pipelinesnamejobsnamenixenablerunnercache).
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
jobSubmodule = {
|
||||
name,
|
||||
config,
|
||||
pipelineName,
|
||||
pipelineConfig,
|
||||
...
|
||||
}: let
|
||||
#
|
||||
# GITLAB OPTIONS
|
||||
#
|
||||
gitlabOptions = {
|
||||
# see https://docs.gitlab.com/ci/yaml/
|
||||
after_script = mkUnsetOption {
|
||||
type = types.listOf types.str;
|
||||
description = ''
|
||||
Override a set of commands that are executed after job.
|
||||
|
||||
[Docs](https://docs.gitlab.com/ci/yaml/#after_script)
|
||||
'';
|
||||
};
|
||||
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 can’t 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 repository’s .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)
|
||||
'';
|
||||
};
|
||||
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)
|
||||
'';
|
||||
};
|
||||
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, it’s 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 it’s 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)
|
||||
'';
|
||||
};
|
||||
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)
|
||||
'';
|
||||
};
|
||||
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)
|
||||
'';
|
||||
};
|
||||
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)
|
||||
'';
|
||||
};
|
||||
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 job’s `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 {
|
||||
options =
|
||||
{
|
||||
nix = mkOption {
|
||||
description = ''
|
||||
Nix-GitLab-CI config options for this job.
|
||||
'';
|
||||
type = types.submoduleWith {
|
||||
modules = [jobConfigSubmodule];
|
||||
specialArgs.pipelineConfig = pipelineConfig;
|
||||
};
|
||||
default = {};
|
||||
};
|
||||
finalConfig = mkOption {
|
||||
description = ''
|
||||
Final configuration of this job. (readonly)
|
||||
'';
|
||||
readOnly = true;
|
||||
internal = true;
|
||||
type = types.attrs;
|
||||
};
|
||||
depsDrv = mkOption {
|
||||
description = ''
|
||||
Derivation containing all the dependencies of this job. (readonly)
|
||||
'';
|
||||
readOnly = true;
|
||||
internal = true;
|
||||
type = types.package;
|
||||
};
|
||||
runnerDrv = mkOption {
|
||||
description = ''
|
||||
Derivation containing the script for running the job locally. (readonly)
|
||||
'';
|
||||
readOnly = true;
|
||||
internal = true;
|
||||
type = types.package;
|
||||
};
|
||||
packages = mkOption {
|
||||
description = ''
|
||||
Final packages for this job, eg. for running the job or getting it's deps. (readonly)
|
||||
'';
|
||||
readOnly = true;
|
||||
internal = true;
|
||||
type = types.attrsOf types.package;
|
||||
};
|
||||
}
|
||||
// gitlabOptions;
|
||||
config = let
|
||||
attrsToKeep = builtins.attrNames gitlabOptions;
|
||||
in {
|
||||
finalConfig = cilib.mkJobPatched {
|
||||
key = name;
|
||||
job = filterUnset (filterAttrs (n: _v: builtins.elem n attrsToKeep) config);
|
||||
nixConfig = config.nix;
|
||||
inherit pipelineName;
|
||||
};
|
||||
depsDrv = cilib.mkJobDeps {
|
||||
key = name;
|
||||
job = config.finalConfig;
|
||||
nixConfig = config.nix;
|
||||
};
|
||||
runnerDrv = cilib.mkJobRun {
|
||||
key = name;
|
||||
job = config.finalConfig;
|
||||
jobDeps = config.depsDrv;
|
||||
};
|
||||
packages = {
|
||||
"gitlab-ci:pipeline:${pipelineName}:job-deps:${name}" = config.depsDrv;
|
||||
"gitlab-ci:pipeline:${pipelineName}:job:${name}" = config.runnerDrv;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
228
lib/impl/modules/pipeline.nix
Normal file
228
lib/impl/modules/pipeline.nix
Normal file
|
|
@ -0,0 +1,228 @@
|
|||
{
|
||||
lib,
|
||||
cilib,
|
||||
jobSubmodule,
|
||||
...
|
||||
}: let
|
||||
inherit (lib) mkOption types filterAttrs mergeAttrsList mapAttrs mkRenamedOptionModule literalExpression;
|
||||
inherit (cilib.helpers) filterUnset unset mkUnsetOption toYaml toYamlPretty eitherWithSubOptions;
|
||||
|
||||
pipelineConfigSubmodule = {rootConfig, ...}: {
|
||||
options = {
|
||||
nixJobsByDefault = mkOption {
|
||||
description = ''
|
||||
Whether to transform all jobs to nix-configured jobs by default.
|
||||
If false, you need to set `nix.enable` for each job you want to be transformed.
|
||||
'';
|
||||
type = types.bool;
|
||||
default = rootConfig.nixJobsByDefault;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
pipelineSubmodule = {
|
||||
name,
|
||||
config,
|
||||
rootConfig,
|
||||
...
|
||||
}: let
|
||||
#
|
||||
# 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 {
|
||||
# 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) variable’s 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 {
|
||||
description = ''
|
||||
Nix-GitLab-CI config options for this pipeline.
|
||||
'';
|
||||
type = types.submoduleWith {
|
||||
modules = [pipelineConfigSubmodule];
|
||||
specialArgs.rootConfig = rootConfig;
|
||||
};
|
||||
default = {};
|
||||
};
|
||||
finalConfig = mkOption {
|
||||
description = ''
|
||||
Final config of the pipeline. (readonly)
|
||||
'';
|
||||
readOnly = true;
|
||||
type = types.attrs;
|
||||
};
|
||||
packages = mkOption {
|
||||
description = ''
|
||||
Final packages for use in CI. (readonly)
|
||||
'';
|
||||
readOnly = true;
|
||||
type = types.attrsOf types.package;
|
||||
};
|
||||
# jobs are nested to make distinguishing them from other keys in the ci config easier
|
||||
jobs = mkOption {
|
||||
description = ''
|
||||
Jobs for this pipeline.
|
||||
'';
|
||||
type = types.attrsOf (types.submoduleWith {
|
||||
modules = [jobSubmodule];
|
||||
specialArgs = {
|
||||
pipelineName = name;
|
||||
pipelineConfig = config.nix;
|
||||
};
|
||||
});
|
||||
default = {};
|
||||
};
|
||||
}
|
||||
// gitlabOptions;
|
||||
config = let
|
||||
attrsToKeep = builtins.attrNames gitlabOptions;
|
||||
in {
|
||||
finalConfig =
|
||||
(filterUnset (filterAttrs (n: _v: builtins.elem n attrsToKeep) config))
|
||||
// mapAttrs (_name: value: value.finalConfig) config.jobs;
|
||||
packages =
|
||||
{
|
||||
"gitlab-ci:pipeline:${name}" = toYaml "gitlab-ci-config.json" config.finalConfig;
|
||||
"gitlab-ci:pipeline:${name}:pretty" = toYamlPretty "gitlab-ci-config.yml" config.finalConfig;
|
||||
}
|
||||
// mergeAttrsList (map (job: job.packages) (builtins.attrValues config.jobs));
|
||||
};
|
||||
};
|
||||
in {
|
||||
inherit pipelineSubmodule pipelineConfigSubmodule;
|
||||
}
|
||||
74
lib/impl/modules/root.nix
Normal file
74
lib/impl/modules/root.nix
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
{
|
||||
lib,
|
||||
soonixSubmodule,
|
||||
pipelineSubmodule,
|
||||
...
|
||||
}: let
|
||||
inherit (lib) mkOption types;
|
||||
in rec {
|
||||
configSubmodule = {
|
||||
options = {
|
||||
soonix = mkOption {
|
||||
description = ''
|
||||
Configure the soonix `.gitlab-ci.yml` generation.
|
||||
'';
|
||||
type = types.submodule soonixSubmodule;
|
||||
default = {};
|
||||
};
|
||||
nixJobsByDefault = mkOption {
|
||||
description = ''
|
||||
Whether to transform all jobs to nix-configured jobs by default.
|
||||
If false, you need to set [`nix.enable`](#pipelinesnamejobsnamenixenable)
|
||||
for each job you want to be transformed.
|
||||
'';
|
||||
type = types.bool;
|
||||
default = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
nixCiSubmodule = {config, ...}: {
|
||||
options = {
|
||||
config = mkOption {
|
||||
description = ''
|
||||
Configuration of Nix-GitLab-CI itself.
|
||||
'';
|
||||
type = types.submodule configSubmodule;
|
||||
default = {};
|
||||
};
|
||||
pipelines = mkOption {
|
||||
description = ''
|
||||
Defines all pipelines.
|
||||
'';
|
||||
type = types.attrsOf (types.submoduleWith {
|
||||
modules = [pipelineSubmodule];
|
||||
specialArgs.rootConfig = config.config;
|
||||
});
|
||||
default = {};
|
||||
};
|
||||
|
||||
packages = mkOption {
|
||||
description = ''
|
||||
Final packages for use in CI. (readonly)
|
||||
'';
|
||||
readOnly = true;
|
||||
type = types.attrsOf types.package;
|
||||
};
|
||||
soonix = mkOption {
|
||||
description = ''
|
||||
Soonix config for generating `.gitlab-ci.yml`. (readonly)
|
||||
|
||||
See [`config.soonix`](#configsoonix) for configuring this.
|
||||
'';
|
||||
readOnly = true;
|
||||
type = types.attrs;
|
||||
};
|
||||
};
|
||||
config = {
|
||||
packages = lib.fold (pipeline: acc: acc // pipeline) {} (
|
||||
map (pipeline: pipeline.packages) (builtins.attrValues config.pipelines)
|
||||
);
|
||||
soonix = config.config.soonix.finalConfig;
|
||||
};
|
||||
};
|
||||
}
|
||||
69
lib/impl/modules/soonix.nix
Normal file
69
lib/impl/modules/soonix.nix
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
{
|
||||
lib,
|
||||
cilib,
|
||||
...
|
||||
}: let
|
||||
inherit (lib) mkOption types;
|
||||
in {
|
||||
soonixSubmodule = {config, ...}: {
|
||||
options = {
|
||||
componentVersion = mkOption {
|
||||
description = ''
|
||||
CI/CD component version. Also get's passed to inputs → version.
|
||||
'';
|
||||
type = types.str;
|
||||
default = cilib.version;
|
||||
};
|
||||
componentUrl = mkOption {
|
||||
description = ''
|
||||
CI/CD component url.
|
||||
'';
|
||||
type = types.str;
|
||||
default = "gitlab.com/TECHNOFAB/nix-gitlab-ci/nix-gitlab-ci";
|
||||
};
|
||||
componentInputs = mkOption {
|
||||
description = ''
|
||||
Extra inputs to pass to the CI/CD component.
|
||||
'';
|
||||
type = types.attrs;
|
||||
default = {};
|
||||
};
|
||||
extraData = mkOption {
|
||||
description = ''
|
||||
Extra data to include in the `.gitlab-ci.yml` file.
|
||||
'';
|
||||
type = types.attrs;
|
||||
default = {};
|
||||
};
|
||||
|
||||
finalConfig = mkOption {
|
||||
internal = true;
|
||||
type = types.attrs;
|
||||
};
|
||||
};
|
||||
config.finalConfig = {
|
||||
opts.format = "yaml";
|
||||
hook = {
|
||||
mode = "copy";
|
||||
gitignore = false;
|
||||
};
|
||||
output = ".gitlab-ci.yml";
|
||||
generator = "nix";
|
||||
data =
|
||||
cilib.helpers.deepMerge
|
||||
{
|
||||
include = [
|
||||
{
|
||||
component = "${config.componentUrl}@${config.componentVersion}";
|
||||
inputs =
|
||||
{
|
||||
version = config.componentVersion;
|
||||
}
|
||||
// config.componentInputs;
|
||||
}
|
||||
];
|
||||
}
|
||||
config.extraData;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
@ -1,20 +1,20 @@
|
|||
{
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
helpers,
|
||||
mkJobDeps,
|
||||
mkJobRun,
|
||||
mkJobPatched,
|
||||
}: let
|
||||
cilib = import ./. {inherit lib pkgs;};
|
||||
inherit (cilib.helpers) filterAttrsRec customMapAttrs toYaml;
|
||||
inherit (cilib.jobDeps) mkJobDeps;
|
||||
inherit (cilib.jobRun) mkJobRun;
|
||||
inherit (cilib.jobPatch) mkJobPatched;
|
||||
in {
|
||||
mkPipeline = {
|
||||
inherit (lib) assertMsg;
|
||||
inherit (helpers) filterAttrsRec customMapAttrs toYaml toYamlPretty;
|
||||
in
|
||||
{
|
||||
name,
|
||||
pipeline,
|
||||
nixConfig,
|
||||
}: let
|
||||
jobs = filterAttrsRec (n: v: v != null) pipeline.jobs;
|
||||
rest = filterAttrsRec (n: v: v != null) (builtins.removeAttrs pipeline ["jobs" "config"]);
|
||||
jobs = filterAttrsRec (_n: v: v != null) pipeline.jobs;
|
||||
rest = filterAttrsRec (_n: v: v != null) (builtins.removeAttrs pipeline ["jobs"]);
|
||||
# this allows us to nix build this to get all the mentioned dependencies from the binary cache
|
||||
# pro: we don't have to download everything, just the deps for the current job
|
||||
# before, we just allowed pkgs inside the script string directly, but now with the ability to source this file
|
||||
|
|
@ -22,7 +22,7 @@ in {
|
|||
jobsMappedForDeps =
|
||||
customMapAttrs (key: job: {
|
||||
name = "gitlab-ci:pipeline:${name}:job-deps:${key}";
|
||||
value = mkJobDeps {inherit key job;};
|
||||
value = mkJobDeps {inherit key job nixConfig;};
|
||||
})
|
||||
jobs;
|
||||
# allows the user to directly run the script
|
||||
|
|
@ -30,7 +30,7 @@ in {
|
|||
customMapAttrs (key: job: {
|
||||
name = "gitlab-ci:pipeline:${name}:job:${key}";
|
||||
value = mkJobRun {
|
||||
inherit key job;
|
||||
inherit key job nixConfig;
|
||||
jobDeps = jobsMappedForDeps."gitlab-ci:pipeline:${name}:job-deps:${key}";
|
||||
};
|
||||
})
|
||||
|
|
@ -39,10 +39,10 @@ in {
|
|||
jobsPatched =
|
||||
customMapAttrs (key: job: {
|
||||
name = key;
|
||||
value = assert lib.assertMsg (builtins.elem job.stage (rest.stages or [])) "stage '${job.stage}' of job '${key}' does not exist";
|
||||
value = assert assertMsg (builtins.elem job.stage (rest.stages or [])) "stage '${job.stage}' of job '${key}' does not exist";
|
||||
mkJobPatched {
|
||||
inherit key job;
|
||||
pipeline_name = name;
|
||||
inherit key job nixConfig;
|
||||
pipelineName = name;
|
||||
};
|
||||
})
|
||||
jobs;
|
||||
|
|
@ -53,9 +53,9 @@ in {
|
|||
# gitlab-ci:pipeline:<name>:job-deps:<name>
|
||||
{
|
||||
"gitlab-ci:pipeline:${name}" = toYaml "gitlab-ci-${name}.yml" (rest // jobsPatched);
|
||||
"gitlab-ci:pipeline:${name}:pretty" = toYamlPretty "gitlab-ci-${name}.yml" (rest // jobsPatched);
|
||||
}
|
||||
// jobsMappedForDeps
|
||||
// jobsMappedForScript;
|
||||
finalConfig = rest // jobsPatched;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -35,6 +35,7 @@ done
|
|||
|
||||
if [ "$NO_SANDBOX" = false ]; then
|
||||
echo "Running with simple sandboxing"
|
||||
TMPDIR=$(mktemp -dt "nix-gitlab-ci.XXX")
|
||||
if [ "$KEEP_TMP" = false ]; then
|
||||
trap "rm -rf '$TMPDIR'" EXIT
|
||||
else
|
||||
|
|
@ -49,7 +50,6 @@ 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
|
||||
|
|
@ -1,49 +0,0 @@
|
|||
{
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}: let
|
||||
cilib = import ./. {inherit lib pkgs;};
|
||||
inherit (lib) toList;
|
||||
inherit (cilib.helpers) prependToBeforeScript appendToAfterScript filterJobVariables;
|
||||
in {
|
||||
mkJobPatched = {
|
||||
key,
|
||||
job,
|
||||
pipeline_name,
|
||||
}:
|
||||
builtins.removeAttrs (
|
||||
(prependToBeforeScript [
|
||||
"source setup_nix_ci \"gitlab-ci:pipeline:${pipeline_name}:job-deps:${key}\""
|
||||
]
|
||||
(appendToAfterScript [
|
||||
"finalize_nix_ci"
|
||||
]
|
||||
job))
|
||||
// lib.optionalAttrs job.nix.enable (
|
||||
(let
|
||||
variables =
|
||||
(filterJobVariables false job)
|
||||
// lib.optionalAttrs job.nix.enable-runner-cache {
|
||||
NIX_CI_CACHE_STRATEGY = "runner";
|
||||
};
|
||||
in
|
||||
# filter empty variables
|
||||
lib.optionalAttrs (variables != {}) {
|
||||
inherit variables;
|
||||
})
|
||||
// (let
|
||||
cache =
|
||||
(toList (job.cache or []))
|
||||
++ (lib.optional (job.nix.enable-runner-cache) {
|
||||
key = job.nix.runner-cache-key;
|
||||
paths = [".nix-cache/"];
|
||||
});
|
||||
in
|
||||
# filter empty cache
|
||||
lib.optionalAttrs (cache != []) {
|
||||
inherit cache;
|
||||
})
|
||||
)
|
||||
) ["nix"];
|
||||
}
|
||||
48
nix/packages/pkgs.nix
Normal file
48
nix/packages/pkgs.nix
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
{
|
||||
inputs,
|
||||
system,
|
||||
...
|
||||
}: let
|
||||
inherit (inputs) pkgs;
|
||||
in rec {
|
||||
setupScript = pkgs.writeShellScriptBin "setup_nix_ci" (builtins.readFile ./scripts/setup_nix_ci.sh);
|
||||
finalizeScript = pkgs.writeShellScriptBin "finalize_nix_ci" (builtins.readFile ./scripts/finalize_nix_ci.sh);
|
||||
image = pkgs.dockerTools.buildImage {
|
||||
name = "nix-ci";
|
||||
fromImage = let
|
||||
hashes = {
|
||||
"x86_64-linux" = "sha256-kJ7dqje5o1KPr3RDZ7/THbhMSoiCU1C/7HshDrNfwnM=";
|
||||
"aarch64-linux" = "sha256-jz+Z3Ji+hy5d9ImOh/YOKCqy9P9/cseSov+5J/O95bg=";
|
||||
};
|
||||
# check digest of tags like nixos-24.11-aarch64-linux etc.
|
||||
digests = {
|
||||
"x86_64-linux" = "sha256:345f210dea4cbd049e2d01d13159c829066dfb6e273cdd49ea878186d17b19f7";
|
||||
"aarch64-linux" = "sha256:66163fdf446d851416dd4e9be28c0794d9c2550214a57a846957699a3f5747f6";
|
||||
};
|
||||
hash = hashes.${system} or (throw "Unsupported system");
|
||||
imageDigest = digests.${system} or (throw "Unsupported system");
|
||||
in
|
||||
pkgs.dockerTools.pullImage {
|
||||
imageName = "nixpkgs/nix-flakes";
|
||||
inherit hash imageDigest;
|
||||
};
|
||||
copyToRoot = pkgs.buildEnv {
|
||||
name = "image-root";
|
||||
paths = with pkgs;
|
||||
[
|
||||
gitMinimal
|
||||
gnugrep
|
||||
gnused
|
||||
coreutils
|
||||
diffutils
|
||||
cachix
|
||||
attic-client
|
||||
]
|
||||
++ [
|
||||
setupScript
|
||||
finalizeScript
|
||||
];
|
||||
pathsToLink = ["/bin"];
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
@ -38,4 +38,3 @@ echo -e "\\e[0Ksection_start:`date +%s`:finalize_nix_ci[collapsed=true]\\r\\e[0K
|
|||
echo "Caching disabled, not uploading $COUNT new store entries..."
|
||||
fi
|
||||
echo -e "\\e[0Ksection_end:`date +%s`:finalize_nix_ci\\r\\e[0K"
|
||||
|
||||
|
|
@ -46,4 +46,3 @@ echo -e "\\e[0Ksection_start:`date +%s`:nix_setup[collapsed=true]\\r\\e[0KSettin
|
|||
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"
|
||||
|
||||
99
nix/repo/ci.nix
Normal file
99
nix/repo/ci.nix
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
{inputs, ...}: let
|
||||
inherit (inputs) cilib;
|
||||
in
|
||||
cilib.mkCI {
|
||||
config.soonix = {
|
||||
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"];
|
||||
"build:image" = {
|
||||
stage = "build-images";
|
||||
parallel.matrix = [
|
||||
{ARCH = ["x86_64-linux" "aarch64-linux"];}
|
||||
];
|
||||
image = "nixpkgs/nix-flakes:latest";
|
||||
script = ["nix build .#image --system $ARCH"];
|
||||
after_script = ["install -D result dist/nix-ci-$ARCH.tar.gz"];
|
||||
artifacts.paths = ["dist"];
|
||||
};
|
||||
"deploy:image" = {
|
||||
stage = "build-images";
|
||||
image = "nixpkgs/nix-flakes:latest";
|
||||
needs = ["build:image"];
|
||||
before_script = [
|
||||
# sh
|
||||
''
|
||||
nix profile install nixpkgs#buildah
|
||||
export PATH="$PATH:$HOME/.nix-profile/bin"
|
||||
export REGISTRY_AUTH_FILE=''${HOME}/auth.json
|
||||
echo "$CI_REGISTRY_PASSWORD" | buildah login -u "$CI_REGISTRY_USER" --password-stdin $CI_REGISTRY
|
||||
mkdir -p /etc/containers && echo '{"default":[{"type":"insecureAcceptAnything"}]}' > /etc/containers/policy.json
|
||||
mkdir -p /var/tmp
|
||||
''
|
||||
];
|
||||
script = [
|
||||
# sh
|
||||
''
|
||||
export NORMALIZED_BRANCH=''${CI_COMMIT_BRANCH/\//-}
|
||||
buildah manifest create localhost/nix-ci
|
||||
buildah manifest add localhost/nix-ci docker-archive:dist/nix-ci-x86_64-linux.tar.gz
|
||||
buildah manifest add localhost/nix-ci docker-archive:dist/nix-ci-aarch64-linux.tar.gz
|
||||
buildah manifest push --all localhost/nix-ci docker://''${CI_REGISTRY_IMAGE}/nix-ci:''${CI_COMMIT_SHORT_SHA}
|
||||
# branches
|
||||
if [ -z "$CI_COMMIT_TAG" ]; then
|
||||
buildah manifest push --all localhost/nix-ci docker://''${CI_REGISTRY_IMAGE}/nix-ci:''${NORMALIZED_BRANCH/main/latest}
|
||||
fi
|
||||
# tags
|
||||
if [ -n "$CI_COMMIT_TAG" ]; then
|
||||
buildah manifest push --all localhost/nix-ci docker://''${CI_REGISTRY_IMAGE}/nix-ci:''${CI_COMMIT_TAG}
|
||||
fi
|
||||
''
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
pipelines."default" = {
|
||||
stages = ["test" "build" "deploy"];
|
||||
jobs = {
|
||||
"test" = {
|
||||
stage = "test";
|
||||
script = [
|
||||
"nix run .#tests -- --junit=junit.xml"
|
||||
];
|
||||
allow_failure = true;
|
||||
artifacts = {
|
||||
when = "always";
|
||||
reports.junit = "junit.xml";
|
||||
};
|
||||
};
|
||||
"docs" = {
|
||||
stage = "build";
|
||||
script = [
|
||||
# sh
|
||||
''
|
||||
nix build .#docs:default
|
||||
mkdir -p public
|
||||
cp -r result/. public/
|
||||
''
|
||||
];
|
||||
artifacts.paths = ["public"];
|
||||
};
|
||||
"pages" = {
|
||||
nix.enable = false;
|
||||
image = "alpine:latest";
|
||||
stage = "deploy";
|
||||
script = ["true"];
|
||||
artifacts.paths = ["public"];
|
||||
rules = [
|
||||
{
|
||||
"if" = "$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH";
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
35
nix/repo/devShells.nix
Normal file
35
nix/repo/devShells.nix
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
{
|
||||
cell,
|
||||
inputs,
|
||||
...
|
||||
}: let
|
||||
inherit (inputs) pkgs devshell treefmt soonix;
|
||||
inherit (cell) ci;
|
||||
in {
|
||||
default = devshell.mkShell {
|
||||
imports = [soonix.devshellModule];
|
||||
packages = [
|
||||
pkgs.nil
|
||||
(treefmt.mkWrapper pkgs {
|
||||
programs = {
|
||||
alejandra.enable = true;
|
||||
deadnix.enable = true;
|
||||
statix.enable = true;
|
||||
mdformat.enable = true;
|
||||
yamlfmt.enable = true;
|
||||
};
|
||||
settings.formatter = {
|
||||
yamlfmt.excludes = ["templates/nix-gitlab-ci.yml" ".gitlab-ci.yml"];
|
||||
mdformat.command = let
|
||||
pkg = pkgs.python3.withPackages (p: [
|
||||
p.mdformat
|
||||
p.mdformat-mkdocs
|
||||
]);
|
||||
in "${pkg}/bin/mdformat";
|
||||
};
|
||||
})
|
||||
];
|
||||
|
||||
soonix.hooks."ci" = ci.soonix;
|
||||
};
|
||||
}
|
||||
80
nix/repo/docs.nix
Normal file
80
nix/repo/docs.nix
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
{inputs, ...}: let
|
||||
inherit (inputs) pkgs cilib doclib;
|
||||
|
||||
optionsDoc = doclib.mkOptionDocs {
|
||||
module = cilib.modules.nixCiSubmodule;
|
||||
roots = [
|
||||
{
|
||||
url = "https://gitlab.com/TECHNOFAB/nix-gitlab-ci/-/blob/main/lib";
|
||||
path = "${inputs.self}/lib";
|
||||
}
|
||||
];
|
||||
};
|
||||
optionsDocs = pkgs.runCommand "options-docs" {} ''
|
||||
mkdir -p $out
|
||||
ln -s ${optionsDoc} $out/options.md
|
||||
'';
|
||||
in
|
||||
(doclib.mkDocs {
|
||||
docs."default" = {
|
||||
base = "${inputs.self}";
|
||||
path = "${inputs.self}/docs";
|
||||
material = {
|
||||
enable = true;
|
||||
colors = {
|
||||
primary = "deep orange";
|
||||
accent = "orange";
|
||||
};
|
||||
umami = {
|
||||
enable = true;
|
||||
src = "https://analytics.tf/umami";
|
||||
siteId = "28f7c904-db22-4c2b-9ee4-ed42e14b6db9";
|
||||
domains = ["nix-gitlab-ci.projects.tf"];
|
||||
};
|
||||
};
|
||||
macros = {
|
||||
enable = true;
|
||||
includeDir = toString optionsDocs;
|
||||
};
|
||||
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.svg";
|
||||
icon.repo = "simple/gitlab";
|
||||
favicon = "images/logo.svg";
|
||||
};
|
||||
nav = [
|
||||
{"Introduction" = "index.md";}
|
||||
{"Setup" = "setup.md";}
|
||||
{"Usage" = "usage.md";}
|
||||
{"CI/CD Component" = "cicd_component.md";}
|
||||
{"Environment Variables" = "environment_variables.md";}
|
||||
{"Caching" = "caching.md";}
|
||||
{"Multiple Pipelines" = "multi_pipeline.md";}
|
||||
{"Soonix Integration" = "soonix.md";}
|
||||
{"Utilities" = "utilities.md";}
|
||||
{"Kubernetes Runner Example" = "kubernetes_runner.md";}
|
||||
{"Example Configs" = "examples.md";}
|
||||
{"Options" = "options.md";}
|
||||
];
|
||||
markdown_extensions = [
|
||||
{
|
||||
"pymdownx.highlight".pygments_lang_class = true;
|
||||
}
|
||||
"pymdownx.inlinehilite"
|
||||
"pymdownx.snippets"
|
||||
"pymdownx.superfences"
|
||||
"pymdownx.escapeall"
|
||||
"fenced_code"
|
||||
"admonition"
|
||||
];
|
||||
};
|
||||
};
|
||||
}).packages
|
||||
// {
|
||||
inherit optionsDocs;
|
||||
}
|
||||
99
nix/repo/flake.lock
generated
Normal file
99
nix/repo/flake.lock
generated
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
{
|
||||
"nodes": {
|
||||
"devshell-lib": {
|
||||
"locked": {
|
||||
"dir": "lib",
|
||||
"lastModified": 1755673398,
|
||||
"narHash": "sha256-51MmR+Eo1+bKDd/Ss77wwTqi4yAR2xgmyCSEbKWSpj0=",
|
||||
"owner": "rensa-nix",
|
||||
"repo": "devshell",
|
||||
"rev": "e76bef387e8a4574f9b6d37b1a424e706491af08",
|
||||
"type": "gitlab"
|
||||
},
|
||||
"original": {
|
||||
"dir": "lib",
|
||||
"owner": "rensa-nix",
|
||||
"repo": "devshell",
|
||||
"type": "gitlab"
|
||||
}
|
||||
},
|
||||
"nixmkdocs-lib": {
|
||||
"locked": {
|
||||
"dir": "lib",
|
||||
"lastModified": 1757055638,
|
||||
"narHash": "sha256-KHYSkEreFe4meXzSdEbknC/HwaQSNClQkc8vzHlAsMM=",
|
||||
"owner": "TECHNOFAB",
|
||||
"repo": "nixmkdocs",
|
||||
"rev": "7840a5febdbeaf2da90babf6c94b3d0929d2bf74",
|
||||
"type": "gitlab"
|
||||
},
|
||||
"original": {
|
||||
"dir": "lib",
|
||||
"owner": "TECHNOFAB",
|
||||
"repo": "nixmkdocs",
|
||||
"type": "gitlab"
|
||||
}
|
||||
},
|
||||
"nixtest-lib": {
|
||||
"locked": {
|
||||
"dir": "lib",
|
||||
"lastModified": 1756812148,
|
||||
"narHash": "sha256-0g8KNk4zoLApA51PBHOWqPLRYpprjrQuSzNCjfBQgu8=",
|
||||
"owner": "TECHNOFAB",
|
||||
"repo": "nixtest",
|
||||
"rev": "5741109cc9ec2b6d41b56abd3f5bc51ed7a9a228",
|
||||
"type": "gitlab"
|
||||
},
|
||||
"original": {
|
||||
"dir": "lib",
|
||||
"owner": "TECHNOFAB",
|
||||
"repo": "nixtest",
|
||||
"type": "gitlab"
|
||||
}
|
||||
},
|
||||
"root": {
|
||||
"inputs": {
|
||||
"devshell-lib": "devshell-lib",
|
||||
"nixmkdocs-lib": "nixmkdocs-lib",
|
||||
"nixtest-lib": "nixtest-lib",
|
||||
"soonix-lib": "soonix-lib",
|
||||
"treefmt-nix": "treefmt-nix"
|
||||
}
|
||||
},
|
||||
"soonix-lib": {
|
||||
"locked": {
|
||||
"dir": "lib",
|
||||
"lastModified": 1756797658,
|
||||
"narHash": "sha256-4rkyP4oaoqG/FFVL7W8U+8hGer4tOBPff/2SeN5tJYQ=",
|
||||
"owner": "TECHNOFAB",
|
||||
"repo": "soonix",
|
||||
"rev": "3baef660cf8b87391d475a0455dd66fae0e60008",
|
||||
"type": "gitlab"
|
||||
},
|
||||
"original": {
|
||||
"dir": "lib",
|
||||
"owner": "TECHNOFAB",
|
||||
"repo": "soonix",
|
||||
"type": "gitlab"
|
||||
}
|
||||
},
|
||||
"treefmt-nix": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1756662192,
|
||||
"narHash": "sha256-F1oFfV51AE259I85av+MAia221XwMHCOtZCMcZLK2Jk=",
|
||||
"owner": "numtide",
|
||||
"repo": "treefmt-nix",
|
||||
"rev": "1aabc6c05ccbcbf4a635fb7a90400e44282f61c4",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "numtide",
|
||||
"repo": "treefmt-nix",
|
||||
"type": "github"
|
||||
}
|
||||
}
|
||||
},
|
||||
"root": "root",
|
||||
"version": 7
|
||||
}
|
||||
22
nix/repo/flake.nix
Normal file
22
nix/repo/flake.nix
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
{
|
||||
inputs = {
|
||||
devshell-lib.url = "gitlab:rensa-nix/devshell?dir=lib";
|
||||
nixtest-lib.url = "gitlab:TECHNOFAB/nixtest?dir=lib";
|
||||
soonix-lib.url = "gitlab:TECHNOFAB/soonix?dir=lib";
|
||||
nixmkdocs-lib.url = "gitlab:TECHNOFAB/nixmkdocs?dir=lib";
|
||||
treefmt-nix = {
|
||||
url = "github:numtide/treefmt-nix";
|
||||
flake = false;
|
||||
};
|
||||
};
|
||||
outputs = i:
|
||||
i
|
||||
// {
|
||||
devshell = i.devshell-lib.lib {inherit (i.parent) pkgs;};
|
||||
soonix = i.soonix-lib.lib {inherit (i.parent) pkgs;};
|
||||
ntlib = i.nixtest-lib.lib {inherit (i.parent) pkgs;};
|
||||
doclib = i.nixmkdocs-lib.lib {inherit (i.parent) pkgs;};
|
||||
cilib = import "${i.parent.self}/lib" {inherit (i.parent) pkgs;};
|
||||
treefmt = import i.treefmt-nix;
|
||||
};
|
||||
}
|
||||
10
nix/repo/tests.nix
Normal file
10
nix/repo/tests.nix
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
{inputs, ...}: let
|
||||
inherit (inputs) pkgs ntlib cilib;
|
||||
in {
|
||||
tests = ntlib.mkNixtest {
|
||||
modules = ntlib.autodiscover {dir = "${inputs.self}/tests";};
|
||||
args = {
|
||||
inherit pkgs ntlib cilib;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
@ -1 +0,0 @@
|
|||
{"docs":{"after_script":["finalize_nix_ci"],"artifacts":{"paths":["public"]},"before_script":["source setup_nix_ci \"gitlab-ci:pipeline:default:job-deps:docs\""],"image":"$NIX_CI_IMAGE","script":["nix build .#docs:default\nmkdir -p public\ncp -r result/. public/\n"],"stage":"build"},"nixtest":{"after_script":["finalize_nix_ci"],"allow_failure":true,"artifacts":{"reports":{"junit":"junit.xml"},"when":"always"},"before_script":["source setup_nix_ci \"gitlab-ci:pipeline:default:job-deps:nixtest\""],"image":"$NIX_CI_IMAGE","script":["nix run .#nixtests:run -- --junit=junit.xml --pure"],"stage":"nixtest"},"pages":{"artifacts":{"paths":["public"]},"image":"alpine:latest","rules":[{"if":"$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH"}],"script":["true"],"stage":"deploy"},"stages":["test","nixtest","build","deploy"],"test":{"after_script":["finalize_nix_ci"],"before_script":["source setup_nix_ci \"gitlab-ci:pipeline:default:job-deps:test\""],"cache":[{"key":"$CI_JOB_NAME-$CI_COMMIT_REF_SLUG","paths":[".nix-cache/"]}],"image":"$NIX_CI_IMAGE","script":["hello","curl google.de","echo $TEST $TEST_WITH_DERIVATION"],"stage":"test","variables":{"NIX_CI_CACHE_STRATEGY":"runner","TEST":"test"}},"test-default":{"after_script":["finalize_nix_ci"],"before_script":["source setup_nix_ci \"gitlab-ci:pipeline:default:job-deps:test-default\""],"image":"$NIX_CI_IMAGE","script":["hello"],"stage":"test"},"test-non-nix":{"image":"alpine:latest","script":["echo \"This job will not be modified to use nix\""],"stage":"test"}}
|
||||
|
|
@ -1 +0,0 @@
|
|||
{"stages":["test"],"test":{"after_script":["finalize_nix_ci"],"before_script":["source setup_nix_ci \"gitlab-ci:pipeline:non-default:job-deps:test\""],"image":"$NIX_CI_IMAGE","script":["echo Hello from another pipeline"],"stage":"test"}}
|
||||
|
|
@ -110,3 +110,4 @@ nix-ci:trigger:
|
|||
strategy: depend
|
||||
forward:
|
||||
pipeline_variables: true
|
||||
|
||||
|
|
|
|||
140
tests/ci-lib.nix
140
tests/ci-lib.nix
|
|
@ -1,140 +0,0 @@
|
|||
{
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}: let
|
||||
cilib = import ./../lib {inherit lib pkgs;};
|
||||
in {
|
||||
nixtest.suites."CI Lib" = {
|
||||
pos = __curPos;
|
||||
tests = let
|
||||
inherit (cilib.jobDeps) mkJobDeps;
|
||||
inherit (cilib.jobRun) mkJobRun;
|
||||
inherit (cilib.jobPatch) mkJobPatched;
|
||||
inherit (cilib.pipeline) mkPipeline;
|
||||
deps = mkJobDeps {
|
||||
key = "test";
|
||||
job = {
|
||||
nix.deps = [pkgs.hello];
|
||||
variables.TEST = "${pkgs.curl}";
|
||||
};
|
||||
};
|
||||
in [
|
||||
{
|
||||
name = "jobDeps";
|
||||
type = "script";
|
||||
script =
|
||||
# sh
|
||||
''
|
||||
export PATH=${lib.makeBinPath [pkgs.gnugrep]}
|
||||
grep -q "/nix/store" ${deps}
|
||||
grep -q 'hello/bin:$PATH' ${deps}
|
||||
grep -q "export TEST=" ${deps}
|
||||
grep -q "curl" ${deps}
|
||||
'';
|
||||
}
|
||||
{
|
||||
name = "jobRun";
|
||||
type = "script";
|
||||
script = let
|
||||
run = mkJobRun {
|
||||
key = "test";
|
||||
job.script = ["hello"];
|
||||
jobDeps = deps;
|
||||
};
|
||||
in
|
||||
# sh
|
||||
''
|
||||
export PATH=${lib.makeBinPath [pkgs.gnugrep]}
|
||||
grep -q "sandbox-helper" ${run}/bin/gitlab-ci-job:test
|
||||
grep -q "gitlab-ci-job-test-raw" ${run}/bin/gitlab-ci-job:test
|
||||
grep -q "gitlab-ci-job-deps-test" ${run.passthru.actualJobScript}
|
||||
grep -q "Running script..." ${run.passthru.actualJobScript}
|
||||
grep -q "hello" ${run.passthru.actualJobScript}
|
||||
'';
|
||||
}
|
||||
{
|
||||
name = "jobPatched nix disabled";
|
||||
expected = {};
|
||||
actual = mkJobPatched {
|
||||
key = "test";
|
||||
pipeline_name = "test";
|
||||
job.nix.enable = false;
|
||||
};
|
||||
}
|
||||
{
|
||||
name = "jobPatched without runner cache";
|
||||
expected = {
|
||||
after_script = ["finalize_nix_ci"];
|
||||
before_script = ["source setup_nix_ci \"gitlab-ci:pipeline:test:job-deps:test\""];
|
||||
};
|
||||
actual = mkJobPatched {
|
||||
key = "test";
|
||||
pipeline_name = "test";
|
||||
job.nix = {
|
||||
enable = true;
|
||||
enable-runner-cache = false;
|
||||
};
|
||||
};
|
||||
}
|
||||
{
|
||||
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 = [
|
||||
{
|
||||
key = "test";
|
||||
paths = [".nix-cache/"];
|
||||
}
|
||||
];
|
||||
variables."NIX_CI_CACHE_STRATEGY" = "runner";
|
||||
};
|
||||
actual = mkJobPatched {
|
||||
key = "test";
|
||||
pipeline_name = "test";
|
||||
job.nix = {
|
||||
enable = true;
|
||||
enable-runner-cache = true;
|
||||
runner-cache-key = "test";
|
||||
};
|
||||
};
|
||||
}
|
||||
{
|
||||
name = "mkPipeline empty";
|
||||
expected = {};
|
||||
actual =
|
||||
(mkPipeline {
|
||||
name = "test";
|
||||
pipeline.jobs = {};
|
||||
}).finalConfig;
|
||||
}
|
||||
{
|
||||
name = "mkPipeline empty packages";
|
||||
type = "script";
|
||||
script = let
|
||||
pipeline = builtins.toFile "pipeline-test" (builtins.toJSON
|
||||
(mkPipeline {
|
||||
name = "test";
|
||||
pipeline.jobs = {};
|
||||
}).packages);
|
||||
in
|
||||
# sh
|
||||
''
|
||||
set -euo pipefail
|
||||
export PATH=${lib.makeBinPath [pkgs.jq pkgs.gnugrep pkgs.coreutils]}
|
||||
# single key
|
||||
jq 'keys | length == 1' "${pipeline}" | grep -q true
|
||||
# key is exactly "gitlab-ci:pipeline:test"
|
||||
jq -r 'keys[0]' "${pipeline}" | grep -qx "gitlab-ci:pipeline:test"
|
||||
# value contains "/nix/store/"
|
||||
jq -r '.["gitlab-ci:pipeline:test"]' "${pipeline}" | grep -q "/nix/store/"
|
||||
# value contains "gitlab-ci-test.yml"
|
||||
jq -r '.["gitlab-ci:pipeline:test"]' "${pipeline}" | grep -q "gitlab-ci-test.yml"
|
||||
# file only contains "{}"
|
||||
[[ "$(cat $(jq -r '.["gitlab-ci:pipeline:test"]' "${pipeline}"))" == "{}" ]]
|
||||
'';
|
||||
}
|
||||
];
|
||||
};
|
||||
}
|
||||
168
tests/cilib_test.nix
Normal file
168
tests/cilib_test.nix
Normal file
|
|
@ -0,0 +1,168 @@
|
|||
{
|
||||
pkgs,
|
||||
cilib,
|
||||
ntlib,
|
||||
...
|
||||
}: {
|
||||
suites."CI Lib" = {
|
||||
pos = __curPos;
|
||||
tests = let
|
||||
inherit (cilib) mkJobDeps mkJobRun mkJobPatched mkPipeline;
|
||||
deps = mkJobDeps {
|
||||
key = "test";
|
||||
job = {
|
||||
variables.TEST = "${pkgs.curl}";
|
||||
};
|
||||
nixConfig = {
|
||||
enable = true;
|
||||
deps = [pkgs.hello];
|
||||
};
|
||||
};
|
||||
in [
|
||||
{
|
||||
name = "jobDeps";
|
||||
type = "script";
|
||||
script =
|
||||
# sh
|
||||
''
|
||||
${ntlib.helpers.path [pkgs.gnugrep]}
|
||||
${ntlib.helpers.scriptHelpers}
|
||||
assert_file_contains ${deps} "/nix/store" "should contain nix store path"
|
||||
assert_file_contains ${deps} '-hello-.*/bin:$PATH' "should contain hello"
|
||||
assert_file_contains ${deps} "export TEST=" "should export TEST"
|
||||
assert_file_contains ${deps} "curl" "should contain curl"
|
||||
'';
|
||||
}
|
||||
{
|
||||
name = "jobRun";
|
||||
type = "script";
|
||||
script = let
|
||||
run = mkJobRun {
|
||||
key = "test";
|
||||
job.script = ["hello"];
|
||||
jobDeps = deps;
|
||||
};
|
||||
in
|
||||
# sh
|
||||
''
|
||||
${ntlib.helpers.path [pkgs.gnugrep]}
|
||||
${ntlib.helpers.scriptHelpers}
|
||||
assert_file_contains ${run}/bin/gitlab-ci-job:test "sandbox-helper" "should contain sandbox-helper"
|
||||
assert_file_contains ${run}/bin/gitlab-ci-job:test "gitlab-ci-job-test-raw" "should contain job name"
|
||||
assert_file_contains ${run.passthru.actualJobScript} "gitlab-ci-job-deps-test" "should contain job name"
|
||||
assert_file_contains ${run.passthru.actualJobScript} "Running script..." "should contain 'Running script...'"
|
||||
assert_file_contains ${run.passthru.actualJobScript} "hello" "should contain hello"
|
||||
'';
|
||||
}
|
||||
{
|
||||
name = "jobPatched nix disabled";
|
||||
expected = {};
|
||||
actual = mkJobPatched {
|
||||
key = "test";
|
||||
pipelineName = "test";
|
||||
job = {};
|
||||
nixConfig.enable = false;
|
||||
};
|
||||
}
|
||||
{
|
||||
name = "jobPatched without runner cache";
|
||||
expected = {
|
||||
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 = {};
|
||||
nixConfig = {
|
||||
enable = true;
|
||||
enableRunnerCache = false;
|
||||
};
|
||||
};
|
||||
}
|
||||
{
|
||||
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 = [
|
||||
{
|
||||
key = "test";
|
||||
paths = [".nix-cache/"];
|
||||
}
|
||||
];
|
||||
variables."NIX_CI_CACHE_STRATEGY" = "runner";
|
||||
};
|
||||
actual = mkJobPatched {
|
||||
key = "test";
|
||||
pipelineName = "test";
|
||||
job = {};
|
||||
nixConfig = {
|
||||
enable = true;
|
||||
enableRunnerCache = true;
|
||||
runnerCacheKey = "test";
|
||||
};
|
||||
};
|
||||
}
|
||||
{
|
||||
name = "mkPipeline empty";
|
||||
expected = {};
|
||||
actual =
|
||||
(mkPipeline {
|
||||
name = "test";
|
||||
nixConfig = {};
|
||||
pipeline.jobs = {};
|
||||
}).finalConfig;
|
||||
}
|
||||
{
|
||||
name = "mkPipeline empty packages";
|
||||
type = "script";
|
||||
script = let
|
||||
pipeline =
|
||||
ntlib.helpers.toJsonFile
|
||||
(mkPipeline {
|
||||
name = "test";
|
||||
nixConfig = {};
|
||||
pipeline.jobs = {};
|
||||
}).packages;
|
||||
in
|
||||
# sh
|
||||
''
|
||||
set -euo pipefail
|
||||
${ntlib.helpers.path [pkgs.jq pkgs.gnugrep pkgs.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'"
|
||||
jq -r 'keys[0]' "${pipeline}" | grep -qx "gitlab-ci:pipeline:test"
|
||||
echo "key[1] is exactly 'gitlab-ci:pipeline:test:pretty'"
|
||||
jq -r 'keys[1]' "${pipeline}" | grep -qx "gitlab-ci:pipeline:test:pretty"
|
||||
echo "value contains '/nix/store/'"
|
||||
jq -r '.["gitlab-ci:pipeline:test"]' "${pipeline}" | grep -q "/nix/store/"
|
||||
echo "value contains 'gitlab-ci-test.yml'"
|
||||
jq -r '.["gitlab-ci:pipeline:test"]' "${pipeline}" | grep -q "gitlab-ci-test.yml"
|
||||
echo "file only contains '{}'"
|
||||
[[ "$(cat $(jq -r '.["gitlab-ci:pipeline:test"]' "${pipeline}"))" == "{}" ]]
|
||||
'';
|
||||
}
|
||||
{
|
||||
name = "handle store paths in variables";
|
||||
expected = {
|
||||
stages = ["test"];
|
||||
test.stage = "test";
|
||||
};
|
||||
actual =
|
||||
(mkPipeline {
|
||||
name = "test";
|
||||
nixConfig.enable = false;
|
||||
pipeline = {
|
||||
stages = ["test"];
|
||||
jobs.test = {
|
||||
stage = "test";
|
||||
variables."TEST" = "${pkgs.hello}";
|
||||
};
|
||||
};
|
||||
}).finalConfig;
|
||||
}
|
||||
];
|
||||
};
|
||||
}
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
{
|
||||
imports = [
|
||||
./utils.nix
|
||||
./ci-lib.nix
|
||||
./helpers.nix
|
||||
./pipeline-yamls.nix
|
||||
];
|
||||
}
|
||||
77
tests/fixtures/flake_parts/flake.lock
generated
vendored
Normal file
77
tests/fixtures/flake_parts/flake.lock
generated
vendored
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
{
|
||||
"nodes": {
|
||||
"flake-parts": {
|
||||
"inputs": {
|
||||
"nixpkgs-lib": "nixpkgs-lib"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1754487366,
|
||||
"narHash": "sha256-pHYj8gUBapuUzKV/kN/tR3Zvqc7o6gdFB9XKXIp1SQ8=",
|
||||
"owner": "hercules-ci",
|
||||
"repo": "flake-parts",
|
||||
"rev": "af66ad14b28a127c5c0f3bbb298218fc63528a18",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "hercules-ci",
|
||||
"repo": "flake-parts",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1756636162,
|
||||
"narHash": "sha256-mBecwgUTWRgClJYqcF+y4O1bY8PQHqeDpB+zsAn+/zA=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "37ff64b7108517f8b6ba5705ee5085eac636a249",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"ref": "nixpkgs-unstable",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs-lib": {
|
||||
"locked": {
|
||||
"lastModified": 1753579242,
|
||||
"narHash": "sha256-zvaMGVn14/Zz8hnp4VWT9xVnhc8vuL3TStRqwk22biA=",
|
||||
"owner": "nix-community",
|
||||
"repo": "nixpkgs.lib",
|
||||
"rev": "0f36c44e01a6129be94e3ade315a5883f0228a6e",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-community",
|
||||
"repo": "nixpkgs.lib",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"root": {
|
||||
"inputs": {
|
||||
"flake-parts": "flake-parts",
|
||||
"nixpkgs": "nixpkgs",
|
||||
"systems": "systems"
|
||||
}
|
||||
},
|
||||
"systems": {
|
||||
"locked": {
|
||||
"lastModified": 1689347949,
|
||||
"narHash": "sha256-12tWmuL2zgBgZkdoB6qXZsgJEH9LR3oUgpaQq2RbI80=",
|
||||
"owner": "nix-systems",
|
||||
"repo": "default-linux",
|
||||
"rev": "31732fcf5e8fea42e59c2488ad31a0e651500f68",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-systems",
|
||||
"repo": "default-linux",
|
||||
"type": "github"
|
||||
}
|
||||
}
|
||||
},
|
||||
"root": "root",
|
||||
"version": 7
|
||||
}
|
||||
41
tests/fixtures/flake_parts/flake.nix
vendored
Normal file
41
tests/fixtures/flake_parts/flake.nix
vendored
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
{
|
||||
outputs = {
|
||||
flake-parts,
|
||||
systems,
|
||||
...
|
||||
} @ inputs:
|
||||
flake-parts.lib.mkFlake {inherit inputs;} {
|
||||
imports = [
|
||||
"@repo_path@/lib/flakeModule.nix"
|
||||
];
|
||||
systems = import systems;
|
||||
flake = {};
|
||||
perSystem = _: {
|
||||
ci = {
|
||||
config = {
|
||||
# true is already default, just for testing
|
||||
nixJobsByDefault = true;
|
||||
};
|
||||
pipelines = {
|
||||
"default" = {
|
||||
stages = ["example"];
|
||||
jobs."example" = {
|
||||
stage = "example";
|
||||
script = ["echo hello world"];
|
||||
};
|
||||
};
|
||||
"test".jobs."example" = {
|
||||
stage = ".pre";
|
||||
script = ["echo hello world"];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
inputs = {
|
||||
nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
|
||||
flake-parts.url = "github:hercules-ci/flake-parts";
|
||||
systems.url = "github:nix-systems/default-linux";
|
||||
};
|
||||
}
|
||||
38
tests/flake_parts_test.nix
Normal file
38
tests/flake_parts_test.nix
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
{
|
||||
pkgs,
|
||||
ntlib,
|
||||
...
|
||||
}: {
|
||||
suites."flake-parts" = {
|
||||
pos = __curPos;
|
||||
tests = [
|
||||
{
|
||||
name = "flakeModule";
|
||||
type = "script";
|
||||
script =
|
||||
# sh
|
||||
''
|
||||
${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}/* .
|
||||
# import from the absolute path above, is easier than trying to figure out the repo path etc.
|
||||
sed -i -e "s|@repo_path@|$repo_path|" flake.nix
|
||||
|
||||
# NOTE: --impure is required since importing modules from absolute paths is not allowed in pure mode
|
||||
nix build --impure .#gitlab-ci:pipeline:default
|
||||
assert "-f result" "should exist"
|
||||
assert_file_contains "result" "finalize_nix_ci"
|
||||
jq '.' result # check if valid json just to be sure
|
||||
|
||||
nix build --impure .#gitlab-ci:pipeline:default:pretty
|
||||
assert "-f result" "should exist"
|
||||
assert_file_contains "result" " - finalize_nix_ci"
|
||||
'';
|
||||
}
|
||||
];
|
||||
};
|
||||
}
|
||||
|
|
@ -1,60 +1,28 @@
|
|||
{
|
||||
lib,
|
||||
pkgs,
|
||||
cilib,
|
||||
...
|
||||
}: let
|
||||
cilib = import ./../lib {inherit lib pkgs;};
|
||||
in {
|
||||
nixtest.suites."Helpers" = {
|
||||
}: {
|
||||
suites."Helpers" = {
|
||||
pos = __curPos;
|
||||
tests = let
|
||||
inherit (cilib) helpers;
|
||||
in [
|
||||
{
|
||||
name = "appendToAfterScript nix disabled";
|
||||
expected = {};
|
||||
actual = helpers.appendToAfterScript [] {};
|
||||
}
|
||||
{
|
||||
name = "appendToAfterScript empty";
|
||||
expected = {
|
||||
nix.enable = true;
|
||||
after_script = [];
|
||||
};
|
||||
actual = helpers.appendToAfterScript [] {nix.enable = true;};
|
||||
}
|
||||
{
|
||||
name = "appendToAfterScript";
|
||||
expected = {
|
||||
nix.enable = true;
|
||||
after_script = ["echo after_script" "finalize_nix_ci"];
|
||||
};
|
||||
actual = helpers.appendToAfterScript ["finalize_nix_ci"] {
|
||||
nix.enable = true;
|
||||
after_script = ["echo after_script"];
|
||||
};
|
||||
}
|
||||
{
|
||||
name = "prependToBeforeScript nix disabled";
|
||||
expected = {};
|
||||
actual = helpers.prependToBeforeScript [] {};
|
||||
}
|
||||
{
|
||||
name = "prependToBeforeScript empty";
|
||||
expected = {
|
||||
nix.enable = true;
|
||||
before_script = [];
|
||||
};
|
||||
actual = helpers.prependToBeforeScript [] {nix.enable = true;};
|
||||
}
|
||||
{
|
||||
name = "prependToBeforeScript";
|
||||
expected = {
|
||||
nix.enable = true;
|
||||
before_script = ["setup_nix_ci" "echo before_script"];
|
||||
};
|
||||
actual = helpers.prependToBeforeScript ["setup_nix_ci"] {
|
||||
nix.enable = true;
|
||||
before_script = ["echo before_script"];
|
||||
};
|
||||
}
|
||||
|
|
@ -66,18 +34,22 @@ in {
|
|||
{
|
||||
name = "filterAttrsRec";
|
||||
expected = {world = "world";};
|
||||
actual = helpers.filterAttrsRec (n: v: v != null) {
|
||||
actual = helpers.filterAttrsRec (_n: v: v != null) {
|
||||
hello = null;
|
||||
world = "world";
|
||||
};
|
||||
}
|
||||
{
|
||||
name = "filterJobVariables with store paths";
|
||||
expected = {HELLO = "${pkgs.hello}";};
|
||||
expected = {
|
||||
HELLO = "${pkgs.hello}";
|
||||
MULTIPLE = "${pkgs.hello}:${pkgs.hello}";
|
||||
};
|
||||
actual = helpers.filterJobVariables true {
|
||||
variables = {
|
||||
HELLO = "${pkgs.hello}";
|
||||
WORLD = "world";
|
||||
MULTIPLE = "${pkgs.hello}:${pkgs.hello}";
|
||||
};
|
||||
};
|
||||
}
|
||||
82
tests/modules_test.nix
Normal file
82
tests/modules_test.nix
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
{
|
||||
pkgs,
|
||||
cilib,
|
||||
ntlib,
|
||||
...
|
||||
}: {
|
||||
suites."Modules" = {
|
||||
pos = __curPos;
|
||||
tests = let
|
||||
simplePipeline = cilib.mkCI {
|
||||
pipelines."test" = {
|
||||
stages = ["test"];
|
||||
jobs."test" = {
|
||||
stage = "test";
|
||||
script = ["echo hello world"];
|
||||
};
|
||||
};
|
||||
};
|
||||
in [
|
||||
{
|
||||
name = "empty pipelines";
|
||||
expected = {};
|
||||
actual =
|
||||
(cilib.mkCI {}).pipelines;
|
||||
}
|
||||
{
|
||||
name = "empty packages";
|
||||
expected = {};
|
||||
actual =
|
||||
(cilib.mkCI {}).packages;
|
||||
}
|
||||
{
|
||||
name = "simple pipeline";
|
||||
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"];
|
||||
after_script = ["finalize_nix_ci"];
|
||||
};
|
||||
};
|
||||
actual = simplePipeline.pipelines."test".finalConfig;
|
||||
}
|
||||
{
|
||||
name = "simple pipeline yaml";
|
||||
type = "script";
|
||||
script = let
|
||||
package = simplePipeline.packages."gitlab-ci:pipeline:test";
|
||||
in
|
||||
# sh
|
||||
''
|
||||
${ntlib.helpers.path [pkgs.gnugrep]}
|
||||
${ntlib.helpers.scriptHelpers}
|
||||
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'
|
||||
'';
|
||||
}
|
||||
{
|
||||
name = "dont fail on store paths";
|
||||
type = "script";
|
||||
script = let
|
||||
package =
|
||||
(cilib.mkCI {
|
||||
pipelines."test" = {
|
||||
variables.EXAMPLE = "${pkgs.hello}";
|
||||
};
|
||||
}).packages."gitlab-ci:pipeline: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-.*"'
|
||||
'';
|
||||
}
|
||||
];
|
||||
};
|
||||
}
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
{
|
||||
lib,
|
||||
pkgs,
|
||||
self',
|
||||
...
|
||||
}: let
|
||||
cilib = import ./../lib {inherit lib pkgs;};
|
||||
in {
|
||||
nixtest.suites."Pipeline YAMLs" = {
|
||||
pos = __curPos;
|
||||
tests = let
|
||||
jsonFile = file: builtins.fromJSON (builtins.readFile file);
|
||||
in [
|
||||
{
|
||||
name = "default";
|
||||
type = "snapshot";
|
||||
actual = jsonFile self'.legacyPackages."gitlab-ci:pipeline:default";
|
||||
}
|
||||
{
|
||||
name = "non-default";
|
||||
type = "snapshot";
|
||||
actual = jsonFile self'.legacyPackages."gitlab-ci:pipeline:non-default";
|
||||
}
|
||||
];
|
||||
};
|
||||
}
|
||||
77
tests/soonix_test.nix
Normal file
77
tests/soonix_test.nix
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
{
|
||||
lib,
|
||||
cilib,
|
||||
...
|
||||
}: let
|
||||
inherit (lib) trimWith;
|
||||
in {
|
||||
suites."Soonix" = {
|
||||
pos = __curPos;
|
||||
tests = let
|
||||
version = trimWith {
|
||||
start = true;
|
||||
end = true;
|
||||
} (builtins.readFile ../lib/VERSION);
|
||||
in [
|
||||
{
|
||||
name = "default soonix config";
|
||||
expected = {
|
||||
data.include = [
|
||||
{
|
||||
component = "gitlab.com/TECHNOFAB/nix-gitlab-ci/nix-gitlab-ci@${version}";
|
||||
inputs.version = version;
|
||||
}
|
||||
];
|
||||
generator = "nix";
|
||||
opts.format = "yaml";
|
||||
hook = {
|
||||
mode = "copy";
|
||||
gitignore = false;
|
||||
};
|
||||
output = ".gitlab-ci.yml";
|
||||
};
|
||||
actual =
|
||||
(cilib.mkCI {
|
||||
config.soonix = {};
|
||||
}).soonix;
|
||||
}
|
||||
{
|
||||
name = "custom soonix config";
|
||||
expected = {
|
||||
data = {
|
||||
include = [
|
||||
{
|
||||
component = "gitlab.com/example/nix-gitlab-ci/nix-gitlab-ci@abc";
|
||||
inputs = {
|
||||
version = "abc";
|
||||
hello = "world";
|
||||
};
|
||||
}
|
||||
];
|
||||
"example".script = ["hello"];
|
||||
};
|
||||
generator = "nix";
|
||||
opts.format = "yaml";
|
||||
hook = {
|
||||
mode = "copy";
|
||||
gitignore = false;
|
||||
};
|
||||
output = ".gitlab-ci.yml";
|
||||
};
|
||||
actual =
|
||||
(cilib.mkCI {
|
||||
config.soonix = {
|
||||
componentVersion = "abc";
|
||||
componentUrl = "gitlab.com/example/nix-gitlab-ci/nix-gitlab-ci";
|
||||
componentInputs = {
|
||||
hello = "world";
|
||||
};
|
||||
extraData = {
|
||||
"example".script = ["hello"];
|
||||
};
|
||||
};
|
||||
}).soonix;
|
||||
}
|
||||
];
|
||||
};
|
||||
}
|
||||
|
|
@ -1,36 +0,0 @@
|
|||
{
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}: let
|
||||
cilib = import ./../lib {inherit lib pkgs;};
|
||||
in {
|
||||
nixtest.suites."Utils" = {
|
||||
pos = __curPos;
|
||||
tests = [
|
||||
{
|
||||
name = "commitAndPushFiles";
|
||||
type = "script";
|
||||
script = let
|
||||
inherit (cilib) utils;
|
||||
job = builtins.toFile "test" (
|
||||
builtins.unsafeDiscardStringContext (
|
||||
builtins.toJSON (
|
||||
utils.commitAndPushFiles {
|
||||
message = "hello world";
|
||||
files = ["a.md" "b.txt"];
|
||||
} {}
|
||||
)
|
||||
)
|
||||
);
|
||||
in
|
||||
# sh
|
||||
''
|
||||
export PATH=${lib.makeBinPath [pkgs.gnugrep]}
|
||||
grep -q 'git commit -m \\"hello world\\"' ${job}
|
||||
grep -q 'git add a.md b.txt' ${job}
|
||||
'';
|
||||
}
|
||||
];
|
||||
};
|
||||
}
|
||||
32
tests/utils_test.nix
Normal file
32
tests/utils_test.nix
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
{
|
||||
pkgs,
|
||||
ntlib,
|
||||
cilib,
|
||||
...
|
||||
}: {
|
||||
suites."Utils" = {
|
||||
pos = __curPos;
|
||||
tests = [
|
||||
{
|
||||
name = "commitAndPushFiles";
|
||||
type = "script";
|
||||
script = let
|
||||
inherit (cilib) utils;
|
||||
job = ntlib.helpers.toJsonFile (
|
||||
utils.commitAndPushFiles {
|
||||
message = "hello world";
|
||||
files = ["a.md" "b.txt"];
|
||||
} {}
|
||||
);
|
||||
in
|
||||
# sh
|
||||
''
|
||||
${ntlib.helpers.path [pkgs.gnugrep]}
|
||||
${ntlib.helpers.scriptHelpers}
|
||||
assert_file_contains ${job} 'git commit -m \\"hello world\\"'
|
||||
assert_file_contains ${job} 'git add a.md b.txt'
|
||||
'';
|
||||
}
|
||||
];
|
||||
};
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue