Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 14 additions & 1 deletion .agents/skills/manage-ci/references/current-inventory.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,27 @@ Read it with `../SKILL.md` and `ci/ci.md` before editing CI.
| `main_windows.yml` (`Main · Windows`) | push to `main` | Exhaustive main planning plus the same-commit reusable Windows lane |
| `ci.yml` | `workflow_call` only | Inert migration shim for the former main ingress filename; no push trigger or dispatch |
| `ci-control.yml` (`CI · Manual Full`) | dispatch on default branch | Explicit operator-only full plan, bounded lane dispatch and correlated diagnostic checks |
| `release.yml` | release tags, dispatch | Release-only signing, assets and publication |
| `release.yml` | release tags, dispatch | Canonical version synchronization, release-only signing, assets and publication |
| `website-pages.yml` | main website paths, dispatch | Public website deployment |
| `pr_cleanup.yml` | PR close, dispatch | Positively matched cleanup only |
| `pr_auto_assign.yml` | PR lifecycle | Metadata only |

Other scheduled, deployment, Docker, package, canary and cache-warming
workflows are independent of required PR readiness.

For a non-canary manual dispatch, `release.yml` runs the checked-in
`scripts/release-version.sh`, creates one linear release-source commit when the
tracked version surface changes, and fast-forwards `main` before any release
build starts. `just release` is a preflight and synchronous dispatcher for that
same workflow. A tag-push release is read-only with respect to `main` and is
accepted only when the tag is already reachable from `main` and applying the
same version script produces no tracked diff. Canary dispatches never update
`main` or publish. The publish job creates only the release-specific tag commit
for generated Swift/SDK resources and enables GitHub-generated release notes.
The comparison base is the highest stable `vMAJOR.MINOR.PATCH` tag below the
target; prerelease tags are excluded so RC and final notes use the same stable
baseline.

The five PR lifecycle rows and five main push rows above are the complete
allowed routine validation entry sets. Their separation and direct GitHub log
visibility are contractual, not a presentation preference. `pr_builds.yml`,
Expand Down
65 changes: 65 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,13 @@ jobs:
metadata:
name: Resolve release metadata
runs-on: ubuntu-24.04
permissions:
contents: write
outputs:
tag: ${{ steps.meta.outputs.tag }}
version: ${{ steps.meta.outputs.version }}
source_sha: ${{ steps.source.outputs.sha }}
release_notes_base: ${{ steps.source.outputs.release_notes_base }}
prerelease: ${{ steps.meta.outputs.prerelease }}
skip_gpu_bundles: ${{ steps.meta.outputs.skip_gpu_bundles }}
canary: ${{ steps.meta.outputs.canary }}
Expand Down Expand Up @@ -136,6 +140,64 @@ jobs:
echo "Manual release tag already exists and is immutable: $RELEASE_TAG" >&2
exit 1
fi
- uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0
with:
node-version: 24
- uses: dtolnay/rust-toolchain@4cda84d5c5c54efe2404f9d843567869ab1699d4 # stable 2026-07-16
- name: Prepare canonical release source
id: source
shell: bash
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
RELEASE_TAG: ${{ steps.meta.outputs.tag }}
CANARY: ${{ steps.meta.outputs.canary }}
run: |
set -euo pipefail
source_sha="$GITHUB_SHA"

if [[ "$GITHUB_EVENT_NAME" == "push" ]]; then
scripts/release-version.sh "$RELEASE_TAG"
if ! git diff --quiet; then
echo "Release tag $RELEASE_TAG does not contain its complete version update." >&2
echo "Run scripts/release-version.sh $RELEASE_TAG, commit the result on main, and create a new tag." >&2
git status --short >&2
exit 1
fi
elif [[ "$CANARY" == "true" ]]; then
echo "Canary release: leaving main unchanged."
else
scripts/release-version.sh "$RELEASE_TAG"
git add --update
if ! git diff --quiet; then
echo "Release version preparation left unstaged tracked changes:" >&2
git status --short >&2
exit 1
fi
if git diff --cached --quiet; then
echo "main already contains the complete $RELEASE_TAG version update."
else
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
git commit -m "$RELEASE_TAG: prepare release source"
fi
source_sha="$(git rev-parse HEAD)"
release_remote="https://x-access-token:${GITHUB_TOKEN}@github.com/${GITHUB_REPOSITORY}.git"
git push "$release_remote" "$source_sha:refs/heads/main"
fi

release_notes_base="$(
git tag --list 'v*' |
python3 scripts/select-release-notes-base.py "$RELEASE_TAG"
)"
if [[ -n "$release_notes_base" ]]; then
echo "GitHub release notes will compare $release_notes_base...$RELEASE_TAG."
else
echo "No earlier stable release tag exists; GitHub release notes have no explicit comparison base."
fi
{
echo "sha=$source_sha"
echo "release_notes_base=$release_notes_base"
} >> "$GITHUB_OUTPUT"
- name: Select trusted Linux runners
id: runners
uses: ./.github/actions/select-ci-runners
Expand Down Expand Up @@ -1607,6 +1669,7 @@ jobs:
steps:
- uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09 # v5.1.0
with:
ref: ${{ needs.metadata.outputs.source_sha }}
# Archive verification and manifest generation run before any push
# credential is exposed to a shell.
persist-credentials: false
Expand Down Expand Up @@ -1747,6 +1810,8 @@ jobs:
with:
tag_name: ${{ needs.metadata.outputs.tag }}
prerelease: ${{ needs.metadata.outputs.prerelease }}
generate_release_notes: true
previous_tag: ${{ needs.metadata.outputs.release_notes_base }}
overwrite_files: false
files: release-artifacts/*

Expand Down
6 changes: 3 additions & 3 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -689,11 +689,11 @@ For stale instances (crashed mesh-llm leaving behind a runtime dir):

See `RELEASE.md` for the full process.

Current release flow: kick off the **Release** workflow (`.github/workflows/release.yml`) from the GitHub Actions UI via `workflow_dispatch` with the version input (e.g. `v0.X.Y`).
Current release flow: kick off the **Release** workflow (`.github/workflows/release.yml`) from the GitHub Actions UI via `workflow_dispatch` with the version input (e.g. `v0.X.Y`), or run `just release v0.X.Y` to preflight and dispatch that same workflow.

The dispatched workflow handles everything: it bumps versions via `scripts/release-version.sh`, generates and patches the SwiftPM manifest, packages SDK console assets, creates and pushes the release tag at a release-prep commit, builds the full artifact matrix (macOS, Linux CPU/ARM64/CUDA/CUDA-Blackwell/ROCm/Vulkan, Windows CPU/CUDA/ROCm/Vulkan), and publishes the GitHub release. Dispatch inputs include `skip_gpu_bundles` and `canary` (dry-run: build + smoke without publishing).
The dispatched workflow handles everything: it bumps versions via `scripts/release-version.sh`, commits the tracked version surface to `main` before building, generates and patches the SwiftPM manifest, packages SDK console assets, creates and pushes the release tag at a release-prep commit, builds the full artifact matrix (macOS, Linux CPU/ARM64/CUDA/CUDA-Blackwell/ROCm/Vulkan, Windows CPU/CUDA/ROCm/Vulkan), and publishes the GitHub release with generated notes. Dispatch inputs include `skip_gpu_bundles` and `canary` (dry-run: build + smoke without mutating `main` or publishing).

Pushing a `v*` tag manually also triggers the workflow, but that path requires preparing `Package.swift` and SDK console assets in the tag commit yourself — see `RELEASE.md`. Prefer the dispatch path.
Pushing a `v*` tag manually also triggers the workflow, but the tag must point to `main` history with the matching `scripts/release-version.sh` update already committed; it also requires preparing `Package.swift` and SDK console assets in the tag commit yourself. The workflow rejects a drifted tag. See `RELEASE.md` and prefer the dispatch path.

### Installer checksum sidecars

Expand Down
Loading
Loading