You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Let release.yml be cut from a manual workflow_dispatch (#160)
Add a tag job to release.yml that, on manual dispatch, resolves the
version and creates+pushes the vX.Y.Z tag (reusing cut_release.sh
--no-push), then builds and publishes in the same run. This lets a
Claude web session — which works on a feature branch and can't push
tags — cut a release via the "Run workflow" button /
actions_run_trigger.
Tag creation lives inside the release run on purpose: a GITHUB_TOKEN tag
push does not re-trigger the on:push half, so a standalone tag-push
workflow would silently never build.
https://claude.ai/code/session_01D6zsmQxdvq3dUPuVrbUaNg
Co-authored-by: Claude <noreply@anthropic.com>
Copy file name to clipboardExpand all lines: .claude/skills/release-prep/SKILL.md
+12-8Lines changed: 12 additions & 8 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,36 +1,40 @@
1
1
---
2
2
name: release-prep
3
-
description: Prepare an assembly CLI release — bump the version, run the full gate, then tag to trigger the bottle pipeline. Use when cutting a new release.
3
+
description: Prepare an assembly CLI release — confirm main is green, then tag (locally or via the manual workflow) to trigger the bottle pipeline. Use when cutting a new release.
4
4
disable-model-invocation: true
5
5
---
6
6
7
7
# release-prep
8
8
9
9
Drive an `assembly` release to a verified, tagged state. Stop and report at the first failure — never tag on a red check.
10
10
11
-
## 1. Version bump
11
+
## 1. Pick the version
12
12
13
-
-Update `version` in `pyproject.toml`(`[project]`). Confirm `aai_cli/__init__.py``__version__` stays in sync (the `version` command reads it).
13
+
-With hatch-vcs **the git tag _is_ the version** — there is no `pyproject.toml`/ `aai_cli/__init__.py`string to bump. `cut_release.sh` defaults to the next patch above the latest `vX.Y.Z` tag; pass `X.Y.Z` for a minor/major bump.
14
14
- Decide the bump (patch/minor/major) from what changed since the last tag; ask the user if it's ambiguous.
15
-
- Land the bump via a normal PR (regular CI) before tagging.
16
15
17
16
## 2. Full gate
18
17
19
18
```sh
20
19
./scripts/check.sh
21
20
```
22
21
23
-
Must end with `All checks passed.` (ruff, mypy, markdownlint, shellcheck, pytest+coverage, build, `twine check --strict`).
22
+
Must end with `All checks passed.` (ruff, mypy, markdownlint, shellcheck, pytest+coverage, build, `twine check --strict`). The release builds whatever `main` points at, so confirm `main` is green before tagging.
24
23
25
24
## 3. Tag to trigger the bottle pipeline
26
25
26
+
Two equivalent ways to cut the tag — both land on `.github/workflows/release.yml`:
27
+
28
+
**Local** (from a clean `main` in sync with `origin/main`):
29
+
27
30
```sh
28
-
./scripts/cut_release.sh
31
+
./scripts/cut_release.sh # next patch; --dry-run verifies without tagging, --yes skips the prompt
32
+
./scripts/cut_release.sh 0.3.0 # explicit version
29
33
```
30
34
31
-
This derives the version from `pyproject.toml`, verifies the tree is clean, on `main`, and in sync with origin, then tags `vX.Y.Z`and pushes it. (`--dry-run` verifies without tagging; `--yes` skips the confirmation prompt.)
35
+
**No local checkout** (e.g. a Claude web session on a feature branch): run the **Release** workflow's manual `workflow_dispatch` — GitHub's "Run workflow" button, or the `actions_run_trigger` MCP tool — with an optional `version` input (blank = next patch). Its `tag` job resolves the version and creates+pushes the tag from `main`, then the same run builds and publishes. Set `dry_run: true` to build the bottle for an existing tag without publishing.
32
36
33
-
The pushed tag triggers `.github/workflows/release.yml`, which:
37
+
The tag triggers `.github/workflows/release.yml`, which:
34
38
35
39
1. Builds the arm64 macOS bottle (`arm64_sonoma`).
36
40
2. Creates the `vX.Y.Z` GitHub Release with the bottle attached.
Copy file name to clipboardExpand all lines: AGENTS.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -75,7 +75,7 @@ structured so independent changes stay in disjoint files. Keep it that way:
75
75
- The **package/module** is `aai_cli`; the **distribution** name is `aai-cli`; the **console command** is `assembly` (`[project.scripts] assembly = "aai_cli.main:run"`).
76
76
-`assembly init` templates live in `aai_cli/init/templates/` and are **committed**, including renamed dotfiles (`gitignore` → `.gitignore`, `env.example`). The wheel force-includes them via `[tool.hatch.build.targets.wheel] artifacts`, excluding `__pycache__/*.pyc`. Editing templates needs care — see the parametrized contract tests (`tests/test_init_template_*.py`).
77
77
-`audioop` left the stdlib in 3.13; `audioop-lts` backfills it (conditional dependency). Supported Pythons: 3.12–3.13.
78
-
- **Releasing is tag-triggered.** The version is **derived from the git tag** by hatch-vcs and written to a gitignored `aai_cli/_version.py` at build time — there is no version string to keep in sync across `pyproject.toml` or `aai_cli/__init__.py`, and `bump_patch.sh` no longer exists. To cut a release, run `scripts/cut_release.sh` from a clean `main` in sync with `origin/main`: no argument → next patch above the latest `vX.Y.Z` tag; `cut_release.sh X.Y.Z` → explicit version. It tags + pushes, which fires `.github/workflows/release.yml` — that builds the prebuilt arm64 Homebrew bottle (`Formula/assembly.rb`), cuts the GitHub Release, and opens the formula PR. Bottling matters because the deps include Rust-backed sdists (`pydantic-core`, `jiter`, `cryptography`) that would otherwise compile from source on `brew install`. The Homebrew formula builds from a git-less GitHub source tarball, so `Formula/assembly.rb`'s `def install` sets the generic `SETUPTOOLS_SCM_PRETEND_VERSION` env var (installing resources first under a clean env, then setting the var for our package only) to feed the tag version to the build. **`cut_release.sh` only runs from a clean `main` in sync with `origin/main`** (it hard-errors on a feature branch / dirty tree), so cut releases from `main`, not your working branch. The "update available" notice users see is `aai_cli/update_check.py`.
78
+
- **Releasing is tag-triggered.** The version is **derived from the git tag** by hatch-vcs and written to a gitignored `aai_cli/_version.py` at build time — there is no version string to keep in sync across `pyproject.toml` or `aai_cli/__init__.py`, and `bump_patch.sh` no longer exists. To cut a release, run `scripts/cut_release.sh` from a clean `main` in sync with `origin/main`: no argument → next patch above the latest `vX.Y.Z` tag; `cut_release.sh X.Y.Z` → explicit version. It tags + pushes, which fires `.github/workflows/release.yml` — that builds the prebuilt arm64 Homebrew bottle (`Formula/assembly.rb`), cuts the GitHub Release, and opens the formula PR. **You don't need a local checkout to release:** `release.yml` also has a manual `workflow_dispatch` (GitHub's "Run workflow" button, or `actions_run_trigger` from a Claude web session) taking an optional `version` input — its `tag` job resolves the version and creates+pushes the tag (reusing `cut_release.sh --no-push`), and the rest of the pipeline then runs in that same workflow run. Tag creation lives *inside* the release run on purpose: a `GITHUB_TOKEN` tag push wouldn't re-trigger the `on: push` half, so a separate "push the tag" workflow would silently never build. (`dry_run: true` builds the bottle for an existing tag without publishing.) Bottling matters because the deps include Rust-backed sdists (`pydantic-core`, `jiter`, `cryptography`) that would otherwise compile from source on `brew install`. The Homebrew formula builds from a git-less GitHub source tarball, so `Formula/assembly.rb`'s `def install` sets the generic `SETUPTOOLS_SCM_PRETEND_VERSION` env var (installing resources first under a clean env, then setting the var for our package only) to feed the tag version to the build. **`cut_release.sh` only runs from a clean `main` in sync with `origin/main`** (it hard-errors on a feature branch / dirty tree), so cut releases from `main`, not your working branch. The "update available" notice users see is `aai_cli/update_check.py`.
79
79
80
80
## Manual QA / running the CLI in sandboxed sessions
0 commit comments