diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 5e8cd0d..7700322 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -14,13 +14,13 @@ permissions: jobs: goreleaser: - uses: OpenCHAMI/github-actions/.github/workflows/build-check-goreleaser.yml@e953668e2039692eb291abb9f79f666a1dbdf6cb # github-actions under test (seantronsen/feat/makefile-drift-avoidance) + uses: OpenCHAMI/github-actions/.github/workflows/build-check-goreleaser.yml@5a0ca6e79ffd9f8db2b517beb176039628d22095 # github-actions under test (seantronsen/feat/release-attestation) with: go-version-file: go.mod validate: needs: goreleaser - uses: OpenCHAMI/github-actions/.github/workflows/validate-packages.yml@466cf8d13ea0a1c493f3bfe9c35cc155eb8da367 # github-actions under test (seantronsen/feat/redesign-deployment) + uses: OpenCHAMI/github-actions/.github/workflows/validate-packages.yml@5a0ca6e79ffd9f8db2b517beb176039628d22095 # github-actions under test (seantronsen/feat/release-attestation) with: packages: | - name: testbed-quadlet* diff --git a/.github/workflows/cleanup.yml b/.github/workflows/cleanup.yml index 064b881..b9017ca 100644 --- a/.github/workflows/cleanup.yml +++ b/.github/workflows/cleanup.yml @@ -16,4 +16,4 @@ permissions: jobs: cleanup: - uses: OpenCHAMI/github-actions/.github/workflows/pr-registry-cleanup.yml@7af41e39e2270b711bd18385f1586df9f7bf98de # github-actions under test (seantronsen/feat/decouple-pr-cleanup) + uses: OpenCHAMI/github-actions/.github/workflows/pr-registry-cleanup.yml@5a0ca6e79ffd9f8db2b517beb176039628d22095 # github-actions under test (seantronsen/feat/release-attestation) diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml index 0518ec6..6c5c010 100644 --- a/.github/workflows/dependency-review.yml +++ b/.github/workflows/dependency-review.yml @@ -10,7 +10,7 @@ permissions: jobs: check: - uses: OpenCHAMI/github-actions/.github/workflows/dependency-review.yml@466cf8d13ea0a1c493f3bfe9c35cc155eb8da367 # github-actions under test (seantronsen/feat/redesign-deployment) + uses: OpenCHAMI/github-actions/.github/workflows/dependency-review.yml@5a0ca6e79ffd9f8db2b517beb176039628d22095 # github-actions under test (seantronsen/feat/release-attestation) permissions: contents: read # baseline for checkout pull-requests: write # summary comment on the PR diff --git a/.github/workflows/govulncheck.yml b/.github/workflows/govulncheck.yml index f113905..fca34aa 100644 --- a/.github/workflows/govulncheck.yml +++ b/.github/workflows/govulncheck.yml @@ -13,7 +13,7 @@ permissions: jobs: check: - uses: OpenCHAMI/github-actions/.github/workflows/govulncheck.yml@466cf8d13ea0a1c493f3bfe9c35cc155eb8da367 # github-actions under test (seantronsen/feat/redesign-deployment) + uses: OpenCHAMI/github-actions/.github/workflows/govulncheck.yml@5a0ca6e79ffd9f8db2b517beb176039628d22095 # github-actions under test (seantronsen/feat/release-attestation) govulncheck: if: ${{ always() }} diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index e58e623..52e3cc8 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -16,21 +16,21 @@ permissions: jobs: lint-go: - uses: OpenCHAMI/github-actions/.github/workflows/lint-go.yml@e953668e2039692eb291abb9f79f666a1dbdf6cb # github-actions under test (seantronsen/feat/makefile-drift-avoidance) + uses: OpenCHAMI/github-actions/.github/workflows/lint-go.yml@5a0ca6e79ffd9f8db2b517beb176039628d22095 # github-actions under test (seantronsen/feat/release-attestation) with: go-version-file: go.mod lint-ci: - uses: OpenCHAMI/github-actions/.github/workflows/lint-ci.yml@e953668e2039692eb291abb9f79f666a1dbdf6cb # github-actions under test (seantronsen/feat/makefile-drift-avoidance) + uses: OpenCHAMI/github-actions/.github/workflows/lint-ci.yml@5a0ca6e79ffd9f8db2b517beb176039628d22095 # github-actions under test (seantronsen/feat/release-attestation) permissions: contents: read # baseline for checkout security-events: write # zizmor SARIF upload to GHAS lint-renovate: - uses: OpenCHAMI/github-actions/.github/workflows/lint-renovate.yml@466cf8d13ea0a1c493f3bfe9c35cc155eb8da367 # github-actions under test (seantronsen/feat/redesign-deployment) + uses: OpenCHAMI/github-actions/.github/workflows/lint-renovate.yml@5a0ca6e79ffd9f8db2b517beb176039628d22095 # github-actions under test (seantronsen/feat/release-attestation) lint-makefile-common: - uses: OpenCHAMI/github-actions/.github/workflows/lint-makefile-common.yml@e953668e2039692eb291abb9f79f666a1dbdf6cb # github-actions under test (seantronsen/feat/makefile-drift-avoidance) + uses: OpenCHAMI/github-actions/.github/workflows/lint-makefile-common.yml@5a0ca6e79ffd9f8db2b517beb176039628d22095 # github-actions under test (seantronsen/feat/release-attestation) lint: if: ${{ always() }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index a2b90d4..3423561 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -6,8 +6,9 @@ name: release # PR images and releases; build-release-goreleaser picks the mode from the # event: # - pull_request: pushes ghcr.io/openchami/github-actions-testbed:pr-. -# - v* tag push: semver images, signed packages, draft release, validation, -# then publish. Safe to tag freely: nothing depends on this repo. +# - v* tag push: semver images, packages, draft release, then validation and +# signing in parallel, signatures attached, then publish. Safe to tag freely: +# nothing depends on this repo. on: pull_request: @@ -19,41 +20,21 @@ permissions: contents: read jobs: - # Throwaway signing key, regenerated each run. Not a secret (it travels as - # a job output); fine here, since the packages are only for testing. - test-key: - runs-on: ubuntu-slim - outputs: - gpg-key-b64: ${{ steps.key.outputs.gpg-key-b64 }} - steps: - - name: Generate throwaway GPG key - id: key - run: | - set -euo pipefail - GNUPGHOME=$(mktemp -d) - export GNUPGHOME - gpg --batch --quiet --passphrase '' \ - --quick-gen-key 'github-actions testbed throwaway key ' rsa3072 sign 1d - echo "gpg-key-b64=$(gpg --batch --armor --export-secret-keys | base64 -w0)" >> "$GITHUB_OUTPUT" - goreleaser: - needs: test-key permissions: contents: write # release creation, uploading assets packages: write # image push, container provenance id-token: write # Sigstore signing (attest-build-provenance) attestations: write # build provenance attestations - uses: OpenCHAMI/github-actions/.github/workflows/build-release-goreleaser.yml@e953668e2039692eb291abb9f79f666a1dbdf6cb # github-actions under test (seantronsen/feat/makefile-drift-avoidance) + uses: OpenCHAMI/github-actions/.github/workflows/build-release-goreleaser.yml@5a0ca6e79ffd9f8db2b517beb176039628d22095 # github-actions under test (seantronsen/feat/release-attestation) with: go-version-file: go.mod - secrets: - gpg-key: ${{ github.event_name == 'push' && needs.test-key.outputs.gpg-key-b64 || '' }} trivy: # Scans the images named in .goreleaser.yaml (testbed and testbed-alt) at # this run's tag (pr- on PRs); fork PRs push nothing, so nothing matches. needs: goreleaser - uses: OpenCHAMI/github-actions/.github/workflows/trivy-image-scan.yml@3f4837668325e804c057a415e108d1393af3406a # github-actions under test (seantronsen/feat/decouple-trivy) + uses: OpenCHAMI/github-actions/.github/workflows/trivy-image-scan.yml@5a0ca6e79ffd9f8db2b517beb176039628d22095 # github-actions under test (seantronsen/feat/release-attestation) permissions: contents: read # baseline for checkout packages: read # read image versions @@ -65,7 +46,7 @@ jobs: # PR builds produce no packages (they're validated in build.yml). if: ${{ github.event_name == 'push' }} needs: goreleaser - uses: OpenCHAMI/github-actions/.github/workflows/validate-packages.yml@466cf8d13ea0a1c493f3bfe9c35cc155eb8da367 # github-actions under test (seantronsen/feat/redesign-deployment) + uses: OpenCHAMI/github-actions/.github/workflows/validate-packages.yml@5a0ca6e79ffd9f8db2b517beb176039628d22095 # github-actions under test (seantronsen/feat/release-attestation) with: packages: | - name: testbed-quadlet* @@ -86,9 +67,30 @@ jobs: deb-files: - /usr/share/doc/testbed/copyright + sign: + if: ${{ github.event_name == 'push' }} + needs: goreleaser + uses: OpenCHAMI/github-actions/.github/workflows/gpg-sign-artifacts.yml@5a0ca6e79ffd9f8db2b517beb176039628d22095 # github-actions under test (seantronsen/feat/release-attestation) + secrets: + repo-cert-key: ${{ secrets.GPG_REPO_CERT_KEY_B64 }} + master-public-key: ${{ secrets.MASTER_PUBLIC_ASC }} + master-fingerprint: ${{ secrets.MASTER_FPR }} + + release-modify: + needs: sign + permissions: + contents: write # edit the draft GitHub Release and upload files + uses: OpenCHAMI/github-actions/.github/workflows/release-modify.yml@5a0ca6e79ffd9f8db2b517beb176039628d22095 # github-actions under test (seantronsen/feat/release-attestation) + with: + notes: | + ${{ needs.sign.outputs.release-notes }} + + Built by [release run ${{ github.run_id }}](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}). + files-artifact-name: release-signatures + publish: if: ${{ github.event_name == 'push' }} - needs: [goreleaser, validate] + needs: [validate, release-modify] permissions: contents: write # publish the draft GitHub Release - uses: OpenCHAMI/github-actions/.github/workflows/publish-release.yml@466cf8d13ea0a1c493f3bfe9c35cc155eb8da367 # github-actions under test (seantronsen/feat/redesign-deployment) + uses: OpenCHAMI/github-actions/.github/workflows/release-publish.yml@5a0ca6e79ffd9f8db2b517beb176039628d22095 # github-actions under test (seantronsen/feat/release-attestation) diff --git a/.github/workflows/reuse.yml b/.github/workflows/reuse.yml index 1a6d0fb..863f68e 100644 --- a/.github/workflows/reuse.yml +++ b/.github/workflows/reuse.yml @@ -12,7 +12,7 @@ permissions: jobs: check: - uses: OpenCHAMI/github-actions/.github/workflows/reuse.yml@e953668e2039692eb291abb9f79f666a1dbdf6cb # github-actions under test (seantronsen/feat/makefile-drift-avoidance) + uses: OpenCHAMI/github-actions/.github/workflows/reuse.yml@5a0ca6e79ffd9f8db2b517beb176039628d22095 # github-actions under test (seantronsen/feat/release-attestation) reuse: if: ${{ always() }} diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index 0e4eb91..b7e9a55 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -19,7 +19,7 @@ jobs: contents: read # baseline for checkout security-events: write # SARIF upload to GHAS id-token: write # publish results to the OpenSSF dashboard - uses: OpenCHAMI/github-actions/.github/workflows/scorecard.yml@466cf8d13ea0a1c493f3bfe9c35cc155eb8da367 # github-actions under test (seantronsen/feat/redesign-deployment) + uses: OpenCHAMI/github-actions/.github/workflows/scorecard.yml@5a0ca6e79ffd9f8db2b517beb176039628d22095 # github-actions under test (seantronsen/feat/release-attestation) scorecard: if: ${{ always() }} diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index b5890be..862663e 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -12,7 +12,7 @@ permissions: jobs: stale: - uses: OpenCHAMI/github-actions/.github/workflows/stale.yml@466cf8d13ea0a1c493f3bfe9c35cc155eb8da367 # github-actions under test (seantronsen/feat/redesign-deployment) + uses: OpenCHAMI/github-actions/.github/workflows/stale.yml@5a0ca6e79ffd9f8db2b517beb176039628d22095 # github-actions under test (seantronsen/feat/release-attestation) permissions: issues: write # label, comment on, and close stale issues pull-requests: write # label, comment on, and close stale PRs diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 61edeb0..e1dcf18 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -18,7 +18,7 @@ permissions: jobs: test-unit-go: - uses: OpenCHAMI/github-actions/.github/workflows/test-unit-go.yml@94dcf268d84a4bf0396e2a93f56769199cd7cb7a # github-actions under test (seantronsen/feat/runner-selection) + uses: OpenCHAMI/github-actions/.github/workflows/test-unit-go.yml@5a0ca6e79ffd9f8db2b517beb176039628d22095 # github-actions under test (seantronsen/feat/release-attestation) with: go-version-file: go.mod coverage: true diff --git a/.goreleaser.yaml b/.goreleaser.yaml index 76d6603..38be531 100644 --- a/.goreleaser.yaml +++ b/.goreleaser.yaml @@ -37,8 +37,9 @@ archives: files: - LICENSES/* +# gpg-sign-artifacts signs this file; the name must be exactly checksums.txt. checksum: - name_template: "{{ .ProjectName }}_checksums.txt" + name_template: checksums.txt dockers_v2: - id: testbed @@ -133,9 +134,6 @@ nfpms: dependencies: - podman (>= 5.0.0) - systemd - rpm: - signature: - key_file: "{{ .Env.GPG_KEY_PATH }}" # Binary package: one per goarch, so a single package glob matches several # files across architectures. - id: testbed @@ -162,21 +160,11 @@ nfpms: release: "1.el9" deb: release: "1" - rpm: - signature: - key_file: "{{ .Env.GPG_KEY_PATH }}" release: disable: '{{ if eq .Env.IS_PR_BUILD "true" }}true{{ else }}false{{ end }}' name_template: "v{{ .Version }}" prerelease: auto - footer: | - ## Verifying packages - - ```bash - rpm --import gpg-public-key.asc - rpm -K testbed-quadlet-*.rpm - ``` changelog: use: git diff --git a/README.md b/README.md index 15a5ccf..077b777 100644 --- a/README.md +++ b/README.md @@ -33,8 +33,9 @@ workflows end to end, releases included, and doubles as the template for wiring them into a service repo. Nothing depends on its images, packages, or releases. It exercises every GoReleaser release effect: binaries, archives, a multi-arch -image (`dockers_v2`), rpm/deb quadlet packages, signing (with a throwaway key -generated per run), attestations, and the GitHub release. +image (`dockers_v2`), rpm/deb quadlet packages, attestations, and the GitHub +release, plus release signing (`checksums.txt`, through the repo's real key +chain, like any other OpenCHAMI repo). ## Using this as a template @@ -47,8 +48,9 @@ generated per run), attestations, and the GitHub release. files. 4. Pin `OpenCHAMI/github-actions` to a release (or SHA) instead of the testbed's branch pin. -5. Replace the throwaway `test-key` job in `release.yml` with your real signing - key secret. Annotated GoReleaser reference: +5. Provision your repo's key as the `GPG_REPO_CERT_KEY_B64` secret; `sign` + also reads the `MASTER_PUBLIC_ASC` / `MASTER_FPR` org secrets. Annotated + GoReleaser reference: [`.goreleaser.example.yml`](https://github.com/OpenCHAMI/github-actions/blob/main/.goreleaser.example.yml). ## Testing the workflows