From b7eb55c30b366cc314fb21646a5c240e8c8122fc Mon Sep 17 00:00:00 2001 From: alexander <259883306+AlexHardAtWork@users.noreply.github.com> Date: Fri, 4 Sep 2026 09:08:05 +0200 Subject: [PATCH 1/6] chore(flake): pin dev-kit input to v2.2.0 --- flake.lock | 7 ++++--- flake.nix | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/flake.lock b/flake.lock index 3c120d6f..d90aa774 100644 --- a/flake.lock +++ b/flake.lock @@ -15,15 +15,16 @@ ] }, "locked": { - "lastModified": 1787918634, - "narHash": "sha256-d/GY4lc2ssP2ax6GGLaakYkXZcW8XM1IlFO98qd7sXQ=", + "lastModified": 1788351182, + "narHash": "sha256-3fOyooxR5RHBdnacI/dw/jxGvr+WJdauzE5iW+hvmAI=", "owner": "opendefensecloud", "repo": "dev-kit", - "rev": "3ce2ec4d731819f2ddcd5b6d9fba88979bb4c04f", + "rev": "7427f5e62c1c45ec058e3e2b483a75d9dbe48805", "type": "github" }, "original": { "owner": "opendefensecloud", + "ref": "v2.2.0", "repo": "dev-kit", "type": "github" } diff --git a/flake.nix b/flake.nix index b5d181a6..780e4346 100644 --- a/flake.nix +++ b/flake.nix @@ -12,7 +12,7 @@ }; dev-kit = { - url = "github:opendefensecloud/dev-kit"; + url = "github:opendefensecloud/dev-kit/v2.2.0"; inputs.nixpkgs.follows = "nixpkgs"; inputs.go-overlay.follows = "go-overlay"; inputs.flake-utils.follows = "flake-utils"; From 2f7c16e968f5b8898c293540ae687057bdb0545e Mon Sep 17 00:00:00 2001 From: alexander <259883306+AlexHardAtWork@users.noreply.github.com> Date: Fri, 4 Sep 2026 09:08:20 +0200 Subject: [PATCH 2/6] chore(flake): drop unused cosign from the dev shell --- flake.nix | 1 - 1 file changed, 1 deletion(-) diff --git a/flake.nix b/flake.nix index 780e4346..2ecc5c53 100644 --- a/flake.nix +++ b/flake.nix @@ -29,7 +29,6 @@ inherit system; goVersion = "1.26.6"; packages = [ - pkgs.cosign pkgs.trivy ]; preCommitHooks = { From cdb342ae37af4db7f165e2a28b7906d8cec5a6c6 Mon Sep 17 00:00:00 2001 From: alexander <259883306+AlexHardAtWork@users.noreply.github.com> Date: Fri, 4 Sep 2026 09:08:30 +0200 Subject: [PATCH 3/6] refactor: use envtest sideloading from dev-kit --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index b520d586..01472bb5 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ # Include ODC common make targets -DEV_KIT_VERSION := v2.1.0 +DEV_KIT_VERSION := v2.2.0 -include common.mk common.mk: @[ -f .common.mk-download ] || \ From 9fb620176f60d65edbf9ead25b715e6bb8eec2fd Mon Sep 17 00:00:00 2001 From: alexander <259883306+AlexHardAtWork@users.noreply.github.com> Date: Fri, 4 Sep 2026 09:08:40 +0200 Subject: [PATCH 4/6] ci: run workflows in the nix dev shell --- .github/workflows/codegen.yaml | 14 ++++--- .github/workflows/golang.yaml | 63 ++++++++++++++++++++++------- .github/workflows/helm-lint.yaml | 11 +++-- .github/workflows/helm-publish.yaml | 14 +++++-- .github/workflows/release.yaml | 28 ++++++------- .github/workflows/test-e2e.yaml | 48 ++++++++++++---------- 6 files changed, 116 insertions(+), 62 deletions(-) diff --git a/.github/workflows/codegen.yaml b/.github/workflows/codegen.yaml index 0f2264c6..7d639947 100644 --- a/.github/workflows/codegen.yaml +++ b/.github/workflows/codegen.yaml @@ -11,17 +11,21 @@ on: jobs: check: runs-on: ubuntu-24.04 + # go and the codegen tools come from the flake and tools.lock. + defaults: + run: + shell: nix develop --command bash -e {0} steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 with: persist-credentials: false - - id: go-version - uses: opendefensecloud/dev-kit/.github/actions/get-go-version@f16fb83a8669ba840346929d9c45b9efe95c4da0 # v1.0.15 - - uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7 + - name: Set up nix with the shared Cachix cache + uses: opendefensecloud/dev-kit/.github/actions/setup-nix@7427f5e62c1c45ec058e3e2b483a75d9dbe48805 # v2.2.0 with: - go-version: ${{ steps.go-version.outputs.version }} + cachix-auth-token: ${{ secrets.CACHIX_AUTH_TOKEN }} + cachix-signing-key: ${{ secrets.CACHIX_SIGNING_KEY }} - name: Run codegen run: | make codegen - name: Check for changes - uses: opendefensecloud/dev-kit/.github/actions/diff-check@f16fb83a8669ba840346929d9c45b9efe95c4da0 # v1.0.15 + uses: opendefensecloud/dev-kit/.github/actions/diff-check@7427f5e62c1c45ec058e3e2b483a75d9dbe48805 # v2.2.0 diff --git a/.github/workflows/golang.yaml b/.github/workflows/golang.yaml index 110af33e..56e51246 100644 --- a/.github/workflows/golang.yaml +++ b/.github/workflows/golang.yaml @@ -9,6 +9,7 @@ on: - "**/*.go" - ".github/workflows/golang.yaml" - ".golangci.yml" + - "flake.lock" - "flake.nix" - "go.mod" - "go.sum" @@ -20,6 +21,7 @@ on: - "**/*.go" - ".github/workflows/golang.yaml" - ".golangci.yml" + - "flake.lock" - "flake.nix" - "go.mod" - "go.sum" @@ -32,36 +34,67 @@ env: jobs: lint: runs-on: ubuntu-24.04 - outputs: - go-version: ${{ steps.go-version.outputs.version }} + # Tools (go, golangci-lint, shellcheck, addlicense) come from the flake + # and tools.lock. `make lint` runs both lint-no-golangci and golangci-lint. + defaults: + run: + shell: nix develop --command bash -e {0} steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 with: persist-credentials: false - - id: go-version - uses: opendefensecloud/dev-kit/.github/actions/get-go-version@f16fb83a8669ba840346929d9c45b9efe95c4da0 # v1.0.15 - - uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7 + - name: Set up nix with the shared Cachix cache + uses: opendefensecloud/dev-kit/.github/actions/setup-nix@7427f5e62c1c45ec058e3e2b483a75d9dbe48805 # v2.2.0 with: - go-version: ${{ steps.go-version.outputs.version }} - - name: lint-license-and-shell - run: | - make lint-no-golangci - - name: golangci-lint - uses: golangci/golangci-lint-action@ba0d7d2ec06a0ea1cb5fa41b2e4a3ab91d21278a # v9 + cachix-auth-token: ${{ secrets.CACHIX_AUTH_TOKEN }} + cachix-signing-key: ${{ secrets.CACHIX_SIGNING_KEY }} + # actions/setup-go used to warm GOMODCACHE / GOCACHE for us. Nix + # provides the toolchain but not those caches, so restore them + # explicitly. The key is trust-scoped (pr/trusted) so a pull request + # cannot poison the cache used by builds of trusted refs. + - name: Cache Go module + build caches + uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 + with: + path: | + ~/go/pkg/mod + ~/.cache/go-build + key: go-cache-lint-${{ github.event_name == 'pull_request' && 'pr' || 'trusted' }}-${{ hashFiles('go.sum') }}-${{ github.sha }} + restore-keys: | + go-cache-lint-${{ github.event_name == 'pull_request' && 'pr' || 'trusted' }}-${{ hashFiles('go.sum') }}- + go-cache-lint-${{ github.event_name == 'pull_request' && 'pr' || 'trusted' }}- + - name: lint + run: make lint test: needs: lint runs-on: ubuntu-24.04 + defaults: + run: + shell: nix develop --command bash -e {0} steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 with: persist-credentials: false - - uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7 + - name: Set up nix with the shared Cachix cache + uses: opendefensecloud/dev-kit/.github/actions/setup-nix@7427f5e62c1c45ec058e3e2b483a75d9dbe48805 # v2.2.0 + with: + cachix-auth-token: ${{ secrets.CACHIX_AUTH_TOKEN }} + cachix-signing-key: ${{ secrets.CACHIX_SIGNING_KEY }} + # See the lint job for rationale. Separate cache scope per job so lint + # (compile-side artefacts only) does not clobber test, which also builds + # envtest / ginkgo binaries. + - name: Cache Go module + build caches + uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 with: - go-version: ${{ needs.lint.outputs.go-version }} + path: | + ~/go/pkg/mod + ~/.cache/go-build + key: go-cache-test-${{ github.event_name == 'pull_request' && 'pr' || 'trusted' }}-${{ hashFiles('go.sum') }}-${{ github.sha }} + restore-keys: | + go-cache-test-${{ github.event_name == 'pull_request' && 'pr' || 'trusted' }}-${{ hashFiles('go.sum') }}- + go-cache-test-${{ github.event_name == 'pull_request' && 'pr' || 'trusted' }}- - name: test - run: | - make test + run: make test - name: Convert coverage to lcov uses: jandelgado/gcov2lcov-action@e4612787670fc5b5f49026b8c29c5569921de1db # v1.2.0 with: diff --git a/.github/workflows/helm-lint.yaml b/.github/workflows/helm-lint.yaml index 39fad8cb..96137624 100644 --- a/.github/workflows/helm-lint.yaml +++ b/.github/workflows/helm-lint.yaml @@ -17,6 +17,10 @@ on: jobs: lint: runs-on: ubuntu-24.04 + # helm comes from the flake (dev-kit's defaultPkgs). + defaults: + run: + shell: nix develop --command bash -e {0} steps: - name: Checkout uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 @@ -24,10 +28,11 @@ jobs: fetch-depth: 0 persist-credentials: false - - name: Set up Helm - uses: azure/setup-helm@9bc31f4ebc9c6b171d7bfbaa5d006ae7abdb4310 # v5 + - name: Set up nix with the shared Cachix cache + uses: opendefensecloud/dev-kit/.github/actions/setup-nix@7427f5e62c1c45ec058e3e2b483a75d9dbe48805 # v2.2.0 with: - version: 'v4.2.4' + cachix-auth-token: ${{ secrets.CACHIX_AUTH_TOKEN }} + cachix-signing-key: ${{ secrets.CACHIX_SIGNING_KEY }} - name: Lint Helm charts run: | diff --git a/.github/workflows/helm-publish.yaml b/.github/workflows/helm-publish.yaml index e7df2b33..1a554d97 100644 --- a/.github/workflows/helm-publish.yaml +++ b/.github/workflows/helm-publish.yaml @@ -34,6 +34,13 @@ jobs: (github.event_name == 'pull_request' && contains(github.event.pull_request.labels.*.name, 'ok-to-helm')) || (github.event_name == 'release' && github.event.action == 'published') + # helm comes from the flake. cosign comes from cosign-installer on the + # runner PATH; nix develop inherits PATH so it remains reachable from + # inside the dev shell. + defaults: + run: + shell: nix develop --command bash -e {0} + steps: - name: Checkout uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 @@ -41,10 +48,11 @@ jobs: fetch-depth: 0 persist-credentials: false - - name: Set up Helm - uses: azure/setup-helm@9bc31f4ebc9c6b171d7bfbaa5d006ae7abdb4310 # v5 + - name: Set up nix with the shared Cachix cache + uses: opendefensecloud/dev-kit/.github/actions/setup-nix@7427f5e62c1c45ec058e3e2b483a75d9dbe48805 # v2.2.0 with: - version: 'v4.2.4' + cachix-auth-token: ${{ secrets.CACHIX_AUTH_TOKEN }} + cachix-signing-key: ${{ secrets.CACHIX_SIGNING_KEY }} - name: Install cosign uses: sigstore/cosign-installer@6f9f17788090df1f26f669e9d70d6ae9567deba6 # v4.1.2 diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index f07d5393..5dc8c92c 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -16,6 +16,16 @@ jobs: contents: write id-token: write # for keyless cosign sign-blob attestations: write # for build-provenance attestation + # go comes from the flake. cosign comes from cosign-installer on the + # runner PATH; nix develop inherits PATH so it remains reachable from + # inside the dev shell. No actions/cache here: this is a privileged + # signing job, so it deliberately does not share a Go cache with + # unprivileged workflows (cache poisoning). This replaces the previous + # setup-go `cache: false`. + defaults: + run: + shell: nix develop --command bash -e {0} + steps: - name: Checkout code uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 @@ -23,21 +33,11 @@ jobs: fetch-depth: 0 persist-credentials: false - - name: Extract go version from flake.nix - id: get-go-version - run: | - GO_VERSION="$(sed -nE 's/^[[:space:]]*goVersion[[:space:]]*=[[:space:]]*"([0-9]+\.[0-9]+\.[0-9]+)";[[:space:]]*$/\1/p' flake.nix)" - if [ "$(printf '%s\n' "$GO_VERSION" | sed '/^$/d' | wc -l)" -ne 1 ]; then - echo "::error::Expected exactly one goVersion assignment in flake.nix" - exit 1 - fi - echo "version=$GO_VERSION" >> $GITHUB_OUTPUT - - - name: Setup Go - uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7 + - name: Set up nix with the shared Cachix cache + uses: opendefensecloud/dev-kit/.github/actions/setup-nix@7427f5e62c1c45ec058e3e2b483a75d9dbe48805 # v2.2.0 with: - go-version: ${{ steps.get-go-version.outputs.version }} - cache: false # privileged signing job: avoid shared cache (cache-poisoning) + cachix-auth-token: ${{ secrets.CACHIX_AUTH_TOKEN }} + cachix-signing-key: ${{ secrets.CACHIX_SIGNING_KEY }} - name: Run tests run: make test diff --git a/.github/workflows/test-e2e.yaml b/.github/workflows/test-e2e.yaml index 984de361..b87f626f 100644 --- a/.github/workflows/test-e2e.yaml +++ b/.github/workflows/test-e2e.yaml @@ -20,36 +20,40 @@ permissions: jobs: test-e2e: runs-on: ubuntu-24.04 + # go, kind, kubectl and helm all come from the flake. The e2e suite + # creates the cluster itself via `make test-e2e`, pinned to + # KIND_NODE_IMAGE (derived from ENVTEST_K8S_VERSION) — the Makefile + # stays the single source of truth for the K8s version. + defaults: + run: + shell: nix develop --command bash -e {0} steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 with: persist-credentials: false - - id: go-version - uses: opendefensecloud/dev-kit/.github/actions/get-go-version@f16fb83a8669ba840346929d9c45b9efe95c4da0 # v1.0.15 - - uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7 + - name: Set up nix with the shared Cachix cache + uses: opendefensecloud/dev-kit/.github/actions/setup-nix@7427f5e62c1c45ec058e3e2b483a75d9dbe48805 # v2.2.0 with: - go-version: ${{ steps.go-version.outputs.version }} - - name: Install Tools + cachix-auth-token: ${{ secrets.CACHIX_AUTH_TOKEN }} + cachix-signing-key: ${{ secrets.CACHIX_SIGNING_KEY }} + # actions/setup-go used to warm GOMODCACHE / GOCACHE for us; restore + # them explicitly now. Trust-scoped (pr/trusted) so a pull request + # cannot poison the cache used by builds of trusted refs. + - name: Cache Go module + build caches + uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 + with: + path: | + ~/go/pkg/mod + ~/.cache/go-build + key: go-cache-e2e-${{ github.event_name == 'pull_request' && 'pr' || 'trusted' }}-${{ hashFiles('go.sum') }}-${{ github.sha }} + restore-keys: | + go-cache-e2e-${{ github.event_name == 'pull_request' && 'pr' || 'trusted' }}-${{ hashFiles('go.sum') }}- + go-cache-e2e-${{ github.event_name == 'pull_request' && 'pr' || 'trusted' }}- + - name: Report tool versions run: | - # Install kind. The e2e suite creates the cluster itself via - # `make test-e2e`, pinned to KIND_NODE_IMAGE (derived from - # ENVTEST_K8S_VERSION) — the Makefile is the single source of truth - # for the K8s version, so we only need the binary here. - KIND_VERSION="v0.31.0" - curl -Lo ./kind "https://kind.sigs.k8s.io/dl/${KIND_VERSION}/kind-linux-amd64" - chmod +x ./kind - sudo mv ./kind /usr/local/bin/kind kind version - - # Install kubectl - curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl" - chmod +x ./kubectl - sudo mv ./kubectl /usr/local/bin/kubectl kubectl version --client - - # Install helm - curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash - helm version + helm version --short - name: Run E2E Test Suite env: E2E_IMAGE_SOURCE: ${{ inputs.is-local && 'local' || 'ghcr' }} From daa4260416a906f5181f5233a48ebd561a472daf Mon Sep 17 00:00:00 2001 From: alexander <259883306+AlexHardAtWork@users.noreply.github.com> Date: Wed, 9 Sep 2026 08:42:02 +0000 Subject: [PATCH 5/6] ci: restore the golangci-lint cache in the lint job --- .github/workflows/golang.yaml | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/.github/workflows/golang.yaml b/.github/workflows/golang.yaml index 56e51246..7c9e7aa2 100644 --- a/.github/workflows/golang.yaml +++ b/.github/workflows/golang.yaml @@ -48,19 +48,23 @@ jobs: with: cachix-auth-token: ${{ secrets.CACHIX_AUTH_TOKEN }} cachix-signing-key: ${{ secrets.CACHIX_SIGNING_KEY }} - # actions/setup-go used to warm GOMODCACHE / GOCACHE for us. Nix - # provides the toolchain but not those caches, so restore them + # actions/setup-go used to warm GOMODCACHE / GOCACHE for us, and + # golangci-lint-action kept golangci-lint's own analysis cache. Nix + # provides the toolchain but neither cache, so restore all three # explicitly. The key is trust-scoped (pr/trusted) so a pull request - # cannot poison the cache used by builds of trusted refs. - - name: Cache Go module + build caches + # cannot poison the cache used by builds of trusted refs, and it covers + # tools.lock / .golangci.yml because a golangci-lint version or config + # change invalidates its analysis results. + - name: Cache Go module, build and lint caches uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 with: path: | ~/go/pkg/mod ~/.cache/go-build - key: go-cache-lint-${{ github.event_name == 'pull_request' && 'pr' || 'trusted' }}-${{ hashFiles('go.sum') }}-${{ github.sha }} + ~/.cache/golangci-lint + key: go-cache-lint-${{ github.event_name == 'pull_request' && 'pr' || 'trusted' }}-${{ hashFiles('go.sum', 'tools.lock', '.golangci.yml') }}-${{ github.sha }} restore-keys: | - go-cache-lint-${{ github.event_name == 'pull_request' && 'pr' || 'trusted' }}-${{ hashFiles('go.sum') }}- + go-cache-lint-${{ github.event_name == 'pull_request' && 'pr' || 'trusted' }}-${{ hashFiles('go.sum', 'tools.lock', '.golangci.yml') }}- go-cache-lint-${{ github.event_name == 'pull_request' && 'pr' || 'trusted' }}- - name: lint run: make lint From 01735d38f009b8c7433857af91c792116eabfa9e Mon Sep 17 00:00:00 2001 From: alexander <259883306+AlexHardAtWork@users.noreply.github.com> Date: Wed, 9 Sep 2026 08:51:46 +0000 Subject: [PATCH 6/6] fix(ci): sanitize the tag used for the provenance asset name --- .github/workflows/release.yaml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 5dc8c92c..ccb8a434 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -74,7 +74,11 @@ jobs: # --bundle arc-.intoto.jsonl env: BUNDLE: ${{ steps.attest.outputs.bundle-path }} - run: cp "${BUNDLE}" "bin/arc-${GITHUB_REF_NAME}.intoto.jsonl" + run: | + # Tags may legally contain '/', which would turn the asset name into a + # path under a directory that does not exist and fail the release job. + asset_tag="${GITHUB_REF_NAME//\//-}" + cp "${BUNDLE}" "bin/arc-${asset_tag}.intoto.jsonl" - name: Install cosign uses: sigstore/cosign-installer@6f9f17788090df1f26f669e9d70d6ae9567deba6 # v4.1.2