From bd57ed361efab02108c35f277e150a783d2dcbed Mon Sep 17 00:00:00 2001 From: Terje Larsen Date: Mon, 6 Apr 2026 21:25:22 +0200 Subject: [PATCH] feat(extra): support multiple pipelines in git-hooks --- .conform.yaml | 1 + dev/flake-module.nix | 56 ++++++++++++++++++++++++++++++- extra/git-hooks.nix | 80 +++++++++++++++++++++++--------------------- 3 files changed, 98 insertions(+), 39 deletions(-) diff --git a/.conform.yaml b/.conform.yaml index aa3699b..7660760 100644 --- a/.conform.yaml +++ b/.conform.yaml @@ -21,6 +21,7 @@ policies: - style - test scopes: + - extra - github - gitlab - job diff --git a/dev/flake-module.nix b/dev/flake-module.nix index 0dd1743..4355224 100644 --- a/dev/flake-module.nix +++ b/dev/flake-module.nix @@ -79,7 +79,7 @@ }; perSystem = - { pkgs, ... }: + { config, pkgs, ... }: { pre-commit.check.enable = false; pre-commit.settings.hooks = { @@ -117,6 +117,60 @@ }; }; + checks.git-hooks = + let + inherit (config.pre-commit.settings) hooks; + gh = hooks.first-ci-kit-gen-github-actions; + gl = hooks.first-ci-kit-gen-gitlab-ci; + + tests = { + "github-actions: default pipelines" = { + check = gh.settings.pipelines.default == ".github/workflows/ci.yaml"; + }; + + "gitlab-ci: default pipelines" = { + check = gl.settings.pipelines.default == ".gitlab-ci.yml"; + }; + + "github-actions: hook name" = { + check = gh.name == "generate-github-actions"; + }; + + "gitlab-ci: hook name" = { + check = gl.name == "generate-gitlab-ci"; + }; + + "github-actions: pass_filenames is false" = { + check = !gh.pass_filenames; + }; + + "gitlab-ci: pass_filenames is false" = { + check = !gl.pass_filenames; + }; + }; + in + pkgs.runCommand "test-git-hooks" { } ( + '' + set -e + '' + + lib.concatStrings ( + lib.mapAttrsToList ( + name: + { check }: + if check then + "" + else + '' + echo "FAILED: ${name}" + exit 1 + '' + ) tests + ) + + '' + echo "All git-hooks tests passed" > $out + '' + ); + packages.module-docs = pkgs.callPackage ../packages/module-docs { moduleRoot = ../module; }; diff --git a/extra/git-hooks.nix b/extra/git-hooks.nix index deada34..a1d0381 100644 --- a/extra/git-hooks.nix +++ b/extra/git-hooks.nix @@ -12,19 +12,23 @@ let }: let writePipelineGenerator = - { name, hook }: + { backend, pipelines }: pkgs.writeShellApplication { - name = "generate-${name}"; + name = "generate-${backend}"; runtimeInputs = [ pkgs.yq-go ]; - text = '' - out="$(nix build --extra-experimental-features 'nix-command flakes' \ - --print-out-paths \ - .#ci-pipeline-${name}-${hook.settings.pipeline} - )" + text = + let + generatePipeline = name: outputPath: '' + out="$(nix build --extra-experimental-features 'nix-command flakes' \ + --print-out-paths \ + .#ci-pipeline-${backend}-${name} + )" - mkdir -p "$(dirname "${hook.settings.outputPath}")" - yq --prettyPrint --output-format yaml "$out" > "${hook.settings.outputPath}" - ''; + mkdir -p "$(dirname "${outputPath}")" + yq --prettyPrint --output-format yaml "$out" > "${outputPath}" + ''; + in + lib.concatStringsSep "\n" (lib.mapAttrsToList generatePipeline pipelines); }; in { @@ -34,18 +38,18 @@ let type = types.submodule { imports = [ hookModule ]; options.settings = { - pipeline = lib.mkOption { - type = types.str; - description = "The pipeline to generate."; - default = "default"; - example = "pr"; - }; - - outputPath = lib.mkOption { - type = types.str; - description = "The path of the output file generated."; - default = ".github/workflows/ci.yaml"; - example = ".github/workflows/example.yaml"; + pipelines = lib.mkOption { + type = types.attrsOf types.str; + default = { + default = ".github/workflows/ci.yaml"; + }; + description = "Pipeline name to output path mapping."; + example = lib.literalExpression '' + { + default = ".github/workflows/ci.yaml"; + nightly = ".github/workflows/nightly.yaml"; + } + ''; }; }; }; @@ -56,18 +60,18 @@ let type = types.submodule { imports = [ hookModule ]; options.settings = { - pipeline = lib.mkOption { - type = types.str; - description = "The pipeline to generate."; - default = "default"; - example = "pr"; - }; - - outputPath = lib.mkOption { - type = types.str; - description = "The path of the output file generated."; - default = ".gitlab-ci.yml"; - example = ".gitlab/ci.yml"; + pipelines = lib.mkOption { + type = types.attrsOf types.str; + default = { + default = ".gitlab-ci.yml"; + }; + description = "Pipeline name to output path mapping."; + example = lib.literalExpression '' + { + default = ".gitlab-ci.yml"; + pr = ".gitlab/ci-pr.yml"; + } + ''; }; }; }; @@ -79,8 +83,8 @@ let name = "generate-github-actions"; description = "generate GitHub Actions workflow"; package = writePipelineGenerator { - name = "github-actions"; - hook = config.hooks.first-ci-kit-gen-github-actions; + backend = "github-actions"; + inherit (config.hooks.first-ci-kit-gen-github-actions.settings) pipelines; }; entry = "${config.hooks.first-ci-kit-gen-github-actions.package}/bin/generate-github-actions"; files = lib.mkDefault "\\.nix$"; @@ -91,8 +95,8 @@ let name = "generate-gitlab-ci"; description = "generate GitLab CI pipeline"; package = writePipelineGenerator { - name = "gitlab-ci"; - hook = config.hooks.first-ci-kit-gen-gitlab-ci; + backend = "gitlab-ci"; + inherit (config.hooks.first-ci-kit-gen-gitlab-ci.settings) pipelines; }; entry = "${config.hooks.first-ci-kit-gen-gitlab-ci.package}/bin/generate-gitlab-ci"; files = lib.mkDefault "\\.nix$";