orca/.github/workflows/release.yml

193 lines
6.5 KiB
YAML

name: Release
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: |
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 }}
# Why: E2E runs alongside the release for visibility (failures surface as a
# red check on the tag), but it is NOT in `release`'s needs list. Releases
# already take a while and the suite is already a required check on PRs, so
# gating here would mostly just delay shipping without adding much signal.
# Matches the pattern used by noqa's app deploy, which runs E2E with
# continue-on-error so failures are visible but don't block the deploy.
e2e:
needs: resolve-release
uses: ./.github/workflows/e2e.yml
with:
ref: ${{ needs.resolve-release.outputs.ref }}
release:
needs:
- resolve-release
- create-release
strategy:
fail-fast: false
matrix:
include:
- os: macos-15
platform: mac
release_command: ORCA_MAC_RELEASE=1 pnpm exec electron-builder --config config/electron-builder.config.cjs --mac --publish always
- os: windows-latest
platform: win
release_command: pnpm exec electron-builder --config config/electron-builder.config.cjs --win --publish always
- os: ubuntu-latest
platform: linux
release_command: pnpm exec electron-builder --config config/electron-builder.config.cjs --linux --publish always
runs-on: ${{ matrix.os }}
permissions:
contents: write
steps:
- name: Checkout
uses: actions/checkout@v4
with:
ref: ${{ needs.resolve-release.outputs.ref }}
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 24
- name: Setup pnpm
uses: pnpm/action-setup@v4
with:
run_install: false
# Why: pnpm install triggers electron's postinstall, which downloads the
# Electron binary from GitHub release assets. GitHub's download CDN
# occasionally returns 504s that fail the whole release. Retry on
# failure so transient network errors don't require a manual re-run.
- name: Install dependencies
uses: nick-fields/retry@v3
with:
timeout_minutes: 10
max_attempts: 3
retry_wait_seconds: 30
command: pnpm install --frozen-lockfile
- name: Verify macOS signing environment
if: matrix.platform == 'mac'
run: node config/scripts/verify-macos-release-env.mjs
env:
CSC_LINK: ${{ secrets.MAC_CERTS }}
CSC_KEY_PASSWORD: ${{ secrets.MAC_CERTS_PASSWORD }}
APPLE_ID: ${{ secrets.APPLE_ID }}
APPLE_APP_SPECIFIC_PASSWORD: ${{ secrets.APPLE_APP_SPECIFIC_PASSWORD }}
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
- name: Build app
run: pnpm build:release
# Why: macOS signing secrets (CSC_LINK, CSC_KEY_PASSWORD) must NOT be
# passed to non-macOS builds. electron-builder uses CSC_LINK as the
# code-signing certificate on any platform, so leaking the Apple
# Developer ID cert to the Windows build causes the NSIS installer to
# be signed with an Apple cert whose chain Windows cannot validate,
# breaking the auto-updater with "certificate chain could not be built
# to a trusted root authority" (issue #631).
#
# Why retry: electron-builder downloads NSIS/winCodeSign/squirrel
# binaries and the Electron runtime from GitHub release assets during
# publish. GitHub's download CDN occasionally returns 504s that fail
# the whole release. Retry on failure so transient network errors
# don't require a manual re-run.
- name: Publish release artifacts (macOS)
if: matrix.platform == 'mac'
uses: nick-fields/retry@v3
with:
timeout_minutes: 45
max_attempts: 3
retry_wait_seconds: 30
command: ${{ matrix.release_command }}
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
CSC_LINK: ${{ secrets.MAC_CERTS }}
CSC_KEY_PASSWORD: ${{ secrets.MAC_CERTS_PASSWORD }}
APPLE_ID: ${{ secrets.APPLE_ID }}
APPLE_APP_SPECIFIC_PASSWORD: ${{ secrets.APPLE_APP_SPECIFIC_PASSWORD }}
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
- name: Publish release artifacts
if: matrix.platform != 'mac'
uses: nick-fields/retry@v3
with:
timeout_minutes: 30
max_attempts: 3
retry_wait_seconds: 30
command: ${{ matrix.release_command }}
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
publish-release:
needs:
- resolve-release
- release
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- name: Publish release
run: gh release edit "${{ needs.resolve-release.outputs.tag }}" --draft=false --repo "${{ github.repository }}"
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}