From 161d69177c09c2368cb9905331b5a5432e079d41 Mon Sep 17 00:00:00 2001 From: MotherSphere Date: Fri, 28 Aug 2026 00:25:24 +0200 Subject: [PATCH] fix(release): upload with gh, not an action that insists on managing the draft With the job skips fixed, all four builds finally ran, compiled, and passed their smoke test - and then every one failed uploading: Found release v0.10.0 (with id=377998799) Unexpected error fetching GitHub release for tag refs/heads/main: HttpError: Resource not accessible by integration - .../rest/releases/releases#update-a-release softprops/action-gh-release does not just upload assets: it PATCHes the release to manage the draft flag, and that update is refused against this draft. The workflow grants contents: write and the repository default is write, so this is the action's own insistence on owning a field it does not need to touch. That insistence is also what published an empty v0.10.0 in front of users earlier today: absent a `draft:` input it calls finalizeRelease() after uploading, which sets draft:false. Adding `draft: true` stopped that, and now the same code path 403s. `gh release upload` only ever adds assets. It cannot publish a release, so the draft is safe by construction rather than by remembering a flag - and it is exactly what the sign job has done successfully since v0.9.2, in this same workflow, with this same token. The action leaves the release path entirely, which also removes a third-party action holding write access to releases. The draft assertion after the upload stays. It is now belt-and-braces rather than load-bearing, and it costs one API call. --- .github/workflows/release-please.yml | 30 +++++++++++++--------------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/.github/workflows/release-please.yml b/.github/workflows/release-please.yml index 89afbf7..c20d1eb 100644 --- a/.github/workflows/release-please.yml +++ b/.github/workflows/release-please.yml @@ -192,24 +192,22 @@ jobs: file "${{ matrix.asset }}" | grep -q 'x86_64' \ || { echo "::error::${{ matrix.asset }} is not an x86_64 binary"; exit 1; } - # `draft: true` is LOAD-BEARING, not a preference. Without it this action - # calls finalizeRelease() after uploading, which PATCHes draft:false - so - # the first matrix leg to finish would publish v0.10.0 as /releases/latest - # carrying one of four binaries and zero signatures, and the sign job's - # closing `--draft=false` would be a silent no-op. Every check would still - # be green. That is the v0.7.0 incident, reached automatically. + # Uploaded with `gh`, not softprops/action-gh-release. The action wants + # to PATCH the release to manage its draft flag, which returns 403 + # "Resource not accessible by integration" against this draft - and its + # default behaviour is to PUBLISH the release after uploading unless told + # otherwise, which is what put an empty v0.10.0 in front of users once + # already. `gh release upload` only ever adds assets: it cannot publish + # anything, so the draft is safe by construction rather than by flag. # - # The action's own action.yml says it: "When reusing an existing draft - # release, set this to true to keep it draft; omit it to publish after - # upload." Verified in the pinned build: an absent input parses to - # `undefined`, and the only guard is - # `input_draft === true || release.draft === false`. + # This is also exactly what the sign job below already does, and has done + # successfully since v0.9.2. - name: Upload binary to GitHub Release - uses: softprops/action-gh-release@3d0d9888cb7fd7b750713d6e236d1fcb99157228 # v3.0.2 - with: - tag_name: ${{ needs.target.outputs.tag }} - files: ${{ matrix.asset }} - draft: true + shell: bash + env: + GH_TOKEN: ${{ github.token }} + TAG: ${{ needs.target.outputs.tag }} + run: gh release upload "$TAG" -R "$GITHUB_REPOSITORY" "${{ matrix.asset }}" --clobber # Assert the hold actually survived, so a future action bump cannot # silently reintroduce the above. Cheap, and it fails the leg rather than