Repository navigation
Release #329
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Release | |
| # Three release paths funnel through this workflow so npm OIDC trusted publishing sees | |
| # a single workflow_ref: | |
| # 1. Standing-PR publish — standing-pr.yml detects the standing PR merge and dispatches | |
| # this workflow with standing_pr_number. | |
| # 2. Immediate release — under ci.releaseStrategy: standing-pr the gate only fires for | |
| # merges labelled release:immediate (CI-gated via workflow_run, as before). | |
| # 3. Manual scoped release — workflow_dispatch with scope/bump inputs. | |
| on: | |
| workflow_run: | |
| workflows: [CI] | |
| types: [completed] | |
| branches: [main] | |
| workflow_dispatch: | |
| inputs: | |
| scope: | |
| description: "Release scope (electron, tauri, dioxus, electrobun, react-native, flutter, native-mobile-core, utils, types, spy, core, cdp-bridge, shared)" | |
| required: true | |
| type: choice | |
| options: | |
| - shared | |
| - utils | |
| - types | |
| - spy | |
| - core | |
| - cdp-bridge | |
| - native-mobile-core | |
| - electron | |
| - tauri | |
| - dioxus | |
| - electrobun | |
| - react-native | |
| - flutter | |
| default: shared | |
| bump: | |
| description: "Version increment" | |
| required: true | |
| type: choice | |
| options: | |
| - patch | |
| - minor | |
| - major | |
| - prerelease | |
| default: patch | |
| release_type: | |
| description: "Release type" | |
| required: true | |
| type: choice | |
| options: | |
| - stable | |
| - prerelease | |
| default: stable | |
| target_branch: | |
| description: "Branch to release from (default: main)" | |
| required: false | |
| type: string | |
| default: main | |
| dry_run: | |
| description: "Dry run (show what would happen without publishing)" | |
| required: false | |
| type: boolean | |
| default: false | |
| standing_pr_number: | |
| description: "PR number of a merged standing release PR. When set, runs the manifest-driven publish path and ignores scope/bump. Set by standing-pr.yml; manual callers should leave blank." | |
| required: false | |
| type: string | |
| default: '' | |
| reconcile_after: | |
| description: "Rebuild the standing release PR after this release completes. Manual callers may enable it so the standing PR drops the just-released changes." | |
| required: false | |
| type: boolean | |
| default: false | |
| concurrency: | |
| group: release | |
| cancel-in-progress: false | |
| permissions: | |
| contents: read | |
| actions: read | |
| id-token: write | |
| pull-requests: write | |
| jobs: | |
| # Under ci.releaseStrategy: standing-pr the gate is the immediate-release evaluator: | |
| # it only fires for merges carrying release:immediate — everything else accumulates | |
| # into the standing release PR maintained by standing-pr.yml. | |
| gate: | |
| name: Gate | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| actions: read | |
| pull-requests: write | |
| if: github.event_name == 'workflow_run' && github.event.workflow_run.conclusion == 'success' && github.event.workflow_run.event == 'push' | |
| outputs: | |
| should_release: ${{ steps.gate.outputs.should-release }} | |
| bump: ${{ steps.gate.outputs.bump }} | |
| scope: ${{ steps.gate.outputs.gate-scope }} | |
| stable: ${{ steps.gate.outputs.gate-stable }} | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v6 | |
| with: | |
| fetch-depth: 0 | |
| - name: Run ReleaseKit Gate | |
| id: gate | |
| uses: goosewobbler/releasekit@v0.30.2 | |
| with: | |
| mode: gate | |
| node-version: '24' | |
| project-dir: . | |
| branch: main | |
| json: "true" | |
| summary: "true" | |
| skip-checkout: 'true' | |
| env: | |
| GITHUB_TOKEN: ${{ github.token }} | |
| release-auto: | |
| name: Release (Immediate) | |
| needs: [gate] | |
| if: github.event_name == 'workflow_run' && github.event.workflow_run.conclusion == 'success' && github.event.workflow_run.event == 'push' && needs.gate.outputs.should_release == 'true' | |
| uses: ./.github/workflows/_release.reusable.yml | |
| permissions: | |
| contents: write | |
| id-token: write | |
| pull-requests: write | |
| with: | |
| target_branch: main | |
| bump: ${{ needs.gate.outputs.bump }} | |
| release_type: ${{ needs.gate.outputs.stable == 'true' && 'stable' || 'prerelease' }} | |
| dry_run: false | |
| scope: ${{ needs.gate.outputs.scope }} | |
| secrets: | |
| ssh_key: ${{ secrets.DEPLOY_KEY }} | |
| crates_io_token: ${{ secrets.CRATES_IO_TOKEN }} | |
| ollama_api_key: ${{ secrets.OLLAMA_API_KEY }} | |
| # An immediate release leaves the standing PR holding changes that overlap with what | |
| # was just published. Re-running standing-pr update reconciles: closes the standing PR | |
| # if nothing's left, otherwise rebuilds the release branch against the new HEAD. | |
| # reconcile=true bypasses the skip-pattern guard, which would otherwise noop on the | |
| # release commit at HEAD. | |
| reconcile-after-auto: | |
| name: Reconcile standing PR | |
| needs: [release-auto] | |
| if: needs.release-auto.result == 'success' | |
| uses: ./.github/workflows/_standing-pr-update.reusable.yml | |
| permissions: | |
| contents: write | |
| pull-requests: write | |
| with: | |
| reconcile: true | |
| secrets: | |
| ssh_key: ${{ secrets.DEPLOY_KEY }} | |
| ollama_api_key: ${{ secrets.OLLAMA_API_KEY }} | |
| release-manual: | |
| name: Release (Manual) | |
| if: github.event_name == 'workflow_dispatch' && inputs.standing_pr_number == '' | |
| uses: ./.github/workflows/_release.reusable.yml | |
| permissions: | |
| contents: write | |
| id-token: write | |
| pull-requests: write | |
| with: | |
| target_branch: ${{ inputs.target_branch }} | |
| bump: ${{ inputs.bump }} | |
| release_type: ${{ inputs.release_type }} | |
| dry_run: ${{ inputs.dry_run }} | |
| scope: ${{ inputs.scope }} | |
| secrets: | |
| ssh_key: ${{ secrets.DEPLOY_KEY }} | |
| crates_io_token: ${{ secrets.CRATES_IO_TOKEN }} | |
| ollama_api_key: ${{ secrets.OLLAMA_API_KEY }} | |
| reconcile-after-manual: | |
| name: Reconcile standing PR | |
| needs: [release-manual] | |
| if: github.event_name == 'workflow_dispatch' && inputs.reconcile_after && !inputs.dry_run && needs.release-manual.result == 'success' | |
| uses: ./.github/workflows/_standing-pr-update.reusable.yml | |
| permissions: | |
| contents: write | |
| pull-requests: write | |
| with: | |
| reconcile: true | |
| secrets: | |
| ssh_key: ${{ secrets.DEPLOY_KEY }} | |
| ollama_api_key: ${{ secrets.OLLAMA_API_KEY }} | |
| # Standing-PR publish path. Dispatched by standing-pr.yml via `gh workflow run` so the | |
| # OIDC token's workflow_ref claim is release.yml — the trusted-publisher entry on | |
| # npmjs.com is keyed off the top-level workflow filename, and only one is allowed per | |
| # package, so all OIDC publishes have to funnel through here. | |
| release-standing-pr: | |
| name: Release from Standing PR | |
| if: github.event_name == 'workflow_dispatch' && inputs.standing_pr_number != '' | |
| uses: ./.github/workflows/_release.reusable.yml | |
| permissions: | |
| contents: write | |
| id-token: write | |
| # standing-pr-publish reads the manifest comment from the merged PR and posts a | |
| # completion comment back — without this every PR API call 403s. | |
| pull-requests: write | |
| with: | |
| target_branch: main | |
| # bump/release_type are required inputs of the reusable but unused on the | |
| # standing-pr publish path — versions come from the merged PR's manifest. | |
| bump: patch | |
| release_type: stable | |
| dry_run: false | |
| scope: all | |
| standing_pr_number: ${{ inputs.standing_pr_number }} | |
| secrets: | |
| ssh_key: ${{ secrets.DEPLOY_KEY }} | |
| crates_io_token: ${{ secrets.CRATES_IO_TOKEN }} | |
| ollama_api_key: ${{ secrets.OLLAMA_API_KEY }} |