prepare release #1413
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 | |
| run-name: prepare release | |
| on: | |
| push: | |
| branches: | |
| - main | |
| permissions: | |
| contents: read | |
| concurrency: | |
| group: release-${{ github.ref }} | |
| cancel-in-progress: false | |
| # CI is not a user. Without this, executor's own product telemetry reports to the | |
| # production PostHog project from every e2e shard: the analytics layer | |
| # (integration_added, execution_completed, artifact_*) and the | |
| # integrations-registry fetch, which lands as a `hit` event. Each shard is a | |
| # fresh container, so it mints a fresh anonymous id and arrives on a fresh | |
| # runner IP — inflating machine and user counts by roughly an order of | |
| # magnitude. Both opt-outs are the packages' documented CI/test hooks. | |
| env: | |
| DO_NOT_TRACK: "1" | |
| EXECUTOR_DISABLE_ANALYTICS: "1" | |
| EXECUTOR_DISABLE_INTEGRATIONS_FETCH: "1" | |
| jobs: | |
| release: | |
| runs-on: ubuntu-latest | |
| permissions: | |
| actions: write | |
| contents: write | |
| id-token: write | |
| pull-requests: write | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| persist-credentials: false | |
| - name: Setup Bun | |
| uses: oven-sh/setup-bun@v2 | |
| with: | |
| bun-version: 1.3.11 | |
| - name: Setup Node | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: 24 | |
| registry-url: https://registry.npmjs.org | |
| - name: Update npm for trusted publishing | |
| run: | | |
| # npm 12.0.0 fails `publish --provenance` with "Cannot find module | |
| # 'sigstore'" (npm/cli#9722); 11.x supports trusted publishing and works. | |
| npm install -g npm@11 | |
| npm --version | |
| - name: Install dependencies | |
| run: bun install --frozen-lockfile | |
| - name: Create or update release pull request | |
| id: changesets | |
| uses: changesets/action@v1 | |
| with: | |
| # @changesets/changelog-github occasionally receives truncated | |
| # GitHub GraphQL responses. The script retries only that transient | |
| # failure mode. It must be a script file: the action splits this | |
| # command itself rather than running it through a shell, so an | |
| # inline `bash -c '...'` one-liner gets mangled at the quotes. | |
| version: bash scripts/changeset-version-with-retry.sh | |
| commit: Version Packages | |
| title: Version Packages | |
| createGithubReleases: false | |
| env: | |
| # PAT (RELEASE_PAT) so the auto-opened Version Packages PR | |
| # triggers downstream workflows (pkg-pr-new, CI). PRs authored | |
| # by the default GITHUB_TOKEN do not trigger other workflows by | |
| # GitHub design. Falls back to GITHUB_TOKEN when the secret is | |
| # not set, so the workflow keeps working in forks / before the | |
| # secret is configured. | |
| GITHUB_TOKEN: ${{ secrets.RELEASE_PAT || secrets.GITHUB_TOKEN }} | |
| - name: Smoke test packed @executor-js library packages | |
| if: steps.changesets.outputs.hasChangesets == 'false' | |
| run: bun run release:smoke:packages | |
| - name: Publish @executor-js library packages | |
| if: steps.changesets.outputs.hasChangesets == 'false' | |
| run: bun run release:publish:packages | |
| - name: Detect release version change | |
| if: steps.changesets.outputs.hasChangesets == 'false' | |
| id: detect_release | |
| run: | | |
| before="${{ github.event.before }}" | |
| if [ "$before" = "0000000000000000000000000000000000000000" ]; then | |
| before="$(git rev-list --max-count=1 HEAD^ 2>/dev/null || true)" | |
| fi | |
| version="$(node -e "console.log(JSON.parse(require('fs').readFileSync('apps/cli/package.json', 'utf8')).version)")" | |
| if [ -n "$before" ] && git cat-file -e "$before:apps/cli/package.json" 2>/dev/null; then | |
| previous_version="$(git show "$before:apps/cli/package.json" | node -e "let data = ''; process.stdin.setEncoding('utf8'); process.stdin.on('data', (chunk) => { data += chunk; }); process.stdin.on('end', () => { console.log(JSON.parse(data).version ?? ''); });")" | |
| else | |
| previous_version="" | |
| fi | |
| release_tag="v$version" | |
| if [ -n "$previous_version" ] && [ "$previous_version" != "$version" ]; then | |
| echo "changed=true" >> "$GITHUB_OUTPUT" | |
| elif ! git ls-remote --exit-code --tags origin "refs/tags/$release_tag" >/dev/null 2>&1; then | |
| echo "changed=true" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "changed=false" >> "$GITHUB_OUTPUT" | |
| fi | |
| echo "version=$version" >> "$GITHUB_OUTPUT" | |
| - name: Validate release tag | |
| if: steps.changesets.outputs.hasChangesets == 'false' && steps.detect_release.outputs.changed == 'true' | |
| id: validate_release | |
| env: | |
| RELEASE_VERSION: ${{ steps.detect_release.outputs.version }} | |
| run: bun run scripts/validate-release-ref.ts --version-env RELEASE_VERSION --output tag | |
| - name: Create and push release tag | |
| if: steps.changesets.outputs.hasChangesets == 'false' && steps.detect_release.outputs.changed == 'true' | |
| env: | |
| GH_TOKEN: ${{ secrets.RELEASE_PAT || github.token }} | |
| RELEASE_TAG: ${{ steps.validate_release.outputs.tag }} | |
| run: | | |
| auth_remote="https://x-access-token:${GH_TOKEN}@github.com/${GITHUB_REPOSITORY}.git" | |
| if git ls-remote --exit-code --tags "$auth_remote" "refs/tags/$RELEASE_TAG" >/dev/null 2>&1; then | |
| echo "Tag $RELEASE_TAG already exists." | |
| exit 0 | |
| fi | |
| git config user.name "github-actions[bot]" | |
| git config user.email "41898282+github-actions[bot]@users.noreply.github.com" | |
| git tag "$RELEASE_TAG" | |
| git push "$auth_remote" "$RELEASE_TAG" | |
| # Publishing is intentionally tag-driven: pushing the validated v* tag | |
| # triggers publish-executor-package.yml. A second workflow_dispatch path | |
| # races a duplicate publish for the same release. | |
| # Desktop build downloads CLI binaries from the release, so it must | |
| # run after CLI publish completes. Trigger it from the CLI workflow | |
| # or manually via: gh workflow run publish-desktop.yml -f tag=vX.Y.Z |