Release #16
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: | |
| workflow_dispatch: | |
| inputs: | |
| version: | |
| description: Exact next release version without the v prefix | |
| required: true | |
| type: string | |
| increment: | |
| description: Select minor only with explicit user authorization; otherwise next patch | |
| required: true | |
| type: choice | |
| default: patch | |
| options: | |
| - patch | |
| - minor | |
| startup_receipt: | |
| description: JSON receipt from the exact approved static package's headed cold and warm-upgrade movie/menu/playable-frame gate | |
| required: false | |
| type: string | |
| package_run_id: | |
| description: Successful Prepare release package run on this exact main commit; download and test its artifact before releasing | |
| required: true | |
| type: string | |
| waive_v0012_startup_receipt: | |
| description: Explicitly authorized v0.0.12-only startup receipt waiver; asset and binding checks remain mandatory | |
| required: false | |
| type: boolean | |
| default: false | |
| permissions: | |
| contents: write | |
| actions: read | |
| concurrency: | |
| group: playsrc-production-release | |
| cancel-in-progress: false | |
| jobs: | |
| release: | |
| name: Deploy latest main | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 60 | |
| environment: production | |
| steps: | |
| - name: Check out latest main | |
| uses: actions/checkout@v6 | |
| with: | |
| ref: main | |
| fetch-depth: 0 | |
| - name: Set up Bun | |
| uses: oven-sh/setup-bun@v2 | |
| with: | |
| bun-version: canary | |
| - name: Resolve release identity | |
| id: release | |
| shell: bash | |
| env: | |
| VERSION: ${{ inputs.version }} | |
| INCREMENT: ${{ inputs.increment }} | |
| GH_TOKEN: ${{ github.token }} | |
| run: | | |
| set -euo pipefail | |
| latest="$(gh release view --json tagName --jq .tagName)" | |
| git ls-remote --tags --refs origin | sed 's|.*refs/tags/||' | bun tools/playsrc/src/release-version.ts "$VERSION" "${latest#v}" "$INCREMENT" | |
| tag="v${VERSION}" | |
| sha="$(git rev-parse HEAD)" | |
| remote_sha="$(git ls-remote origin refs/heads/main | cut -f1)" | |
| if [[ "$sha" != "$remote_sha" ]]; then | |
| echo "checked out commit is not latest main" >&2 | |
| exit 2 | |
| fi | |
| existing_tag="$(git ls-remote origin "refs/tags/${tag}" | cut -f1)" | |
| if [[ -n "$existing_tag" ]]; then | |
| echo "${tag} already exists" >&2 | |
| exit 2 | |
| fi | |
| if gh release view "$tag" >/dev/null 2>&1; then | |
| echo "${tag} already has a GitHub Release" >&2 | |
| exit 2 | |
| fi | |
| notes="apps/web/tf2/releases/notes/${tag}.md" | |
| if [[ ! -s "$notes" ]]; then | |
| echo "authored release notes are missing: ${notes}" >&2 | |
| exit 2 | |
| fi | |
| if [[ "$(head -n 1 "$notes")" != "# playsrc ${tag}" ]]; then | |
| echo "release notes must begin with # playsrc ${tag}" >&2 | |
| exit 2 | |
| fi | |
| echo "tag=${tag}" >> "$GITHUB_OUTPUT" | |
| echo "sha=${sha}" >> "$GITHUB_OUTPUT" | |
| echo "notes=${notes}" >> "$GITHUB_OUTPUT" | |
| - name: Set up Terraform | |
| uses: hashicorp/setup-terraform@v4.0.1 | |
| with: | |
| terraform_version: 1.15.8 | |
| terraform_wrapper: false | |
| - name: Install dependencies | |
| run: bun install --frozen-lockfile | |
| - name: Authenticate prepared artifact source | |
| env: | |
| PACKAGE_RUN_ID: ${{ inputs.package_run_id }} | |
| GH_TOKEN: ${{ github.token }} | |
| run: | | |
| set -euo pipefail | |
| [[ "$PACKAGE_RUN_ID" =~ ^[1-9][0-9]*$ ]] | |
| gh api "repos/${GITHUB_REPOSITORY}/actions/runs/${PACKAGE_RUN_ID}" | bun tools/playsrc/src/release-package-run.ts "$(git rev-parse HEAD)" "$GITHUB_REPOSITORY" | |
| - name: Download the exact tested package | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: tf2-release-package | |
| path: apps/web/tf2/dist/cloudflare | |
| run-id: ${{ inputs.package_run_id }} | |
| github-token: ${{ github.token }} | |
| - name: Verify accepted bytes before any production operation | |
| run: bun tools/playsrc/src/cli.ts verify release-package | |
| env: | |
| PLAYSRC_STATIC_STARTUP_RECEIPT: ${{ inputs.startup_receipt }} | |
| PLAYSRC_RELEASE_VERSION: ${{ inputs.version }} | |
| - name: Bootstrap Terraform state | |
| run: bun run infra:bootstrap | |
| env: | |
| CLOUDFLARE_ACCOUNT_ID: ${{ vars.CLOUDFLARE_ACCOUNT_ID }} | |
| CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }} | |
| - name: Deploy production | |
| run: bun run infra:deploy | |
| env: | |
| PLAYSRC_STATIC_STARTUP_RECEIPT: ${{ inputs.startup_receipt }} | |
| PLAYSRC_RELEASE_VERSION: ${{ inputs.version }} | |
| PLAYSRC_WAIVE_V0012_STARTUP_RECEIPT: ${{ inputs.waive_v0012_startup_receipt }} | |
| CLOUDFLARE_ACCOUNT_ID: ${{ vars.CLOUDFLARE_ACCOUNT_ID }} | |
| CLOUDFLARE_ZONE_ID: ${{ vars.CLOUDFLARE_ZONE_ID }} | |
| CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }} | |
| AWS_ACCESS_KEY_ID: ${{ secrets.CLOUDFLARE_R2_ACCESS_KEY_ID }} | |
| AWS_SECRET_ACCESS_KEY: ${{ secrets.CLOUDFLARE_R2_SECRET_ACCESS_KEY }} | |
| - name: Create tag | |
| if: success() | |
| shell: bash | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| TAG: ${{ steps.release.outputs.tag }} | |
| SHA: ${{ steps.release.outputs.sha }} | |
| run: | | |
| set -euo pipefail | |
| if ! git ls-remote --exit-code origin "refs/tags/${TAG}" >/dev/null 2>&1; then | |
| gh api "repos/${GITHUB_REPOSITORY}/git/refs" \ | |
| --method POST \ | |
| --field "ref=refs/tags/${TAG}" \ | |
| --field "sha=${SHA}" >/dev/null | |
| fi | |
| - name: Create GitHub Release | |
| if: success() | |
| shell: bash | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| TAG: ${{ steps.release.outputs.tag }} | |
| RELEASE_NOTES: ${{ steps.release.outputs.notes }} | |
| run: | | |
| set -euo pipefail | |
| gh release create "$TAG" \ | |
| "apps/web/tf2/dist/cloudflare/release.json#Cloudflare deployment manifest" \ | |
| --verify-tag \ | |
| --notes-file "$RELEASE_NOTES" \ | |
| --title "playsrc ${TAG}" |