forked from akai/readest
ci(release): attest release and nightly build artifacts (#4851)
Add actions/attest-build-provenance to both build workflows so every binary is attested in the same job that builds it, the only point where provenance meaningfully proves an artifact was built from source rather than uploaded by hand. release.yml (build-tauri): grant id-token and attestations write permissions, then attest the desktop bundles via the tauri-action artifactPaths output, the Android apks, and the Windows portable exe. nightly.yml (build): same permissions plus one step attesting the staged nightly-out binaries. Nightlies ship via download.readest.com, but gh attestation verify is digest based so it verifies them too. Verify a download with: gh attestation verify <file> --repo readest/readest Closes #4848 Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -40,6 +40,12 @@ jobs:
|
||||
|
||||
build:
|
||||
needs: compute-version
|
||||
permissions:
|
||||
contents: read
|
||||
# Required by actions/attest-build-provenance: id-token mints the Sigstore
|
||||
# OIDC identity, attestations writes the provenance to the repo's store.
|
||||
id-token: write
|
||||
attestations: write
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
@@ -381,6 +387,18 @@ jobs:
|
||||
;;
|
||||
esac
|
||||
|
||||
# Attest the distributable binaries staged in nightly-out (apks, AppImage,
|
||||
# app.tar.gz, setup/portable exe). gh attestation verify is digest-based,
|
||||
# so it verifies these against readest/readest even though they ship via
|
||||
# download.readest.com rather than a GitHub release. The .sig updater
|
||||
# signatures are excluded — they are not binaries users run.
|
||||
- name: attest nightly binaries
|
||||
uses: actions/attest-build-provenance@0f67c3f4856b2e3261c31976d6725780e5e4c373 # v4.1.1
|
||||
with:
|
||||
subject-path: |
|
||||
nightly-out/Readest*
|
||||
!nightly-out/*.sig
|
||||
|
||||
- name: upload artifacts + fragment to R2
|
||||
shell: bash
|
||||
run: |
|
||||
|
||||
@@ -122,6 +122,10 @@ jobs:
|
||||
needs: get-release
|
||||
permissions:
|
||||
contents: write
|
||||
# Required by actions/attest-build-provenance: id-token mints the Sigstore
|
||||
# OIDC identity, attestations writes the provenance to the repo's store.
|
||||
id-token: write
|
||||
attestations: write
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
@@ -267,6 +271,14 @@ jobs:
|
||||
gh release upload ${{ needs.get-release.outputs.release_tag }} $universial_apk.sig --clobber
|
||||
gh release upload ${{ needs.get-release.outputs.release_tag }} $arm64_apk.sig --clobber
|
||||
|
||||
- name: attest Android apks
|
||||
if: matrix.config.release == 'android'
|
||||
uses: actions/attest-build-provenance@0f67c3f4856b2e3261c31976d6725780e5e4c373 # v4.1.1
|
||||
with:
|
||||
subject-path: |
|
||||
apps/readest-app/Readest_${{ needs.get-release.outputs.release_version }}_universal.apk
|
||||
apps/readest-app/Readest_${{ needs.get-release.outputs.release_version }}_arm64.apk
|
||||
|
||||
- name: download and update latest.json for Android release
|
||||
if: matrix.config.release == 'android'
|
||||
env:
|
||||
@@ -309,6 +321,7 @@ jobs:
|
||||
run: cargo install tauri-cli --git https://github.com/tauri-apps/tauri --branch feat/truly-portable-appimage --force
|
||||
|
||||
- uses: tauri-apps/tauri-action@84b9d35b5fc46c1e45415bdb6144030364f7ebc5 # v0
|
||||
id: tauri
|
||||
if: matrix.config.release != 'android'
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
@@ -332,6 +345,16 @@ jobs:
|
||||
releaseBody: ${{ needs.get-release.outputs.release_note }}
|
||||
args: ${{ matrix.config.args || '' }}
|
||||
|
||||
# Attest the freshly built desktop bundles (installers, AppImage, dmg,
|
||||
# updater archives + their .sig). tauri-action reports their on-disk paths
|
||||
# as a JSON array; fromJSON('"\n"') yields a real newline to join them into
|
||||
# the newline-delimited list subject-path expects.
|
||||
- name: attest desktop bundles
|
||||
if: matrix.config.release != 'android' && steps.tauri.outputs.artifactPaths != ''
|
||||
uses: actions/attest-build-provenance@0f67c3f4856b2e3261c31976d6725780e5e4c373 # v4.1.1
|
||||
with:
|
||||
subject-path: ${{ join(fromJSON(steps.tauri.outputs.artifactPaths), fromJSON('"\n"')) }}
|
||||
|
||||
- name: upload release notes to GitHub release
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
@@ -384,6 +407,15 @@ jobs:
|
||||
echo "Uploading signature to GitHub release"
|
||||
gh release upload ${{ needs.get-release.outputs.release_tag }} $bin_file.sig --clobber
|
||||
|
||||
# The portable rebuild above is not produced by tauri-action, so it is not
|
||||
# covered by the "attest desktop bundles" step; attest it here. Exactly one
|
||||
# portable exe is staged at the workspace root per Windows leg.
|
||||
- name: attest Windows portable binary
|
||||
if: matrix.config.os == 'windows-latest'
|
||||
uses: actions/attest-build-provenance@0f67c3f4856b2e3261c31976d6725780e5e4c373 # v4.1.1
|
||||
with:
|
||||
subject-path: Readest_*-portable.exe
|
||||
|
||||
- name: download and update latest.json for Windows portable release
|
||||
if: matrix.config.os == 'windows-latest'
|
||||
env:
|
||||
|
||||
Reference in New Issue
Block a user