fix infra build in publish.yml
#1534
Workflow file for this run
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: "publish" | |
| # Three trigger flows: | |
| # | |
| # push to main — Full release flow: process changesets, publish docs, | |
| # and (when a version-bump PR just merged) prepare, | |
| # review, and publish to npm/crates.io/GitHub Releases. | |
| # Requires manual approval via the slang-release environment. | |
| # | |
| # workflow_dispatch — Replays the push-to-main path (e.g. to retry a | |
| # flaky publish). Requires manual approval. | |
| # | |
| # pull_request — Prepare and review only: builds the npm tarball | |
| # that would be published and validates it, but | |
| # skips the actual upload. No approval needed. | |
| # | |
| # Job topology — split into prepare → review → publish to enforce that the bytes | |
| # reviewed are the bytes uploaded: | |
| # | |
| # Trigger repo-check changesets prepare review notify-deploy publish | |
| # ─────────────── ────────── ──────────────── ───────── ───────── ───────────── ─────── | |
| # PR ✓ gate ⊘ skip (no push) ✓ build ✓ validate ⊘ skip ⊘ skip | |
| # push (pending) ✓ gate ✓ has changesets ✓ build ✓ validate ⊘ skip ⊘ skip | |
| # push (no-op) ✓ gate ✓ no new version ✓ build ✓ validate ⊘ skip ⊘ skip | |
| # push (release) ✓ gate ✓ new version ✓ build ✓ validate ✓ notify ✓ publish | |
| # | |
| # Every job has an explicit 'if' condition — no job relies on implicit skip | |
| # propagation from needs. The one exception is prepare, which uses !cancelled() | |
| # to override skip propagation from the changesets job (skipped on PRs). | |
| on: | |
| # Run using manual triggers from GitHub UI: | |
| # https://docs.github.com/en/actions/managing-workflow-runs/manually-running-a-workflow | |
| workflow_dispatch: {} | |
| # Run on pushes to 'main' branch: | |
| push: | |
| branches: | |
| - "main" | |
| # Run on PRs for build and validation: | |
| pull_request: {} | |
| permissions: {} | |
| # Serialize runs for the same PR or branch. Different PRs/branches can run concurrently. | |
| concurrency: | |
| group: "${{ github.workflow }}-${{ github.event_name == 'pull_request' && github.event.pull_request.number || github.ref_name }}" | |
| cancel-in-progress: false | |
| jobs: | |
| # ─────────────────────────────────────────────── | |
| # Gate: only run on the main repo (not forks). | |
| # ─────────────────────────────────────────────── | |
| repo-check: | |
| if: >- | |
| (github.event_name == 'pull_request' | |
| && github.event.pull_request.head.repo.full_name == github.repository) | |
| || github.ref_name == 'main' | |
| runs-on: "ubuntu-24.04" # _SLANG_DEV_CONTAINER_BASE_IMAGE_ (keep in sync) | |
| steps: | |
| - run: "true" | |
| # ─────────────────────────────────────────────── | |
| # Changesets: process version bumps and publish docs | |
| # Runs on push to main and dispatch (not PRs) | |
| # ─────────────────────────────────────────────── | |
| changesets: | |
| needs: | |
| - "repo-check" | |
| if: >- | |
| github.event_name == 'push' | |
| || github.event_name == 'workflow_dispatch' | |
| runs-on: "ubuntu-24.04" # _SLANG_DEV_CONTAINER_BASE_IMAGE_ (keep in sync) | |
| permissions: | |
| contents: "write" # to create new branches | |
| pull-requests: "write" # to create new pull requests for changesets | |
| outputs: | |
| hasChangesets: "${{ steps.runChangesets.outputs.hasChangesets }}" | |
| publishNeeded: "${{ steps.checkVersion.outputs.publishNeeded || 'false' }}" | |
| steps: | |
| - name: "Checkout Repository" | |
| uses: "actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd" # v6.0.2 | |
| with: | |
| persist-credentials: false | |
| fetch-depth: 0 # Full history is needed by 'git/restore-mtime' to find each file's last commit time. | |
| - name: "Free up disk space" | |
| uses: "./.github/actions/free-disk-space" | |
| - name: "Restore file mtimes from git" | |
| uses: "./.github/actions/git/restore-mtime" | |
| - name: "Restore Dependencies Cache" | |
| uses: "./.github/actions/cache/dependencies/restore" | |
| - name: "Restore Cargo Target Cache" | |
| uses: "./.github/actions/cache/cargo-target/restore" | |
| - name: "infra setup" | |
| run: "./scripts/bin/infra setup" | |
| # Consume the changesets, and create a git stash, to be popped by the next step: | |
| - name: "infra publish changesets" | |
| run: "./scripts/bin/infra publish changesets" | |
| env: | |
| GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" | |
| - name: "Create/Update Changesets Pull Request" | |
| id: "runChangesets" | |
| uses: "changesets/action@63a615b9cd06ba9a3e6d13796c7fbcb080a60a0b" # v1.8.0 | |
| with: | |
| title: "Bump Slang Version" | |
| commit: "Bump Slang Version" | |
| createGithubReleases: false | |
| version: "git stash pop" # Stash created by 'infra publish changesets' | |
| env: | |
| GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" | |
| - name: "Check if publish needed" | |
| id: "checkVersion" | |
| if: "${{ steps.runChangesets.outputs.hasChangesets == 'false' }}" | |
| run: | | |
| RESULT="$(./scripts/bin/infra publish github-release --check-only)" | |
| echo "publishNeeded=${RESULT}" >> "$GITHUB_OUTPUT" | |
| env: | |
| GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" | |
| - name: "infra publish mkdocs --target main-branch" | |
| run: "./scripts/bin/infra publish mkdocs --target main-branch" | |
| env: | |
| GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" | |
| - name: "infra publish mkdocs --target latest-release" | |
| if: "${{ steps.runChangesets.outputs.hasChangesets == 'false' }}" | |
| run: "./scripts/bin/infra publish mkdocs --target latest-release" | |
| env: | |
| GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" | |
| # ─────────────────────────────────────────────── | |
| # Prepare: build the npm tarball for downstream review and publish. | |
| # ─────────────────────────────────────────────── | |
| prepare: | |
| needs: | |
| - "repo-check" | |
| - "changesets" | |
| # !cancelled() overrides GitHub's default skip-propagation (needed because | |
| # changesets is skipped on PRs). It also overrides failure-propagation, | |
| # so repo-check and changesets must be re-asserted explicitly. | |
| if: >- | |
| !cancelled() | |
| && needs.repo-check.result == 'success' | |
| && (needs.changesets.result == 'success' || needs.changesets.result == 'skipped') | |
| runs-on: "ubuntu-24.04" # _SLANG_DEV_CONTAINER_BASE_IMAGE_ (keep in sync) | |
| permissions: | |
| contents: "read" | |
| outputs: | |
| artifact-name: "${{ steps.prepare.outputs.artifact-name }}" | |
| tarball-name: "${{ steps.prepare.outputs.tarball-name }}" | |
| steps: | |
| - name: "Checkout Repository" | |
| uses: "actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd" # v6.0.2 | |
| with: | |
| persist-credentials: false | |
| fetch-depth: 0 # Full history is needed by 'git/restore-mtime' to find each file's last commit time. | |
| - name: "Free up disk space" | |
| uses: "./.github/actions/free-disk-space" | |
| # Skip cache + mtime restore on a real release so the published artifact | |
| # comes from a clean build with no side inputs. | |
| - name: "Restore file mtimes from git" | |
| if: "${{ needs.changesets.outputs.publishNeeded != 'true' }}" | |
| uses: "./.github/actions/git/restore-mtime" | |
| - name: "Restore Dependencies Cache" | |
| if: "${{ needs.changesets.outputs.publishNeeded != 'true' }}" | |
| uses: "./.github/actions/cache/dependencies/restore" | |
| - name: "Restore Cargo Target Cache" | |
| if: "${{ needs.changesets.outputs.publishNeeded != 'true' }}" | |
| uses: "./.github/actions/cache/cargo-target/restore" | |
| - name: "infra setup" | |
| run: "./scripts/bin/infra setup" | |
| - name: "Prepare publish artifacts" | |
| id: "prepare" | |
| uses: "./.github/actions/publish/prepare" | |
| - name: "infra publish mkdocs --dry-run" | |
| run: | | |
| git config user.name "github-actions[bot]" | |
| git config user.email "github-actions[bot]@users.noreply.github.com" | |
| ./scripts/bin/infra publish mkdocs --target main-branch --dry-run | |
| - name: "Upload publish artifacts" | |
| uses: "actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a" # v7.0.1 | |
| with: | |
| name: "${{ steps.prepare.outputs.artifact-name }}" | |
| path: "target/publish-artifacts/" | |
| if-no-files-found: "error" | |
| retention-days: 7 | |
| # ─────────────────────────────────────────────── | |
| # Review: download the prepared artifact and dry-run publish against what would be uploaded. | |
| # ─────────────────────────────────────────────── | |
| review: | |
| needs: | |
| - "repo-check" | |
| - "prepare" | |
| if: >- | |
| !cancelled() | |
| && needs.repo-check.result == 'success' | |
| && needs.prepare.result == 'success' | |
| runs-on: "ubuntu-24.04" # _SLANG_DEV_CONTAINER_BASE_IMAGE_ (keep in sync) | |
| permissions: | |
| contents: "read" | |
| steps: | |
| - name: "Checkout Repository" | |
| uses: "actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd" # v6.0.2 | |
| with: | |
| persist-credentials: false | |
| fetch-depth: 0 # Full history is needed by 'git/restore-mtime' to find each file's last commit time. | |
| - name: "Free up disk space" | |
| uses: "./.github/actions/free-disk-space" | |
| # Review only validates the prepared artifact; the publishable bytes come from | |
| # `prepare`, not from this job's `target/`. Cache restore here is purely a | |
| # speedup for `cargo publish --dry-run`'s verify-build and has no provenance impact. | |
| - name: "Restore file mtimes from git" | |
| uses: "./.github/actions/git/restore-mtime" | |
| - name: "Restore Dependencies Cache" | |
| uses: "./.github/actions/cache/dependencies/restore" | |
| - name: "Restore Cargo Target Cache" | |
| uses: "./.github/actions/cache/cargo-target/restore" | |
| - name: "infra setup" | |
| run: "./scripts/bin/infra setup" | |
| - name: "Download publish artifacts" | |
| uses: "actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c" # v8.0.1 | |
| with: | |
| name: "${{ needs.prepare.outputs.artifact-name }}" | |
| path: "target/publish-artifacts/" | |
| - name: "infra publish npm --dry-run" | |
| # No tarball means prepare packed nothing (version already on npm) — nothing to validate. | |
| if: "${{ needs.prepare.outputs.tarball-name != '' }}" | |
| run: "./scripts/bin/infra publish npm --dry-run --tarball target/publish-artifacts/${{ needs.prepare.outputs.tarball-name }}" | |
| - name: "infra publish cargo --dry-run" | |
| run: "./scripts/bin/infra publish cargo --dry-run" | |
| - name: "Publish review summary" | |
| run: | | |
| VERSION=$(grep '^version = ' Cargo.toml | head -1 | sed 's/version = "\(.*\)"/\1/') | |
| ARTIFACT_NAME='${{ needs.prepare.outputs.artifact-name }}' | |
| { | |
| echo "## Publish Review Summary" | |
| echo "" | |
| echo "**Version:** \`${VERSION}\`" | |
| echo "**Artifact:** \`${ARTIFACT_NAME}\` — download from the run's Artifacts panel to inspect." | |
| echo "" | |
| echo "### What was validated against the prepared artifact" | |
| echo "- \`pnpm publish --dry-run <tarball>\` (npm pack/structure check)" | |
| echo "- \`cargo publish --dry-run\` batched workspace verify-build (catches cross-crate path-dep rewrites)" | |
| if [ "${{ github.event_name }}" = "pull_request" ]; then | |
| echo "" | |
| echo "### Skipped (only on push/dispatch)" | |
| echo "- Actual npm/cargo publishing" | |
| echo "- GitHub release creation" | |
| fi | |
| } >> "$GITHUB_STEP_SUMMARY" | |
| # ─────────────────────────────────────────────── | |
| # Notify: Slack notification that review is requested | |
| # ─────────────────────────────────────────────── | |
| notify-deploy: | |
| needs: | |
| - "changesets" | |
| - "prepare" | |
| - "review" | |
| if: >- | |
| github.event_name != 'pull_request' | |
| && needs.changesets.outputs.hasChangesets == 'false' | |
| && needs.changesets.outputs.publishNeeded == 'true' | |
| runs-on: "ubuntu-24.04" # _SLANG_DEV_CONTAINER_BASE_IMAGE_ (keep in sync) | |
| steps: | |
| - name: "Notify review requested" | |
| continue-on-error: true | |
| uses: "slackapi/slack-github-action@45a88b9581bfab2566dc881e2cd66d334e621e2c" # v3.0.3 | |
| with: | |
| webhook: "${{ secrets.PUBLISHING_NOTIFICATIONS_SLACK_WEBHOOK_URL }}" | |
| webhook-type: "incoming-webhook" | |
| payload: | | |
| { | |
| "text": "Slang release — Review requested", | |
| "blocks": [ | |
| { | |
| "type": "header", | |
| "text": { | |
| "type": "plain_text", | |
| "text": "Slang release — Review requested" | |
| } | |
| }, | |
| { | |
| "type": "section", | |
| "text": { | |
| "type": "mrkdwn", | |
| "text": "*Commit:* <${{ github.event.head_commit.url || format('{0}/{1}/commit/{2}', github.server_url, github.repository, github.sha) }}|View commit>\n*Approve:* <${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|Open workflow run>" | |
| } | |
| }, | |
| { | |
| "type": "context", | |
| "elements": [ | |
| { | |
| "type": "mrkdwn", | |
| "text": "Triggered by *${{ github.actor }}* via `${{ github.event_name }}`" | |
| } | |
| ] | |
| } | |
| ] | |
| } | |
| # ─────────────────────────────────────────────── | |
| # Publish: actual publishing with environment gate | |
| # Only runs on push to main or dispatch (never PRs). | |
| # ─────────────────────────────────────────────── | |
| publish: | |
| needs: | |
| - "changesets" | |
| - "prepare" | |
| - "review" | |
| - "notify-deploy" | |
| # Redundant with the needs chain, but explicit for safety: never publish | |
| # from PRs, when there are pending changesets, or when the version is | |
| # already published. | |
| if: >- | |
| github.event_name != 'pull_request' | |
| && needs.changesets.outputs.hasChangesets == 'false' | |
| && needs.changesets.outputs.publishNeeded == 'true' | |
| runs-on: "ubuntu-24.04" # _SLANG_DEV_CONTAINER_BASE_IMAGE_ (keep in sync) | |
| environment: "slang-release" | |
| permissions: | |
| contents: "write" # to create new releases | |
| id-token: "write" # OIDC token (needed for trusted publishing) | |
| steps: | |
| - name: "Notify deployment starting" | |
| continue-on-error: true | |
| uses: "slackapi/slack-github-action@45a88b9581bfab2566dc881e2cd66d334e621e2c" # v3.0.3 | |
| with: | |
| webhook: "${{ secrets.PUBLISHING_NOTIFICATIONS_SLACK_WEBHOOK_URL }}" | |
| webhook-type: "incoming-webhook" | |
| payload: | | |
| { | |
| "text": "Slang release — Deployment starting", | |
| "blocks": [ | |
| { | |
| "type": "header", | |
| "text": { | |
| "type": "plain_text", | |
| "text": "Slang release — Deployment starting" | |
| } | |
| }, | |
| { | |
| "type": "section", | |
| "text": { | |
| "type": "mrkdwn", | |
| "text": "*Run:* <${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|Open workflow run>" | |
| } | |
| }, | |
| { | |
| "type": "context", | |
| "elements": [ | |
| { | |
| "type": "mrkdwn", | |
| "text": "Triggered by *${{ github.actor }}*" | |
| } | |
| ] | |
| } | |
| ] | |
| } | |
| - name: "Checkout Repository" | |
| uses: "actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd" # v6.0.2 | |
| with: | |
| persist-credentials: false | |
| - name: "Download publish artifacts" | |
| uses: "actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c" # v8.0.1 | |
| with: | |
| name: "${{ needs.prepare.outputs.artifact-name }}" | |
| path: "target/publish-artifacts/" | |
| # Compile infra_cli with no registry token in scope. | |
| - name: "Build infra_cli (before any token)" | |
| run: "./scripts/bin/infra --help" | |
| - name: "infra publish npm" | |
| # No tarball means prepare packed nothing (version already on npm) — nothing to publish. | |
| if: "${{ needs.prepare.outputs.tarball-name != '' }}" | |
| run: "./scripts/bin/infra publish npm --tarball target/publish-artifacts/${{ needs.prepare.outputs.tarball-name }}" | |
| - name: "Exchange Cargo Token" | |
| id: "exchangeCargoToken" | |
| uses: "rust-lang/crates-io-auth-action@bbd81622f20ce9e2dd9622e3218b975523e45bbe" # v1.0.4 | |
| - name: "infra publish cargo" | |
| run: "./scripts/bin/infra publish cargo" | |
| env: | |
| CARGO_REGISTRY_TOKEN: "${{ steps.exchangeCargoToken.outputs.token }}" | |
| - name: "infra publish github-release" | |
| run: "./scripts/bin/infra publish github-release" | |
| env: | |
| GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" |