From 4023aaa26da0f3fee5ba0af84ed7f24924cc3da5 Mon Sep 17 00:00:00 2001 From: pasta Date: Sat, 31 Oct 2026 05:10:01 +0000 Subject: [PATCH] ci: publish and attest the Guix SHA256SUMS of release tags CI Guix-builds every release tag but only keeps per-host artifacts, so its result can't be compared with guix.sigs. On v* tags pushed to dashpay/dash, combine the per-host SHA256SUMS.part files with contrib/guix/guix-attest into a guix.sigs-format noncodesigned.SHA256SUMS. Attest it with a keyless Sigstore attestation (tied to this workflow and the tag) and upload it as an artifact. No signing key is stored anywhere. Tag builds no longer restore the depends-sources or Guix/depends caches, which labelled pull_request_target runs can write (any cache entry can plant arbitrary workspace files). Co-Authored-By: Claude Opus 5.5 --- .github/workflows/guix-build.yml | 56 ++++++++++++++++++++++++++++++++ doc/release-process.md | 7 ++++ 2 files changed, 63 insertions(+) diff --git a/.github/workflows/guix-build.yml b/.github/workflows/guix-build.yml index 9004df28ec4e..cb6f679e9ab8 100644 --- a/.github/workflows/guix-build.yml +++ b/.github/workflows/guix-build.yml @@ -103,7 +103,10 @@ jobs: path: dash fetch-depth: 0 + # Attested tag builds must not restore caches that labelled + # pull_request_target runs can write - name: Cache depends sources + if: github.ref_type != 'tag' uses: actions/cache@v5 with: path: dash/depends/sources @@ -113,6 +116,7 @@ jobs: - name: Cache Guix and depends id: guix-cache-restore + if: github.ref_type != 'tag' uses: actions/cache@v5 with: path: | @@ -169,3 +173,55 @@ jobs: uses: actions/attest@v4 with: subject-path: ${{ github.workspace }}/dash/guix-build*/output/${{ matrix.build_target }}/* + + - name: Upload SHA256SUMS fragment + uses: actions/upload-artifact@v6 + with: + name: guix-sha256sums-${{ matrix.build_target }} + path: ${{ github.workspace }}/dash/guix-build*/output/${{ matrix.build_target }}/SHA256SUMS.part + if-no-files-found: error + + # Publish the release's guix.sigs-format noncodesigned.SHA256SUMS with a + # keyless (Sigstore) attestation tying it to this workflow and tag + attest: + needs: build + if: github.repository == 'dashpay/dash' && github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v') + runs-on: ubuntu-24.04 + permissions: + id-token: write + attestations: write + steps: + - name: Checkout + uses: actions/checkout@v6 + with: + persist-credentials: false + path: dash + + - name: Download SHA256SUMS fragments + uses: actions/download-artifact@v8 + with: + pattern: guix-sha256sums-* + path: ${{ runner.temp }}/fragments + merge-multiple: true + + - name: Create SHA256SUMS + working-directory: dash + run: | + VERSION="${GITHUB_REF_NAME#v}" + mkdir "${RUNNER_TEMP}/guix.sigs" + # Only finds the outputs of a build versioned exactly after the tag + env FORCE_VERSION="${VERSION}" \ + OUTDIR_BASE="${RUNNER_TEMP}/fragments/guix-build-${VERSION}/output" \ + GUIX_SIGS_REPO="${RUNNER_TEMP}/guix.sigs" SIGNER=dashcore-ci NO_SIGN=1 \ + ./contrib/guix/guix-attest + + - name: Attest SHA256SUMS + uses: actions/attest@v4 + with: + subject-path: ${{ runner.temp }}/guix.sigs/*/*/noncodesigned.SHA256SUMS + + - name: Upload SHA256SUMS + uses: actions/upload-artifact@v6 + with: + name: guix-sigs-${{ github.ref_name }} + path: ${{ runner.temp }}/guix.sigs/ diff --git a/doc/release-process.md b/doc/release-process.md index f4c417875f54..224477fe5547 100644 --- a/doc/release-process.md +++ b/doc/release-process.md @@ -113,6 +113,13 @@ _Note: we ship releases for only some supported HOSTs so consider providing limi - [Verifying build output attestations](/contrib/guix/README.md#verifying-build-output-attestations) +CI also Guix-builds each release tag and publishes its `noncodesigned.SHA256SUMS` as the `guix-sigs-v${VERSION}` artifact of the `Guix Build` run, with a Sigstore attestation. Verify it, then compare it with the guix.sigs attestations or check binaries against it: + +```sh +gh attestation verify noncodesigned.SHA256SUMS --repo dashpay/dash \ + --signer-workflow dashpay/dash/.github/workflows/guix-build.yml --source-ref "refs/tags/v${VERSION}" +``` + ### Commit your non codesigned signature to guix.sigs ```sh