prepare release #1471
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 compiles its own sidecar from the tag's source; it needs only | |
| # the tag and the staged draft release, so publish-executor-package.yml | |
| # triggers it as soon as those exist. Manual repair: | |
| # gh workflow run publish-desktop.yml -f tag=vX.Y.Z |