Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
86 changes: 86 additions & 0 deletions .claude/skills/bump-aztec-version/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
---
name: bump-aztec-version
description: >-
Upgrade this repo to a new aztec-packages version — bump every reference (all Nargo.toml
aztec-nr git tags/revs + every @aztec/* npm dep + config.aztecVersion), install the matching
toolchain, and validate the bump locally (compile, Noir tests, typecheck, build, dry-run).
Produces a validated branch ready to merge. Publishing is the separate `release` skill.
Use when adopting a new aztec-packages tag or commit.
---

# Bump the aztec-packages version

Adopts a new `aztec-packages` version across the repo and proves it works locally. Output: a branch
that compiles, tests, typechecks, and builds against the new deps — ready to open a PR to `main`.
**Publishing (rc / production) is handled by the separate `release` skill** — this skill stops at a
merged, validated bump.

## Step 0 — gather inputs (ask the user)
Use `AskUserQuestion` (or ask directly) for:
1. **Target version** — a **tag** (e.g. `v5.0.0`) or a **commit SHA** of `AztecProtocol/aztec-packages`.
2. **Source** — a **path to a local checkout** of aztec-packages, or the **GitHub repo** (`AztecProtocol/aztec-packages`). The source is for *diagnosis + toolchain*, not the dep URL (Nargo deps always point at the GitHub git URL).
3. Derive the **npm version**: for a tag `vX.Y.Z` → `X.Y.Z`; for a commit, find the matching published npm version (`npm view @aztec/aztec.js versions` — often a `-nightly.`/`-snapshot.` build) or confirm one exists. If none, stop and tell the user the npm packages aren't published for that commit.

Verify the target exists before touching anything:
- local: `git -C <path> cat-file -e <tag-or-sha>^{commit}`
- github: `gh api repos/AztecProtocol/aztec-packages/commits/<tag-or-sha> --jq .sha`
- npm: `npm view @aztec/aztec.js@<npmver> version`

## Step 1 — bump the Noir deps (all `Nargo.toml`)
```bash
find . -name Nargo.toml -not -path '*/node_modules/*'
```
In each, update **only** the deps whose `git = "https://github.com/AztecProtocol/aztec-packages/"`
(e.g. `aztec`, `serde`, `uint_note`, `balance_set`, `compressed_string`). For a tag set
`tag = "vX.Y.Z"`; for a commit set `rev = "<sha>"` (replacing the existing `tag`/`rev`).
**Do NOT touch** non-aztec-packages deps (e.g. `sha512`, `bignum`) — they version independently.

## Step 2 — bump the npm deps (`package.json`)
- Every `@aztec/*` dependency (accounts, aztec.js, noir-contracts.js, protocol-contracts, pxe, stdlib, wallet-sdk, wallets, …) → the npm version.
- `config.aztecVersion` → the npm version (the `setup-aztec` CI action reads this to install the toolchain).
- The package's own `version` is the *release* version — bump it too if this repo tracks aztec (it does), else leave.
- **`@aztec-foundation/aztec-benchmark` is a separate package** (its own repo/release). Only bump it if a matching release exists; it declares `@aztec/*` as **peerDependencies**, so it must resolve to the same aztec version — mismatches cause duplicate-type errors (see Gotchas).

## Step 3 — regenerate the lockfile + toolchain
```bash
yarn install # updates node_modules + yarn.lock to the new versions
aztec-up install <version> # install the toolchain matching the target (do NOT rely on a stale nightly)
export PATH="$HOME/.aztec/current/bin:$PATH"
```
Confirm: `aztec --version`. If a local aztec-packages checkout was given, its toolchain can be used instead.

## Step 4 — local validation (prove the bump)
Run in order; stop and diagnose on the first failure:
```bash
yarn ccc # clean + compile + codegen against the new deps
yarn test:nr # Noir tests (aztec test)
# typecheck src + scripts (+ benchmarks if the benchmark dep resolves) via a temp tsconfig with noEmit
yarn format:check
yarn install --frozen-lockfile # lockfile matches package.json
yarn build # assembles export/<pkg>
(cd export/@aztec-foundation/aztec-standards && npm publish --dry-run --access public) # tarball sanity
# yarn test:js — only if a local network is up (aztec start --local-network); needs no npm creds
```
**Diagnosing failures:** a compile/test break is often a real API change in the new aztec version,
not a repo bug. Use the **local aztec-packages checkout / `gh api` at the target ref** to diff the
relevant internals and fix. See Gotchas.

## Step 5 — hand off
When everything is green: commit, open a PR to `main`, let CI pass, merge. Then invoke the
**`release`** skill to cut an `rc` prerelease and, once that's validated, the production release.

---

## Gotchas (bump-time — check these first)
- **Toolchain mismatch.** The default local `aztec`/`nargo` is often an older nightly that can't parse
the target's aztec-nr (e.g. "Non-ASCII character in comment"). Always `aztec-up install <version>`.
- **Hand-rolled reproductions of aztec internals break on API changes.** `src/escrow_contract/src/key_derivation.nr`
re-implements `deriveKeys`; when v5 added master message-signing/fallback keys, escrow addresses
stopped matching. If `get_escrow`/derivation tests fail, diff the aztec-packages key-derivation
constants/`PublicKeys` at the target ref and re-sync. Regenerate the hardcoded `get_test_vector` hashes.
- **v5 wallet API.** `createSchnorrAccount(secret, salt)` → now needs a 3rd `GrumpkinScalar` signing key;
`Wallet` context types may need `EmbeddedWallet`. Deploy scripts derive the secret from the signing key
(`deriveSecretKeyFromSigningKey`).
- **Benchmark peerDep / duplicate tree.** If `benchmarks/*.ts` typecheck shows `_branding` /
`.../aztec-benchmark/node_modules/@aztec/...` errors, the benchmark pulled a *second* `@aztec` tree —
it must be on a version whose `@aztec/*` are `peerDependencies` matching this repo's aztec version.
105 changes: 105 additions & 0 deletions .claude/skills/release/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
---
name: release
description: >-
Publish this repo to npm via the tag-driven release.yml — both rc prereleases
(X.Y.Z-rc.N → `rc` dist-tag) and production releases (X.Y.Z → `latest`). Stamps and
validates the version, pushes a `v*` tag, and verifies the publish (dist-tag, provenance,
smoke install). Always rehearse with an rc before a production tag. Use to cut an rc or a
final release.
---

# Release (rc prerelease or production)

One flow for both. The tag-driven `release.yml` (`on: push tags v*`) derives the dist-tag from the
version: `-rc.N` → `rc`, else `latest`. The `rc` is a **rehearsal** for the immutable production
publish — always do it first. Assumes the version bump is already merged to `main` (see the
`bump-aztec-version` skill).

## Preconditions (state them; don't assume)
- Fork workflows enabled; `NPM_TOKEN` in the `Production` environment with publish+**create** rights
for the package scope; workflows on an available runner (standard `ubuntu-latest`); `v*` tag-push rights.

## Step 1 — pick mode + version (ALWAYS ASK — never infer)
**Always ask the user which release to cut** (use `AskUserQuestion`); never assume the mode from prior
context or conversation. This is a hard-to-reverse publish — the user chooses rc vs production every time.
- **rc rehearsal:** `X.Y.Z-rc.N` (do this first). Next `N` if a prior rc tag exists (`git ls-remote --tags origin`).
- **production:** `X.Y.Z` (only after a green rc).

## Step 2 — stamp the version (⚠️ from the repo ROOT, never `export/`)
`export/…` is a gitignored build artifact with its own trimmed `package.json`; `npm version` there is
a silent no-op on the real package. Always start with `cd "$(git rev-parse --show-toplevel)"`.

- **rc:** throwaway branch off `main` carrying the bump (keeps `main` at `X.Y.Z`):
```bash
cd "$(git rev-parse --show-toplevel)"
git checkout main && git pull
git checkout -b rehearse/vX.Y.Z-rc.N
npm version X.Y.Z-rc.N --no-git-tag-version # edits the tracked ROOT package.json
git commit -am "chore: rehearse X.Y.Z-rc.N"
```
- **production:** `main` is already `X.Y.Z` — no bump, no branch; you'll tag `main` directly.

## Step 3 — MANDATORY pre-tag guard (both modes)
Locally reproduce `release.yml`'s `tag == package.json` check *before* pushing the tag (this is the
assertion that fails the run on a mismatch):
```bash
cd "$(git rev-parse --show-toplevel)"
TARGET="X.Y.Z-rc.N" # the version you're releasing: X.Y.Z (production) or X.Y.Z-rc.N (rc)
case "$TARGET" in *-*) DIST="${TARGET#*-}"; DIST="${DIST%%.*}";; *) DIST="latest";; esac # rc/beta/... | latest — mirrors release.yml
echo "releasing v$TARGET → dist-tag '$DIST'"
[ "$(node -p "require('./package.json').version")" = "$TARGET" ] || { echo "ABORT: root package.json != $TARGET (bump didn't land — wrong dir / edited export/?)"; exit 1; }
git diff --quiet HEAD -- package.json || { echo "ABORT: bump uncommitted — the tag must point at the committed bump"; exit 1; }
grep -q "runs-on: ubuntu-latest$" .github/workflows/release.yml || echo "WARN: release.yml runner may be wrong (rebase onto main?)"
```

## Step 4 — tag & push
⚠️ **STOP — the tag push is the point of no return.** It fires `release.yml`, which publishes to npm,
and npm versions are **immutable**. Before running the push, show the user the exact `TARGET`, `DIST`,
and target commit, and get explicit confirmation. Do **not** push on your own initiative — even for an
rc. (The local tag/guard steps are safe to run first; only the `git push origin` line is gated.)
```bash
git tag -d "v$TARGET" 2>/dev/null; git push origin ":refs/tags/v$TARGET" 2>/dev/null # clear any stale/orphaned tag
git tag "v$TARGET" && git push origin "v$TARGET" # fires release.yml (tag-triggered; uses the file at this commit)
```
Approve the `Production` environment run if reviewers are set.

## Step 5 — verify, THEN report
Watch (`gh run watch`). The publish step succeeding (`+ pkg@ver`, provenance signed) is the source of
truth — the publish is immutable. Then verify the artifact (use `--prefer-online` to dodge cache/lag):
```bash
npm view @aztec-foundation/aztec-standards@"$TARGET" version --prefer-online # exists
npm view @aztec-foundation/aztec-standards dist-tags --prefer-online # $DIST -> $TARGET (see latest gotcha)
cd "$(mktemp -d)" && npm init -y >/dev/null && npm i --prefer-online @aztec-foundation/aztec-standards@"$DIST"
```
For production `DIST=latest`, so `@latest` is what a plain `npm i @aztec-foundation/aztec-standards` resolves to.
Report success once the publish step is green (+ provenance) and the version resolves. A red
*smoke* step alone (propagation lag) is not a failed release — confirm the publish step + `npm view`.

**Order across releases:** rc first (`DIST=rc`, rehearsal), then production (`DIST=latest`) once it's green.

---

## Gotchas (release-time — check these first)
- **Run from the repo ROOT, never `export/`.** That dir is a gitignored build artifact with its own
trimmed `package.json`; `npm version` there is a no-op (`npm error Version not changed`) and leaves the
tag mismatched against the real version → `release.yml` validation fails. Step 3's guard catches it.
- **Registry propagation lag (esp. first publish).** A just-published version — particularly a package's
first-ever publish — can take minutes to resolve; an immediate `npm install` 404s. Don't fail the
release on a smoke miss (warn), and use `--prefer-online` to bypass the negative cache. Your *local*
npm may also cache the 404 — re-check with `npm view … --prefer-online`.
- **The first publish claims `latest`.** npm sets `latest` on a package's first-ever publish regardless of
`--tag`, so an `rc` rehearsal on a brand-new package leaves `latest` pointing at the rc. It self-corrects
when the stable `X.Y.Z` publishes; you can't `dist-tag rm latest` (a package must have one). Don't
announce the package until the stable is out.
- **Runners + fork state.** A GitHub fork has workflows disabled by default (enable in the Actions tab).
Target `ubuntu-latest`; don't assume custom/larger-runner labels (e.g. `ubuntu-latest-m`) exist — jobs
stuck `queued` are the symptom.
- **Pin CI to real tags.** Reusable-workflow refs (aztec-ci-actions / aztec-benchmark) should be pinned to a
released tag SHA (with a `# vX` comment), not a transient `main` HEAD — a pre-re-scope commit can still
`require('@defi-wonderland/…')`.
- **npm is immutable.** Always rehearse with an `rc` before the final tag. `release.yml` publishes
idempotently (re-running a tag re-points the dist-tag instead of erroring) and smoke-tests, so a failed
run is safe to re-trigger.
- **Provenance.** `release.yml` publishes with `--provenance` (needs `id-token: write` + `repository.url`
matching the running repo). The `rc` run is the first to exercise it; a Sigstore transparency-log line
in the publish output confirms it worked.
Loading