Merge pull request #1562 from qawolf/mateus/run-create-chat-session-id #155
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 | |
| on: | |
| push: | |
| branches: [main] | |
| jobs: | |
| # GitHub applies environment protection when a job starts, not when a step | |
| # runs, so a gated job can only be avoided by never creating it. | |
| mode: | |
| name: Detect release mode | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| outputs: | |
| has_changesets: ${{ steps.detect.outputs.has_changesets }} | |
| needs_publish: ${{ steps.detect.outputs.needs_publish }} | |
| steps: | |
| - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 | |
| with: | |
| fetch-depth: 2 # HEAD^ for the version-bump comparison | |
| persist-credentials: false | |
| - name: Detect pending changesets and unpublished version | |
| id: detect | |
| run: | | |
| shopt -s nullglob | |
| has_changesets=false | |
| for f in .changeset/*.md; do | |
| if [[ "$(basename "$f")" != "README.md" ]]; then | |
| has_changesets=true | |
| break | |
| fi | |
| done | |
| # Publish only when this push bumped the version and that version has | |
| # no tag yet. The bump check stops a merge that lands while a publish | |
| # waits for approval from raising a second prompt. The tag check stops | |
| # a re-run after a successful publish from publishing twice. An | |
| # unreadable parent leaves the tag check to decide. The repo is | |
| # public, so the anonymous ls-remote needs no token. | |
| version=$(jq -r .version package.json) | |
| previous=$(git show HEAD^:package.json 2>/dev/null | jq -r .version || true) | |
| needs_publish=false | |
| if [[ "$has_changesets" == "false" && "$version" != "$previous" ]]; then | |
| if [[ -z "$(git ls-remote --tags origin "refs/tags/v${version}")" ]]; then | |
| needs_publish=true | |
| fi | |
| fi | |
| echo "has_changesets=$has_changesets" >> "$GITHUB_OUTPUT" | |
| echo "needs_publish=$needs_publish" >> "$GITHUB_OUTPUT" | |
| echo "has_changesets=\`$has_changesets\` needs_publish=\`$needs_publish\`" >> "$GITHUB_STEP_SUMMARY" | |
| version: | |
| name: Version PR | |
| needs: mode | |
| if: needs.mode.outputs.has_changesets == 'true' | |
| # The qa-wolf-ops credentials are environment secrets. This environment | |
| # holds a copy with no reviewers, so the job reads them without a prompt. | |
| environment: release-version | |
| runs-on: ubuntu-latest | |
| # Two version runs would race on force-pushing changeset-release/main. | |
| concurrency: | |
| group: release-version-${{ github.ref }} | |
| cancel-in-progress: false | |
| permissions: | |
| contents: write | |
| pull-requests: write | |
| steps: | |
| - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 | |
| with: | |
| fetch-depth: 0 | |
| - uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2 | |
| with: | |
| bun-version-file: package.json | |
| # No build: version-packages only runs `changeset version` and oxfmt. | |
| - run: bun install --frozen-lockfile | |
| # GITHUB_TOKEN can't create PRs under org policy, and PRs it opens don't | |
| # trigger CI; the App token does both. | |
| - name: Generate qa-wolf-ops token | |
| id: app-token | |
| uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0 | |
| with: | |
| client-id: ${{ secrets.QA_WOLF_OPS_CLIENT_ID }} | |
| private-key: ${{ secrets.QA_WOLF_OPS_PRIVATE_KEY }} | |
| permission-contents: write | |
| permission-pull-requests: write | |
| - name: Create or update Version Packages PR | |
| uses: changesets/action@63a615b9cd06ba9a3e6d13796c7fbcb080a60a0b # v1.8.0 | |
| with: | |
| version: bun run version-packages | |
| env: | |
| GITHUB_TOKEN: ${{ steps.app-token.outputs.token }} | |
| publish: | |
| name: Publish | |
| needs: mode | |
| if: needs.mode.outputs.needs_publish == 'true' | |
| environment: release | |
| runs-on: ubuntu-latest | |
| # Two publish runs would race on pushing the same tag. | |
| concurrency: | |
| group: release-publish-${{ github.ref }} | |
| cancel-in-progress: false | |
| permissions: | |
| contents: write | |
| id-token: write # OIDC for npm provenance | |
| outputs: | |
| published: ${{ steps.changesets.outputs.published }} | |
| tag: ${{ steps.tag.outputs.tag }} | |
| slack_ts: ${{ steps.slack.outputs.ts }} | |
| steps: | |
| - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 | |
| with: | |
| fetch-depth: 0 | |
| - uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2 | |
| with: | |
| bun-version-file: package.json | |
| - run: bun install --frozen-lockfile | |
| - run: bun run build | |
| # The App token creates the GitHub Release, so release-binaries picks it | |
| # up: a release created by GITHUB_TOKEN triggers no workflow. | |
| - name: Generate qa-wolf-ops token | |
| id: app-token | |
| uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0 | |
| with: | |
| client-id: ${{ secrets.QA_WOLF_OPS_CLIENT_ID }} | |
| private-key: ${{ secrets.QA_WOLF_OPS_PRIVATE_KEY }} | |
| permission-contents: write | |
| - name: Publish to npm | |
| id: changesets | |
| uses: changesets/action@63a615b9cd06ba9a3e6d13796c7fbcb080a60a0b # v1.8.0 | |
| with: | |
| publish: bunx changeset publish | |
| env: | |
| GITHUB_TOKEN: ${{ steps.app-token.outputs.token }} | |
| NPM_TOKEN: ${{ secrets.NPM_TOKEN }} | |
| NPM_CONFIG_PROVENANCE: true | |
| - name: Resolve release tag | |
| id: tag | |
| if: steps.changesets.outputs.published == 'true' | |
| env: | |
| PUBLISHED_PACKAGES: ${{ steps.changesets.outputs.publishedPackages }} | |
| run: | | |
| VERSION=$(echo "$PUBLISHED_PACKAGES" | bun -e "const d = await Bun.stdin.text(); console.log(JSON.parse(d)[0].version)") | |
| echo "tag=v${VERSION}" >> "$GITHUB_OUTPUT" | |
| # continue-on-error: a Slack outage must never fail a release | |
| - name: Notify Slack of release | |
| id: slack | |
| if: steps.changesets.outputs.published == 'true' | |
| continue-on-error: true | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }} | |
| SLACK_CHANNEL_ID: ${{ secrets.SLACK_RELEASE_CHANNEL_ID }} | |
| RELEASE_TAG: ${{ steps.tag.outputs.tag }} | |
| run: | | |
| payload=$(gh release view "$RELEASE_TAG" --json body,url,tagName \ | |
| | bun scripts/slackReleaseMessage.ts --phase publish --channel "$SLACK_CHANNEL_ID") | |
| response=$(curl -sf --max-time 30 -X POST https://slack.com/api/chat.postMessage \ | |
| -H "Authorization: Bearer $SLACK_BOT_TOKEN" \ | |
| -H "Content-Type: application/json; charset=utf-8" \ | |
| --data "$payload") | |
| printf '%s' "$response" | jq -e '.ok' > /dev/null | |
| echo "ts=$(printf '%s' "$response" | jq -r '.ts')" >> "$GITHUB_OUTPUT" | |
| binaries: | |
| name: Binaries | |
| needs: publish | |
| if: needs.publish.outputs.published == 'true' | |
| permissions: | |
| contents: write | |
| uses: ./.github/workflows/release-binaries.yml | |
| with: | |
| tag: ${{ needs.publish.outputs.tag }} | |
| # A sibling of binaries rather than a step in publish: a registry failure must | |
| # not skip the binary build, and changeset publish only knows one registry. | |
| github-packages: | |
| name: GitHub Packages | |
| needs: publish | |
| if: needs.publish.outputs.published == 'true' | |
| permissions: | |
| contents: read | |
| packages: write | |
| uses: ./.github/workflows/publish-github-packages.yml | |
| with: | |
| tag: ${{ needs.publish.outputs.tag }} | |
| notify-binaries: | |
| name: Notify Slack of binaries | |
| needs: [publish, binaries] | |
| # always(): the binaries matrix runs with fail-fast off, so report partial | |
| # failures too. Skips when nothing was published or the publish-time Slack | |
| # message did not post (no ts to update). | |
| if: always() && needs.publish.outputs.published == 'true' && needs.publish.outputs.slack_ts != '' | |
| environment: release-notify | |
| runs-on: ubuntu-latest | |
| concurrency: | |
| group: release-notify-${{ needs.publish.outputs.tag }} | |
| cancel-in-progress: false | |
| permissions: | |
| contents: read | |
| steps: | |
| - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 | |
| with: | |
| persist-credentials: false | |
| - uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2 | |
| with: | |
| bun-version-file: package.json | |
| # The release assets are the ground truth for which binaries built: a | |
| # target only has an asset after its build, smoke test, and upload all | |
| # succeeded. No bun install — the script is dependency-free. | |
| - name: Update release message with binary status | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }} | |
| SLACK_CHANNEL_ID: ${{ secrets.SLACK_RELEASE_CHANNEL_ID }} | |
| RELEASE_TAG: ${{ needs.publish.outputs.tag }} | |
| SLACK_TS: ${{ needs.publish.outputs.slack_ts }} | |
| run: | | |
| payload=$(gh release view "$RELEASE_TAG" --json body,url,tagName,assets \ | |
| | bun scripts/slackReleaseMessage.ts --phase binaries --channel "$SLACK_CHANNEL_ID" --ts "$SLACK_TS") | |
| curl -sf --max-time 30 -X POST https://slack.com/api/chat.update \ | |
| -H "Authorization: Bearer $SLACK_BOT_TOKEN" \ | |
| -H "Content-Type: application/json; charset=utf-8" \ | |
| --data "$payload" | jq -e '.ok' > /dev/null |