diff --git a/.github/workflows/release-rc.yml b/.github/workflows/release-rc.yml index 99b602743..c6893e333 100644 --- a/.github/workflows/release-rc.yml +++ b/.github/workflows/release-rc.yml @@ -9,7 +9,10 @@ on: default: false type: boolean schedule: - - cron: '7,17,27 3,15 * * *' + # Why: GitHub scheduled workflows are not guaranteed to start exactly on + # time and can be delayed or dropped around high-load periods. We retry + # across the full target hour and dedupe per PT slot. + - cron: '*/5 3,15 * * *' timezone: 'America/Los_Angeles' permissions: @@ -23,6 +26,9 @@ jobs: create-rc-tag: runs-on: ubuntu-latest timeout-minutes: 15 + outputs: + tag: ${{ steps.version.outputs.tag }} + should_release: ${{ steps.existing.outputs.already_ran != 'true' && !(github.event_name == 'workflow_dispatch' && inputs.dry_run) }} steps: - name: Checkout @@ -92,9 +98,23 @@ jobs: echo "Reason: ${{ steps.existing.outputs.reason }}" - name: Create and push RC tag + id: version if: steps.existing.outputs.already_ran != 'true' && !(github.event_name == 'workflow_dispatch' && inputs.dry_run) env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | - npm version prerelease --preid=rc -m "release: %s [rc-slot:${{ steps.slot.outputs.value }}]" + # Why: pushes made with GITHUB_TOKEN do not reliably trigger other + # workflows via push events. The RC workflow invokes release.yml + # directly after creating the tag, so the actual Electron release + # runs inside this scheduled flow instead of depending on push. + new_tag="$(npm version prerelease --preid=rc -m "release: %s [rc-slot:${{ steps.slot.outputs.value }}]")" git push origin main --follow-tags + echo "tag=$new_tag" >>"$GITHUB_OUTPUT" + + release-rc: + needs: create-rc-tag + if: needs.create-rc-tag.outputs.should_release == 'true' + uses: ./.github/workflows/release.yml + with: + tag: ${{ needs.create-rc-tag.outputs.tag }} + secrets: inherit diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 38854b887..6d010495b 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -4,23 +4,69 @@ on: push: tags: - 'v*' + workflow_call: + inputs: + tag: + description: Tag to release, for example v1.2.3-rc.0 + required: true + type: string + workflow_dispatch: + inputs: + tag: + description: Existing tag to release, for example v1.2.3-rc.0 + required: true + type: string jobs: + resolve-release: + runs-on: ubuntu-latest + outputs: + tag: ${{ steps.resolve.outputs.tag }} + ref: ${{ steps.resolve.outputs.ref }} + steps: + - name: Resolve release tag and ref + id: resolve + run: | + if [[ "${{ github.event_name }}" == "push" ]]; then + release_tag="${{ github.ref_name }}" + release_ref="${{ github.ref }}" + else + release_tag="${{ inputs.tag }}" + release_ref="refs/tags/${{ inputs.tag }}" + fi + + echo "tag=$release_tag" >>"$GITHUB_OUTPUT" + echo "ref=$release_ref" >>"$GITHUB_OUTPUT" + create-release: + needs: resolve-release runs-on: ubuntu-latest permissions: contents: write steps: - name: Checkout uses: actions/checkout@v4 + with: + ref: ${{ needs.resolve-release.outputs.ref }} - name: Create draft release with auto-generated notes - run: gh release create ${{ github.ref_name }} --draft --generate-notes --prerelease=${{ contains(github.ref_name, 'rc') }} + run: | + if gh release view "${{ needs.resolve-release.outputs.tag }}" --repo "${{ github.repository }}" >/dev/null 2>&1; then + echo "Release ${{ needs.resolve-release.outputs.tag }} already exists." + exit 0 + fi + + gh release create "${{ needs.resolve-release.outputs.tag }}" \ + --draft \ + --generate-notes \ + --prerelease=${{ contains(needs.resolve-release.outputs.tag, 'rc') }} env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} release: - needs: create-release + needs: + - resolve-release + - create-release strategy: fail-fast: false matrix: @@ -43,6 +89,8 @@ jobs: steps: - name: Checkout uses: actions/checkout@v4 + with: + ref: ${{ needs.resolve-release.outputs.ref }} - name: Setup Node.js uses: actions/setup-node@v4 @@ -95,12 +143,14 @@ jobs: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} publish-release: - needs: release + needs: + - resolve-release + - release runs-on: ubuntu-latest permissions: contents: write steps: - name: Publish release - run: gh release edit ${{ github.ref_name }} --draft=false --repo ${{ github.repository }} + run: gh release edit "${{ needs.resolve-release.outputs.tag }}" --draft=false --repo "${{ github.repository }}" env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}