chore(wheelhouse): sync fleet canonicals to template@75f3a4ddf + rege… #1
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: 🚀 GitHub release | |
| # PRESET — seeded once from template/presets/ (onboarding or first cascade), | |
| # then repo-owned: customize what THIS repo releases. The fleet base actions | |
| # do the heavy lifting — github-release-app-token mints the release App token, | |
| # github-release cuts the immutable 3-step release tied to the pushed tag | |
| # (create --draft → upload assets → edit --draft=false). | |
| # | |
| # Default flow: push a signed v* tag → this workflow cuts a GitHub Release for | |
| # it. A manual dispatch is a DRY-RUN (prints the cut plan) unless | |
| # `release: true`. Add build steps + assets for whatever this repo ships. | |
| # | |
| # ORDER RULE: the tag + immutable GH release are the FINAL markers of a | |
| # release — they may only exist AFTER the registry publish is live. A STAGED | |
| # npm package is not published (staging may never be approved), so this | |
| # workflow refuses to cut when the tagged version is not resolvable on its | |
| # registry (npm packument / crates.io sparse index). Registry-less repos | |
| # (private, github-release-only) skip the gate. | |
| on: | |
| workflow_dispatch: | |
| inputs: | |
| release: | |
| description: 'Cut the release for real (false = dry-run plan, the default).' | |
| type: boolean | |
| default: false | |
| tag: | |
| description: 'Tag to release. Required on dispatch (tag pushes use the pushed tag).' | |
| type: string | |
| default: '' | |
| push: | |
| tags: | |
| - 'v*' | |
| permissions: | |
| contents: read | |
| jobs: | |
| release: | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: write | |
| steps: | |
| # First step must be the third-party actions/checkout (GitHub fetches it | |
| # independently) to populate the workspace so the LOCAL | |
| # ./.github/actions/* composite resolves; the fleet checkout action then | |
| # re-checks-out at its own depth. | |
| - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 (2026-05-15) | |
| with: | |
| fetch-depth: 1 | |
| persist-credentials: false | |
| - name: Checkout | |
| uses: ./.github/actions/fleet/checkout | |
| - name: Resolve tag | |
| id: tag | |
| env: | |
| EVENT_NAME: ${{ github.event_name }} | |
| INPUT_TAG: ${{ inputs.tag }} | |
| REF_NAME: ${{ github.ref_name }} | |
| run: | | |
| set -euo pipefail | |
| if [ "${EVENT_NAME}" = "push" ]; then | |
| TAG="${REF_NAME}" | |
| elif [ -n "${INPUT_TAG}" ]; then | |
| TAG="${INPUT_TAG}" | |
| else | |
| echo "× a manual dispatch needs the tag input (tag pushes resolve it from the ref)." >&2 | |
| echo " Fix: re-dispatch with tag: v<version> (the tag must already be pushed)." >&2 | |
| exit 1 | |
| fi | |
| echo "tag=${TAG}" >> "${GITHUB_OUTPUT}" | |
| # Belt-and-braces publish-before-release gate: refuse to cut when the | |
| # tagged version is not actually live on its registry. Runs only when a | |
| # real cut would happen (tag push, or dispatch with release: true) so a | |
| # dry-run plan stays inspectable pre-publish. curl (not npm view) — the | |
| # runner has no install here and npm trips repos' pnpm devEngines. | |
| - name: Registry publish is live | |
| if: ${{ github.event_name == 'push' || inputs.release }} | |
| env: | |
| TAG: ${{ steps.tag.outputs.tag }} | |
| run: | | |
| set -euo pipefail | |
| VERSION="${TAG#v}" | |
| if [ -f package.json ] && [ "$(node -p "require('./package.json').private === true")" != "true" ]; then | |
| NAME="$(node -p "require('./package.json').name")" | |
| if ! curl -fsS -o /dev/null "https://registry.npmjs.org/${NAME}/${VERSION}"; then | |
| echo "× ${NAME}@${VERSION} is not resolvable on npm — refusing to cut the GH release before the registry publish." >&2 | |
| echo " A STAGED package is not published. Fix: approve/complete the publish first, then re-run." >&2 | |
| exit 1 | |
| fi | |
| echo "✓ ${NAME}@${VERSION} is live on npm." | |
| elif [ -f Cargo.toml ]; then | |
| NAME="$(node -e "const m=/^name *= *\"([^\"]+)\"/m.exec(require('node:fs').readFileSync('Cargo.toml','utf8')); if(!m){process.exit(1)}; console.log(m[1])")" | |
| case "${#NAME}" in | |
| 1) IDX="1/${NAME}" ;; | |
| 2) IDX="2/${NAME}" ;; | |
| 3) IDX="3/${NAME:0:1}/${NAME}" ;; | |
| *) IDX="${NAME:0:2}/${NAME:2:2}/${NAME}" ;; | |
| esac | |
| if ! curl -fsS "https://index.crates.io/${IDX}" | grep -q "\"vers\":\"${VERSION}\""; then | |
| echo "× ${NAME}@${VERSION} is not in the crates.io index — refusing to cut the GH release before the registry publish." >&2 | |
| exit 1 | |
| fi | |
| echo "✓ ${NAME}@${VERSION} is live on crates.io." | |
| else | |
| echo "No public npm package or crate manifest — skipping the registry-liveness gate (github-release-only repo)." | |
| fi | |
| - name: Mint release-app token | |
| id: app-token | |
| uses: ./.github/actions/fleet/github-release-app-token | |
| with: | |
| client-id: ${{ vars.SOCKET_RELEASE_CLIENT_ID }} | |
| private-key: ${{ secrets.SOCKET_RELEASE_APP_PRIVATE_KEY }} | |
| owner: ${{ github.repository_owner }} | |
| # Build this repo's release assets here, then list them under the cut | |
| # step's `assets:` (newline-separated paths; each must exist). | |
| - name: Cut immutable GitHub release | |
| uses: ./.github/actions/fleet/github-release | |
| with: | |
| tag: ${{ steps.tag.outputs.tag }} | |
| dry-run: ${{ (github.event_name == 'push' || inputs.release) && 'false' || 'true' }} | |
| token: ${{ steps.app-token.outputs.token }} |