Skip to content

Keep an Anchor v1 copy of every Anchor example, tested in its own CI job - #135

Merged
mikemaccana merged 3 commits into
mainfrom
claude/solana-anchor-v1-v2-structure-x62v8i
Aug 24, 2026
Merged

Keep an Anchor v1 copy of every Anchor example, tested in its own CI job#135
mikemaccana merged 3 commits into
mainfrom
claude/solana-anchor-v1-v2-structure-x62v8i

Conversation

@mikemaccana

Copy link
Copy Markdown
Collaborator

Anchor v1 is expected to stay on long-term support, and many deployed programs will
stay with it. This ships both versions of every Anchor example, each built and tested
by its own CI job.

What is here

  • 55 anchor-v1/ directories, one beside each anchor/, holding the example
    exactly as it stood before the v2 port. Restored from 94abbea, the last commit on
    main before that merge: 864 files, every blob byte-identical to the baseline.
  • .github/workflows/anchor-v1.yml, building and testing them on Anchor 1.1.2.
  • The existing workflow is now Anchor v2. Its filename, triggers and project
    discovery are unchanged.

The v2 directory keeps the plain name anchor/. No path in the current examples moves.

Notes for review

Repository size. 18 MB of files, but 16 MB of that is 17 third-party .so test
fixtures whose blobs are byte-identical to the ones already tracked under anchor/.
Git stores them once, so the tree actually grows by ~2.3 MB of text.

The two workflows cannot see each other's projects. Both discover work with
find -type d -name, which matches a path segment exactly — anchor never matches
anchor-v1 and vice versa. That also keeps anchor-example/ in the
nft-meta-data-pointer tree out of both, as before.

The v2-only IDL workaround is deliberately not carried into v1. anchor#4947
(enum variants emitted as "fields") is a 2.0.0-rc.1 bug, so v1 builds generate IDLs
normally rather than passing --no-idl.

The anchor-v1 crates are not root workspace members, and cannot be. Each carries
the same [package] name as its anchor/ sibling, and one workspace cannot hold two
packages called the same thing. Renaming them to *-v1 was considered and rejected: a
package-only rename still collides on the [lib] output filename (cargo warns
output filename collision, and says it may become a hard error), so it would mean
renaming 59 [lib] names, the target/deploy/<name>.so path that 56 test files
include_bytes!, 159 Anchor.toml [programs.localnet] keys and 62 declare_id! /
declare_program! sites — and the directories would stop being the programs as they
actually shipped on v1. The root Cargo.toml comment records this so the omission does
not read as an oversight.

The consequence is that cargo fmt and cargo clippy never see the v1 crates; the
Anchor v1 workflow compiles and tests them instead.

READMEs now name the CLI their commands need. A bare anchor build was unambiguous
while the repository had one Anchor and is not any more, so anchor/ pages say Anchor
v2 and anchor-v1/ pages say Anchor v1. README.md and CONTRIBUTING.md, which sit
above both, show both.

Both workflows now run weekly (v2 Mondays 03:00 UTC, v1 05:00 UTC, staggered). The
analyze step has always treated a scheduled run as "build everything", but nothing
declared a schedule, so that path had never executed. It is worth having because no
Anchor project commits a Cargo.lock and Dependabot only covers the root workspace, so
dependency drift in either tree is otherwise invisible until an unrelated PR happens to
touch those files.

Both Anchor jobs install the CLI from crates.io. The v1 job initially installed avm
from the tip of anchor's main branch, so what CI installed drifted with whatever
landed there. 1.1.2 is an ordinary published release, so it is now
cargo install anchor-cli --version 1.1.2 --locked, matching v2.

Verification

Checked locally before pushing:

  • 55 projects discovered per workflow, with no overlap between them
  • all 864 restored blobs byte-identical to 94abbea
  • all 55 anchor-v1 projects resolve to their own workspace root, not the repository's
  • no anchor-v1 crate entered the root workspace (cargo metadata: 0 of 101 members)
  • cargo fmt --check clean; pnpm check exits 0 (94 warnings, all pre-existing — the
    v1 and v2 vault-strategy apps report an identical 47 each)
  • five representative v1 projects compile against anchor-lang 1.1.2: favorites,
    escrow, token-extensions/basics, cutils, perpetual-futures
  • every relative link in all 110 Anchor READMEs resolves on disk

Not verified locally: the LiteSVM tests include_bytes! a compiled .so, and the
container had no Anchor CLI or SBF toolchain, so anchor build / anchor test never
ran. CI is what proves those — and this first run builds all 55 v1 projects, because
the workflow file itself changed.

🤖 Generated with Claude Code

https://claude.ai/code/session_01BMDApPWRHM1StJwtyDSrEM


Generated by Claude Code

claude added 3 commits August 21, 2026 20:24
Anchor v1 is expected to stay on long-term support, and many deployed
programs will stay with it. Both versions of every Anchor example now ship.

Every one of the 55 Anchor projects gains a sibling `anchor-v1/` directory
holding the example exactly as it stood before the v2 port, restored from
94abbea, the last commit on main before that merge. 864 files, byte-identical
to the baseline. The 17 third-party .so test fixtures are the same blobs
already tracked under `anchor/`, so git stores one copy and the tree grows by
~2.3 MB of text rather than 18 MB.

.github/workflows/anchor-v1.yml builds and tests them on Anchor 1.1.2 via avm.
It is the workflow as it stood at 94abbea with project discovery changed to
`find -type d -name "anchor-v1"`. The v2-only IDL workaround (anchor#4947,
enum variants emitted as "fields") is deliberately not carried over: that bug
does not exist in 1.1.2, so v1 builds generate IDLs normally.

The `Anchor` workflow becomes `Anchor v2`, so the two checks read as a pair.
Both match a directory name exactly, so neither can ever see the other's
projects - which is also why `anchor-example/` in the nft-meta-data-pointer
tree stays out of both.

The anchor-v1 crates are not root workspace members and cannot be: each
carries the same package name as its `anchor/` sibling, and one workspace
cannot hold two packages called the same thing. They need no `exclude` entry
either, since nothing in the root depends on them by path and each
anchor-v1/Cargo.toml declares its own `[workspace]`. The root manifest comment
now says so, so the omission does not read as an oversight.

A bare `anchor build` was unambiguous while the repository had one Anchor and
is not any more, so every Anchor README now names the CLI its commands need:
`anchor/` pages say Anchor v2, `anchor-v1/` pages say Anchor v1. README.md and
CONTRIBUTING.md, which sit above both, show both.

Verified: 55 projects discovered per workflow with no overlap; all 864 restored
blobs identical to baseline; all 55 anchor-v1 projects resolve to their own
workspace root; no anchor-v1 crate entered the root workspace; cargo fmt and
biome clean; and five representative v1 projects (favorites, escrow,
token-extensions/basics, cutils, perpetual-futures) compile against anchor-lang
1.1.2. The LiteSVM tests need `anchor build` first and no SBF toolchain was
available here, so CI is what proves those.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BMDApPWRHM1StJwtyDSrEM
anchor-v1.yml was copied from anchor.yml verbatim, so both files declared jobs
named `changes`, `summary` and `build-and-test-group-N`. GitHub reports check
names from job names, not the workflow's `name:`, so a pull request touching
both trees showed two `changes`, two `summary` and up to 28 indistinguishable
`build-and-test-group-N` rows with nothing to say which Anchor each belonged to.

The v1 jobs are now `changes (Anchor v1)`, `anchor-v1-group-N` and
`summary (Anchor v1)`. Job ids are unchanged, so the `needs:` edges still
resolve; only the reported names differ. anchor.yml keeps its existing names, so
nothing outside the repository that refers to them has to change.

Also fixes six broken relative links. Three READMEs pointed at the repository
catalog one directory short of the root - `../../README.md` from
`basics/counter/anchor/` is `basics/README.md`, which does not exist. The
restore mirrored each into anchor-v1, doubling them, so all six are corrected
here.

Verified: no check name is now shared between the two workflows, and every
relative link in all 110 Anchor READMEs resolves on disk.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BMDApPWRHM1StJwtyDSrEM
…flows

Two fixes to the Anchor v1 job, both inherited from the workflow it was restored
from rather than introduced by the restore.

The v1 job installed avm with `cargo install --git https://github.com/coral-xyz/anchor
avm`, which builds avm from the tip of anchor's main branch. What CI installs then
drifts with whatever landed there, and it costs a full avm build on every cold cache.
The v2 job already moved off avm because avm has no prebuilt binary for the
2.0.0-rc.1 pre-release. 1.1.2 is an ordinary published release, so the v1 job can use
the same shape for the simpler reason that it is pinned and reproducible:

    cargo install anchor-cli --version 1.1.2 --locked --force

The cache key changes with it, so an entry holding an avm-built binary is never
restored over the registry one.

Both workflows also gain a weekly schedule - v2 Mondays 03:00 UTC, v1 05:00 UTC,
staggered so 110 project builds do not land at once. The analyze step has always
treated `github.event_name == 'schedule'` as "build every project", but neither
workflow declared a schedule, so that branch had never run. It earns its place
because no Anchor project commits a Cargo.lock (.gitignore ignores **/*/Cargo.lock)
and Dependabot is configured for directory "/", the root workspace, which the
anchor-v1 crates are not members of. Dependency drift in either tree was otherwise
invisible until an unrelated pull request happened to touch those files.

Also corrects a comment both files carried claiming these steps install "Anchor via
avm", which stopped being true for v2 several commits ago and is not true for v1 now.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BMDApPWRHM1StJwtyDSrEM
@mikemaccana
mikemaccana merged commit 617cb44 into main Aug 24, 2026
58 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants