From 2626d58d4d000cf09e5d162839290b9e2111aeb3 Mon Sep 17 00:00:00 2001 From: Benoit Tigeot Date: Wed, 29 Jul 2026 16:48:52 +0200 Subject: [PATCH] feat: make Helm releases independently verifiable Helm ships binaries via Azure with no cosign, SBOM, or provenance, and the upstream release.yml is gated to helm/helm so it can't be exercised on a fork. This adds a self-contained release-signed workflow plus the .goreleaser.yaml archive/sbom/checksum/signs config it needs, modeled on goreleaser/example-secure, to demo the full pipeline end-to-end before proposing it upstream. Signed-off-by: Benoit Tigeot --- .github/workflows/release-signed.yml | 53 ++++++++++++++++++++++++++++ .goreleaser.yaml | 49 +++++++++++++++++++++++-- Makefile | 2 +- 3 files changed, 100 insertions(+), 4 deletions(-) create mode 100644 .github/workflows/release-signed.yml diff --git a/.github/workflows/release-signed.yml b/.github/workflows/release-signed.yml new file mode 100644 index 000000000..caf952a56 --- /dev/null +++ b/.github/workflows/release-signed.yml @@ -0,0 +1,53 @@ +# +# PoC: signed release with SBOMs and build provenance. +# Modeled on https://github.com/goreleaser/example-secure +# +name: release-signed + +on: + push: + tags: + - "v*" + +permissions: + contents: write # needed to write releases + id-token: write # needed for keyless signing + attestations: write # needed for provenance + +jobs: + release: + runs-on: ubuntu-latest + steps: + - name: Checkout source code + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # pin@v7.0.1 + with: + fetch-depth: 0 + persist-credentials: false + + - name: Add variables to environment file + run: cat ".github/env" >> "$GITHUB_ENV" + + - name: Setup Go + uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # pin@7.0.0 + with: + go-version: '${{ env.GOLANG_VERSION }}' + check-latest: true + + - name: Install Cosign + uses: sigstore/cosign-installer@cad07c2e89fa2edd6e2d7bab4c1aa38e53f76003 # v4.1.1 + + - name: Install Syft + uses: anchore/sbom-action/download-syft@e22c389904149dbc22b58101806040fa8d37a610 # v0.24.0 + + - name: Run GoReleaser + uses: goreleaser/goreleaser-action@e24998b8b67b290c2fa8b7c14fcfa7de2c5c9b8c # v7.1.0 + with: + version: "~> v2" + args: release --clean + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Attest build provenance + uses: actions/attest-build-provenance@a2bbfa25375fe432b6a289bc6b6cd05ecd0c4c32 # v4.1.0 + with: + subject-checksums: ./_dist/checksums.txt diff --git a/.goreleaser.yaml b/.goreleaser.yaml index ab2089882..fa2c52aba 100644 --- a/.goreleaser.yaml +++ b/.goreleaser.yaml @@ -55,14 +55,57 @@ builds: - goos: windows goarch: loong64 main: ./cmd/helm - no_unique_dist_dir: true - binary: "{{ .Os }}-{{ .Arch }}/helm" + binary: helm + mod_timestamp: "{{ .CommitTimestamp }}" ldflags: - - "{{ .Env.LDFLAGS }}" + - -w -s + - -extldflags "-static" + - -X helm.sh/helm/v4/internal/version.version={{ .Tag }} + - -X helm.sh/helm/v4/internal/version.metadata= + - -X helm.sh/helm/v4/internal/version.gitCommit={{ .FullCommit }} + - -X helm.sh/helm/v4/internal/version.gitTreeState=clean flags: - -trimpath dir: . +source: + enabled: true + name_template: "{{ .ProjectName }}.src" + +archives: + - formats: + - tar.gz + format_overrides: + - goos: windows + formats: + - zip + name_template: "helm-{{ .Tag }}-{{ .Os }}-{{ .Arch }}" + wrap_in_directory: true + files: + - LICENSE + - README.md + builds_info: + mtime: "{{ .CommitTimestamp }}" + +sboms: + - artifacts: archive + - id: source + artifacts: source + +checksum: + name_template: "checksums.txt" + +signs: + - cmd: cosign + signature: "${artifact}.sigstore.json" + args: + - sign-blob + - "--bundle=${signature}" + - "${artifact}" + - "--yes" + artifacts: checksum + output: true + snapshot: version_template: "{{ if index .Env \"GORELEASER_CURRENT_TAG\" }}{{ .Env.GORELEASER_CURRENT_TAG }}{{ else }}{{ incpatch .Version }}-next{{ end }}" diff --git a/Makefile b/Makefile index 5a9c792bb..d6def960c 100644 --- a/Makefile +++ b/Makefile @@ -172,7 +172,7 @@ $(GOIMPORTS): .PHONY: build-cross build-cross: LDFLAGS += -extldflags "-static" build-cross: $(GORELEASER) - LDFLAGS='$(LDFLAGS)' $(GORELEASER) build --snapshot --clean + $(GORELEASER) build --snapshot --clean .PHONY: dist dist: