diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index f4a03306..9846d3e6 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -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: | diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 1e2b6c3c..7ca2eb38 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -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: