From 592224146161efdb914531b07cbbe9ea29022134 Mon Sep 17 00:00:00 2001 From: Feanil Patel Date: Tue, 25 Aug 2026 10:44:26 -0400 Subject: [PATCH 1/2] build: attach release assets before publishing the release The openedx org now has immutable releases enabled, which freezes a release's assets at the moment the release is published. Our flow created and published the release with python-semantic-release and then uploaded the distributions in a separate step, so those uploads now fail with "HTTP 422: Cannot upload assets to an immutable release". Instead, let python-semantic-release tag, push and build (vcs_release: false) and create the release ourselves with `gh release create`, which creates the release as a draft, uploads the assets, and only then publishes it. Its generated release notes are reused via the release_notes output, so the release body is unchanged. This has been broken since v3.6.1 but stayed silent until now, because python-semantic-release swallowed asset upload errors before v10.6.0. v3.6.1, v3.7.0 and v3.7.1 all published with no release assets, and they are immutable now, so they cannot be backfilled. Immutable releases: https://docs.github.com/en/code-security/supply-chain-security/understanding-your-software-supply-chain/immutable-releases Silent upload failures: https://github.com/python-semantic-release/python-semantic-release/issues/1395 Failing run: https://github.com/openedx/sample-plugin/actions/runs/32858608339/job/97836889093 Co-Authored-By: Claude Opus 5 (1M context) --- .github/workflows/release.yml | 34 ++++++++++++++++++++++++++-------- 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 88a38f7..50bb381 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -40,19 +40,37 @@ jobs: # Adjust tag with desired version if applicable. uses: python-semantic-release/python-semantic-release@39dd2052f2ce8282a5d932c31d58a2ca06d2550e # v10.6.1 with: - github_token: ${{ secrets.OPENEDX_SEMANTIC_RELEASE_GITHUB_TOKEN }} + github_token: ${{ secrets.GITHUB_TOKEN }} git_committer_name: "github-actions" git_committer_email: "actions@users.noreply.github.com" changelog: "false" directory: './backend-plugin-sample' - - - name: Publish | Upload to GitHub Release Assets - uses: python-semantic-release/publish-action@5a5718ce47b892ef699f2972dae122297771d641 # v10.6.1 + # Commit, tag, push and build, but don't create the GitHub release. + # We create it ourselves in the next step so that the distributions + # are attached before the release is published. See that step for why. + vcs_release: "false" + + # This repo has immutable releases enabled, which freezes a release's + # assets the moment it is published, so assets cannot be attached + # afterwards. `gh release create` handles this by creating the release as + # a draft, uploading the assets, and only then publishing it: + # https://docs.github.com/en/code-security/supply-chain-security/understanding-your-software-supply-chain/immutable-releases + - name: Publish | Create GitHub Release with Assets if: steps.release.outputs.released == 'true' - with: - github_token: ${{ secrets.OPENEDX_SEMANTIC_RELEASE_GITHUB_TOKEN }} - tag: ${{ steps.release.outputs.tag }} - directory: './backend-plugin-sample' + env: + GH_TOKEN: ${{ secrets.OPENEDX_SEMANTIC_RELEASE_GITHUB_TOKEN }} + # Reuse the release notes python-semantic-release generated for us. + RELEASE_NOTES: ${{ steps.release.outputs.release_notes }} + TAG: ${{ steps.release.outputs.tag }} + run: | + # Output the release notes to a file + printf '%s' "$RELEASE_NOTES" > "$RUNNER_TEMP/release_notes.md" + # Create a draft release + gh release create "$TAG" \ + --verify-tag \ + --title "$TAG" \ + --notes-file "$RUNNER_TEMP/release_notes.md" \ + backend-plugin-sample/dist/* - name: Upload | Backend Distribution Artifacts uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 From 2bb4364989f87e6d3b8e04ad7e5c4659ce267178 Mon Sep 17 00:00:00 2001 From: Feanil Patel Date: Tue, 25 Aug 2026 10:44:43 -0400 Subject: [PATCH 2/2] build: use the default GITHUB_TOKEN for releases OPENEDX_SEMANTIC_RELEASE_GITHUB_TOKEN was introduced in bed319c so that python-semantic-release could push the changelog commit past the branch protection rules on main. 53c8f3f then turned the changelog off, so python-semantic-release only pushes a tag now ("No local changes to add to any commit") and never writes to the protected branch. Tag creation and release creation are both covered by the `contents: write` permission this job already grants, and the repo has no tag protection rules or rulesets that the default token would need to bypass. That drops our reliance on a shared org-level PAT. Co-Authored-By: Claude Opus 5 (1M context) --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 50bb381..8ee9ff4 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -58,7 +58,7 @@ jobs: - name: Publish | Create GitHub Release with Assets if: steps.release.outputs.released == 'true' env: - GH_TOKEN: ${{ secrets.OPENEDX_SEMANTIC_RELEASE_GITHUB_TOKEN }} + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Reuse the release notes python-semantic-release generated for us. RELEASE_NOTES: ${{ steps.release.outputs.release_notes }} TAG: ${{ steps.release.outputs.tag }}