From 9b5f0fa02a891df18adc2b72dacfdf287b8c38dc Mon Sep 17 00:00:00 2001 From: Jaissica Date: Mon, 15 Jun 2026 14:33:05 -0400 Subject: [PATCH 1/4] ci: use a GitHub App token to authenticate releases --- .github/workflows/release.yml | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 51dd999..8807941 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -76,21 +76,28 @@ jobs: id-token: write # Required for OIDC authentication with npm env: - GITHUB_TOKEN: ${{ secrets.MP_INTEGRATIONS_SEMANTIC_RELEASE_BOT }} GIT_AUTHOR_NAME: mparticle-automation GIT_AUTHOR_EMAIL: developers@mparticle.com GIT_COMMITTER_NAME: mparticle-automation GIT_COMMITTER_EMAIL: developers@mparticle.com - # npm auth: no trusted publisher is configured on npmjs for this package, - # so publish authenticates with the org token (provenance still attested via OIDC). + # npm auth: publish authenticates via OIDC trusted publishing; the token + # remains as a fallback (provenance is still attested via OIDC). NODE_AUTH_TOKEN: ${{ secrets.NPM_AUTH_TOKEN }} steps: + - name: Generate GitHub App token + id: app_token + uses: actions/create-github-app-token@v3 + with: + app-id: ${{ secrets.SDK_RELEASE_GITHUB_APP_ID }} + private-key: ${{ secrets.SDK_RELEASE_GITHUB_APP_PRIVATE_KEY }} + - name: Checkout public main branch uses: actions/checkout@v6 with: fetch-depth: 0 ref: main + token: ${{ steps.app_token.outputs.token }} - name: Import GPG Key uses: crazy-max/ghaction-import-gpg@v4 @@ -117,10 +124,14 @@ jobs: - name: Release --dry-run if: ${{ github.event.inputs.dryRun == 'true'}} + env: + GITHUB_TOKEN: ${{ steps.app_token.outputs.token }} run: | npx semantic-release --dry-run - name: Release if: ${{ github.event.inputs.dryRun == 'false'}} + env: + GITHUB_TOKEN: ${{ steps.app_token.outputs.token }} run: | npx semantic-release - name: Archive npm failure logs @@ -138,13 +149,22 @@ jobs: name: Sync repositories needs: release runs-on: ubuntu-latest + permissions: + contents: write steps: + - name: Generate GitHub App token + id: app_token + uses: actions/create-github-app-token@v3 + with: + app-id: ${{ secrets.SDK_RELEASE_GITHUB_APP_ID }} + private-key: ${{ secrets.SDK_RELEASE_GITHUB_APP_PRIVATE_KEY }} + - name: Checkout main branch uses: actions/checkout@v6 with: fetch-depth: 0 repository: ${{ github.repository }} - token: ${{ secrets.MP_INTEGRATIONS_SEMANTIC_RELEASE_BOT }} + token: ${{ steps.app_token.outputs.token }} ref: main - name: Merge release branch into main branch From 72c2945ea12ff5a074c0b5287e50b1ee58d14b39 Mon Sep 17 00:00:00 2001 From: Jaissica Date: Wed, 17 Jun 2026 13:28:45 -0400 Subject: [PATCH 2/4] ci: create GitHub release via ncipollo instead of the semantic-release plugin Replace @semantic-release/github with explicit GitHub Release creation. The release steps (resolve version, extract notes, create release) are appended to the existing sync-repository job so they reuse its App token and main checkout rather than duplicating them in a separate job. semantic-release still owns version determination, CHANGELOG, npm publish, and tagging; only the Release creation moves out into a SHA-pinned action. Because it runs after the branch sync, a Release-creation failure can no longer fail the release job or block npm publish, the tag, or the sync. Version is read from the bumped package.json; notes are extracted from CHANGELOG.md and the dist bundles are attached. Pattern adapted from the RoktUXHelper iOS "Release - Publish" workflow (ffurrer2/extract-release-notes + ncipollo/release-action). --- .github/workflows/release.yml | 29 +++++++++++++++++++++++++++++ release.config.js | 11 ----------- 2 files changed, 29 insertions(+), 11 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 8807941..7e2965b 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -180,3 +180,32 @@ jobs: if: ${{ github.event.inputs.dryRun == 'false' }} run: | git push --delete origin release/${{ github.run_number }} + + # GitHub Release creation lives at the end of this job so it reuses the App + # token and main checkout above, and so a failure here cannot fail npm publish, + # the tag, or the branch sync (all already done by the steps above). + - name: Resolve released version + id: version + if: ${{ github.event.inputs.dryRun == 'false' }} + run: echo "release-version=v$(node -p "require('./package.json').version")" >> "$GITHUB_OUTPUT" + + - name: Extract release notes from CHANGELOG + id: extract-release-notes + if: ${{ github.event.inputs.dryRun == 'false' }} + uses: ffurrer2/extract-release-notes@273da39a24fb7db106a35526c8162815faffd31d # v3.1.0 + with: + changelog_file: CHANGELOG.md + + - name: Create GitHub release + if: ${{ github.event.inputs.dryRun == 'false' }} + uses: ncipollo/release-action@339a81892b84b4eeb0f6e744e4574d79d0d9b8dd # v1.21.0 + with: + makeLatest: true + # The tag already exists (pushed by semantic-release); attach a Release to it. + allowUpdates: true + tag: ${{ steps.version.outputs.release-version }} + artifacts: 'dist/RoktPayPlus-Kit.common.js,dist/RoktPayPlus-Kit.esm.js,dist/RoktPayPlus-Kit.iife.js,dist/RoktPayPlus-Kit.d.ts' + token: ${{ steps.app_token.outputs.token }} + body: | + ## Release notes: + ${{ steps.extract-release-notes.outputs.release_notes }} diff --git a/release.config.js b/release.config.js index 7c4769a..2f23a89 100644 --- a/release.config.js +++ b/release.config.js @@ -46,17 +46,6 @@ module.exports = { publishCmd: 'npm publish', }, ], - [ - '@semantic-release/github', - { - assets: [ - 'dist/RoktPayPlus-Kit.common.js', - 'dist/RoktPayPlus-Kit.esm.js', - 'dist/RoktPayPlus-Kit.iife.js', - 'dist/RoktPayPlus-Kit.d.ts', - ], - }, - ], [ '@semantic-release/git', { From 41b8c21a5858826fb020c64d3db552954b8a7fd5 Mon Sep 17 00:00:00 2001 From: Jaissica Date: Wed, 17 Jun 2026 16:08:51 -0400 Subject: [PATCH 3/4] ci: use ncipollo auto-generated release notes Drop the ffurrer2/extract-release-notes step and let ncipollo generate the release notes via generateReleaseNotes. Simpler, and avoids the CHANGELOG format mismatch between semantic-release and the Keep-a-Changelog parser. --- .github/workflows/release.yml | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 7e2965b..fa84a7a 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -189,13 +189,6 @@ jobs: if: ${{ github.event.inputs.dryRun == 'false' }} run: echo "release-version=v$(node -p "require('./package.json').version")" >> "$GITHUB_OUTPUT" - - name: Extract release notes from CHANGELOG - id: extract-release-notes - if: ${{ github.event.inputs.dryRun == 'false' }} - uses: ffurrer2/extract-release-notes@273da39a24fb7db106a35526c8162815faffd31d # v3.1.0 - with: - changelog_file: CHANGELOG.md - - name: Create GitHub release if: ${{ github.event.inputs.dryRun == 'false' }} uses: ncipollo/release-action@339a81892b84b4eeb0f6e744e4574d79d0d9b8dd # v1.21.0 @@ -203,9 +196,8 @@ jobs: makeLatest: true # The tag already exists (pushed by semantic-release); attach a Release to it. allowUpdates: true + # Let GitHub auto-generate the release notes from merged PRs/commits. + generateReleaseNotes: true tag: ${{ steps.version.outputs.release-version }} artifacts: 'dist/RoktPayPlus-Kit.common.js,dist/RoktPayPlus-Kit.esm.js,dist/RoktPayPlus-Kit.iife.js,dist/RoktPayPlus-Kit.d.ts' token: ${{ steps.app_token.outputs.token }} - body: | - ## Release notes: - ${{ steps.extract-release-notes.outputs.release_notes }} From 22bf439e0fa3083a33b6844e9f8e361b741b0678 Mon Sep 17 00:00:00 2001 From: Jaissica Date: Wed, 17 Jun 2026 16:13:42 -0400 Subject: [PATCH 4/4] ci: trim release-step comments --- .github/workflows/release.yml | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index fa84a7a..5f4c491 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -181,9 +181,7 @@ jobs: run: | git push --delete origin release/${{ github.run_number }} - # GitHub Release creation lives at the end of this job so it reuses the App - # token and main checkout above, and so a failure here cannot fail npm publish, - # the tag, or the branch sync (all already done by the steps above). + # Runs last so a Release failure can't block npm publish, the tag, or the sync. - name: Resolve released version id: version if: ${{ github.event.inputs.dryRun == 'false' }} @@ -194,9 +192,7 @@ jobs: uses: ncipollo/release-action@339a81892b84b4eeb0f6e744e4574d79d0d9b8dd # v1.21.0 with: makeLatest: true - # The tag already exists (pushed by semantic-release); attach a Release to it. allowUpdates: true - # Let GitHub auto-generate the release notes from merged PRs/commits. generateReleaseNotes: true tag: ${{ steps.version.outputs.release-version }} artifacts: 'dist/RoktPayPlus-Kit.common.js,dist/RoktPayPlus-Kit.esm.js,dist/RoktPayPlus-Kit.iife.js,dist/RoktPayPlus-Kit.d.ts'