Skip to content

ci: run the four example tours, so "runnable" is measured (#20) - #21

Merged
EricAndrechek merged 4 commits into
mainfrom
examples-in-ci
Sep 11, 2026
Merged

EricAndrechek merged 4 commits into
mainfrom
examples-in-ci

Conversation

@EricAndrechek

Copy link
Copy Markdown
Member

Closes #20.

README.md advertises examples/ as "four side-by-side runnable tours" and nothing ran them. examples/chplay.sh existed to do exactly that, and nothing called it — so a signature change in any binding would have broken its tour with every gate green.

This takes option 2 from the issue: run them, scoped to the artifacts job, the only job with a verified artifact already in hand and all four toolchains already set up. The marginal cost is one step rather than a new job.

Two flags, both load-bearing

flag without it
--require-all chplay skips a missing toolchain, so a CI run where all four skipped exits 0 and proves nothing
--locked an unlocked resolve silently rewrites a drifted lockfile and exits 0 — and on a runner that rewrite is discarded, so the drift passes forever

Interactively a skip is still the right answer; you should not need four toolchains to see one tour. Neither flag changes what a tour prints.

Both guards were verified by breaking them, not by inspection

# every toolchain hidden (PATH=/usr/bin:/bin)
chplay.sh                 -> exit 0, four SKIPPED      <- the vacuous pass
chplay.sh --require-all   -> exit 1, four FAILED

# chtypes 0.1.0 planted back into examples/rust/Cargo.lock
chplay.sh rust --locked   -> exit 1  (cargo refuses to update the lock)
cargo check (unlocked)    -> exit 0  AND rewrote the lock to 0.1.2

It found a real defect on its first run

examples/python/uv.lock recorded chtypes 0.1.0 — it had missed the 0.1.1 and 0.1.2 releases. #20 only knew about examples/rust/Cargo.lock, which had been patched by hand; this one was never caught because nothing ever resolved it. Regenerated here. All four tours now run 16/16 sections.

RELEASING.md

Two additions, the second unrelated to #20 but found while writing the first:

  1. The lockfile-regeneration step, since CI now fails on a stale one. That is deliberate — it makes the missed-lockfile failure mode impossible rather than relying on someone remembering.
  2. The release order for every release after the first. The file documented only the one-time launch order, which puts Go first. For a routine release Go must be last: a Go module publishes by the tag existing on a public repo, and release-go.yml only verifies — confirmed by reading it, it runs go build, go vet and verify-published.sh and has no publish step — so that push is irreversible with no gate in front of it.

Safety

No job name: changed; branch protection keys required checks on those, and renaming one would silently drop it from the list.

🤖 Generated with Claude Code

https://claude.ai/code/session_018ckJDLjWhAAttQVrYnQEJD

EricAndrechek and others added 4 commits September 11, 2026 14:30
README.md advertises examples/ as "four side-by-side runnable tours" and
nothing ran them. examples/chplay.sh existed to do it and nothing called it,
so a signature change in any binding would have broken its tour with every
gate green.

chplay.sh gains two flags, and both are load-bearing:

  --require-all  a missing toolchain is a FAILURE, not a skip. Without it a
                 CI run where all four skipped exits 0 and proves nothing.
  --locked       each tour resolves its committed lockfile. Without it an
                 unlocked resolve silently REWRITES a drifted lock and exits
                 0 — and on a runner that rewrite is discarded, so the drift
                 would pass forever.

Both were verified by deliberately breaking them rather than by inspection:
with every toolchain hidden, plain chplay exits 0 with four skips and
--require-all exits 1 with four failures; with chtypes 0.1.0 planted back
into examples/rust/Cargo.lock, --locked exits 1 while an unlocked cargo
check exits 0 and rewrites the lock to 0.1.2.

The step goes in the `artifacts` job, the only one with a verified artifact
already in hand and all four toolchains already set up, so the marginal cost
is one step rather than a new job. No job `name:` changed — branch
protection keys required checks on those.

On its first real run the gate found a defect nobody had caught:
examples/python/uv.lock recorded chtypes 0.1.0, having missed the 0.1.1 AND
0.1.2 releases. #20 only knew about the rust lock, which had been patched by
hand. Regenerated here; all four tours now run 16/16 sections.

RELEASING.md gains the lockfile-regeneration step, and — separately — the
release order for every release after the first. It documented only the
one-time launch order, which puts Go FIRST. For a routine release Go must be
LAST: a Go module publishes by the tag existing on a public repo,
release-go.yml only verifies (confirmed: build, vet, verify-published, no
publish step), so that push is irreversible with no gate in front of it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018ckJDLjWhAAttQVrYnQEJD
…t go

Four corrections to the tracked, public orientation file, each measured
against the tree rather than read:

- It advertised `goldens/` as "the public golden set every binding runs".
  That directory does not exist (`ls: goldens: No such file or directory`),
  and the very next paragraph of the same file says the golden set is served,
  not tracked, and that there is no cases file in this repository. Replaced
  with the examples line, which is now true in CI.

- "license pending" for the core half was stale. NOTICE, docs/guides/
  artifacts.md and three of the four per-language READMEs already state
  publicly that the artifacts are Elastic License 2.0 while this repository
  is Apache 2.0, so the file now says so and points at NOTICE.

- It recorded where a private checkout lives, in a public file. Removed.

- `ci/steps/header-sync.sh --pull` is a path inside the private repository:
  a public reader cannot resolve it. The sentence says what happens instead
  of where the script is. Same for the rename date of that repository's
  sdk-suites workflow, which is not orientation for anyone here.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018ckJDLjWhAAttQVrYnQEJD
The `prose` job is markdownlint-cli2 + dprint check; `scripts/lint-prose.sh`
is what the `misspell` job runs. Passing the latter locally says nothing
about the former, which is what went red.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018ckJDLjWhAAttQVrYnQEJD
examples/go/README.md led its "Run it" section with

    go run -tags chtypes_linked .

That tag compiles go/chtypes/linked.go, whose `#cgo LDFLAGS: -lchtypes`
needs a core build tree on CGO_LDFLAGS. That tree is not public, so for
every reader outside this org the documented command fails at link time.
Measured, with the env cleared:

    ld: library 'chtypes' not found
    clang: error: linker command failed with exit code 1

while `go run .` prints 16/16 sections. Go was also the only one of the
four example READMEs that never mentioned its working command; chplay.sh
has known this all along and only adds the tag when CHTYPES_CORE_DIR or
CHTYPES_LIB_BUILD is set.

The README now leads with `go run .` and `../chplay.sh go`, and says
chplay is the tested path — CI runs exactly that, so the documented command
is now verified per pull request instead of merely written down. The cgo
bullet no longer names the private tree's internal directory; it says what
happens without it, including the link error, so a reader who tries the tag
anyway recognizes the failure.

Also: ts/CHANGELOG.md's 0.1.2 entry said the exported constant is now
`DEFAULT_MATERIALIZED`. No such identifier exists in ts/src — the export is
`Reason.DefaultMaterialized` (ts/src/transform.ts:60), camelCase like every
other member of that object. The other three bindings' equivalent claims are
correct (ReasonDefaultMaterialized, reason::DEFAULT_MATERIALIZED,
Reason.DEFAULT_MATERIALIZED). Note this entry already shipped inside npm
0.1.2; the correction reaches the registry at the next release.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018ckJDLjWhAAttQVrYnQEJD
@EricAndrechek
EricAndrechek merged commit 2ff98c1 into main Sep 11, 2026
14 checks passed
@EricAndrechek
EricAndrechek deleted the examples-in-ci branch September 11, 2026 18:39
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.

Nothing builds examples/, so the four "runnable tours" are unverified — and one lockfile silently missed a release

1 participant