From defc6f7c7f8edcddff4c46ad5a7eb778894f59b6 Mon Sep 17 00:00:00 2001 From: Shane B Date: Sun, 9 Aug 2026 20:16:30 +0200 Subject: [PATCH] Pass the release token as an input, not an environment variable The v1.0.5 release published with no assets. Both binaries built and uploaded as workflow artifacts; only the final step failed: Unexpected error fetching GitHub release for tag refs/tags/macos-exporter-v1.0.5: HttpError: Resource not accessible by integration softprops/action-gh-release@v2 takes its credential as the `token` input, which defaults to ${{ github.token }}. Its own documentation says "a non-empty explicit token overrides GITHUB_TOKEN" - and since the default is always non-empty, the GITHUB_TOKEN environment variable this workflow set was ignored outright. The PAT was never used. It authenticated as the built-in token, whose contents permission is read-only for this repository, and so could not update the release. Passing the env var is the v1 idiom, which is presumably where it came from. Also granting contents: write to both build jobs, so an unset or expired PAT degrades to a working upload rather than a 403 - the action treats an empty token as unset and falls back to the built-in one. Nothing to do with the version wiring changed for 1.0.5: every step that used it succeeded, including naming and uploading both zips. Co-Authored-By: Claude Opus 5 --- .github/workflows/macos-exporter-python.yml | 30 ++++++++++++++++++--- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/.github/workflows/macos-exporter-python.yml b/.github/workflows/macos-exporter-python.yml index 4b480f87..b5b12ebf 100644 --- a/.github/workflows/macos-exporter-python.yml +++ b/.github/workflows/macos-exporter-python.yml @@ -98,6 +98,12 @@ jobs: runs-on: macos-14 # Apple Silicon environment: 'MacOS Exporter App CI' + # The repository default is read-only, which is what turned a missing token into a 403 at + # the very last step. Granting it here means the upload still works if the PAT is ever + # unset or expires - the action treats an empty token as unset and falls back to this one. + permissions: + contents: write + # Only run this for 'macos-exporter-v' tags! if: | github.event_name == 'release' @@ -157,20 +163,31 @@ jobs: name: ${{ env.APP_NAME }}-${{ env.APP_VERSION }}-${{ runner.arch }}.zip path: ${{ github.workspace }}/output/${{ env.APP_NAME }}-${{ env.APP_VERSION }}-${{ runner.arch }}.zip + # The token goes in `with:`, not `env:`. This action's `token` input defaults to + # ${{ github.token }}, and its own docs say "a non-empty explicit token overrides + # GITHUB_TOKEN" - so the default is always non-empty and the env var was ignored + # entirely. It authenticated as the built-in token, whose contents permission is read-only + # here, and failed with 403 "Resource not accessible by integration" after both binaries + # had already been built. The v1.0.5 release published with no assets attached. - name: Upload Release Asset to GitHub Release uses: softprops/action-gh-release@v2 if: github.event_name == 'release' with: files: ${{ env.UPLOAD_PATH }} # Path to asset created in previous step name: OpenTagViewer MacOS AirTag Exporter ${{ env.APP_VERSION }} - env: - GITHUB_TOKEN: ${{ secrets.MACOS_EXPORTER_APP_GITHUB_TOKEN }} # Provided by GitHub Actions + token: ${{ secrets.MACOS_EXPORTER_APP_GITHUB_TOKEN }} build-intel: needs: test-release-version runs-on: macos-13 # Intel environment: 'MacOS Exporter App CI' + # The repository default is read-only, which is what turned a missing token into a 403 at + # the very last step. Granting it here means the upload still works if the PAT is ever + # unset or expires - the action treats an empty token as unset and falls back to this one. + permissions: + contents: write + # Only run this for 'macos-exporter-v' tags! if: | github.event_name == 'release' @@ -230,11 +247,16 @@ jobs: name: ${{ env.APP_NAME }}-${{ env.APP_VERSION }}-${{ runner.arch }}.zip path: ${{ github.workspace }}/output/${{ env.APP_NAME }}-${{ env.APP_VERSION }}-${{ runner.arch }}.zip + # The token goes in `with:`, not `env:`. This action's `token` input defaults to + # ${{ github.token }}, and its own docs say "a non-empty explicit token overrides + # GITHUB_TOKEN" - so the default is always non-empty and the env var was ignored + # entirely. It authenticated as the built-in token, whose contents permission is read-only + # here, and failed with 403 "Resource not accessible by integration" after both binaries + # had already been built. The v1.0.5 release published with no assets attached. - name: Upload Release Asset to GitHub Release uses: softprops/action-gh-release@v2 if: github.event_name == 'release' with: files: ${{ env.UPLOAD_PATH }} # Path to asset created in previous step name: OpenTagViewer MacOS AirTag Exporter ${{ env.APP_VERSION }} - env: - GITHUB_TOKEN: ${{ secrets.MACOS_EXPORTER_APP_GITHUB_TOKEN }} # Provided by GitHub Actions \ No newline at end of file + token: ${{ secrets.MACOS_EXPORTER_APP_GITHUB_TOKEN }} \ No newline at end of file