Noyalib ci and release
Skill sebastienrousseau/agtmls/skills/noyalib-ci-and-release
Operate noyalib CI and ship releases: workflow graph, cache-poisoning doctrine, supply-chain gates, tag-driven release flow. Use for red CI, release prep, tagging, cargo-vet or cargo-deny failures. Not which-gates-apply (noyalib-change-control).From its SKILL.md
npx -y skills add sebastienrousseau/agtmls --skill noyalib-ci-and-releaseAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 1 stars1 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its file declares
Copied from the file, not written here
The file declares its own license as MIT. That is the author’s claim about this one file, and it is not the same thing as the license GitHub reports for the repository, which is listed with the other numbers below.
SKILL.md
11.8 KB, as published. Nobody here has run it
noyalib — CI and release runbook
See also
reference.mdfor the full workflow inventory (25 files), the exhaustiveci.ymljob list, theshared-no-std.ymlverbatim triad, the deep per-tool supply-chain detail, theghcheat-sheet, the satellite lockstep matrix, and the caller-permissions table. This file keeps the doctrine and the compact runbook; reference.md holds the inventory.
Repo: github.com/sebastienrousseau/noyalib — pure-Rust YAML 1.2
library, #![forbid(unsafe_code)], single-crate workspace after ADR-0005
splits (noyalib-wasm at v0.0.12, noyalib-mcp at v0.0.13, noyalib-lsp
noya-cliat v0.0.14+ per RELEASE-NOTES-v0.0.13.md). Current release branch:feat/v0.0.14. Ground truth:.github/workflows/*,Makefile,supply-chain/config.toml,deny.toml,RELEASE-NOTES-v0.0.13.md,RELEASE-NOTES-v0.0.14.md,doc/adr/0005-workspace-split.md. If this skill and those files disagree, the files win — re-verify with the commands in "Provenance and maintenance" at the bottom.
Jargon (used everywhere below):
- Orchestrator —
.github/workflows/ci.ymlon push / PR / nightly. - Shared workflow — a
.github/workflows/shared-*.ymlfile with aworkflow_call:trigger; consumed by the orchestrator viauses: ./.github/workflows/shared-*.ymland by satellite repos viauses: sebastienrousseau/noyalib/.github/workflows/shared-*.yml@<sha>. - Compile surface — the tuple
(toolchain, features, target, RUSTFLAGS/RUSTDOCFLAGS, cfg gates, sanitiser). Two jobs that share a compile surface can share a target/; jobs that differ MUST NOT. - Satellite — a downstream repo that publishes a
noyalib-*crate at exact-match=X.Y.Zin lockstep withnoyalib. Post-split:noyalib-wasm,noyalib-mcp,noyalib-lsp,noya-cli.
1. Workflow graph (at a glance)
Under .github/workflows/ there are 8 non-shared workflows + 17
shared-* reusables = 25 total (verified 2026-07-08). The
orchestrator ci.yml wires 19+ jobs — the local shared-* reusables,
one external rust-ci.yml reusable, and two inline jobs
(cargo-semver-checks, lossless-u64-matrix).
Full inventory + per-workflow purpose + ci.yml job list are in
reference.md §A/§B. Re-derive locally with:
ls .github/workflows/
grep -E '^ [a-z-]+:$' .github/workflows/ci.yml
Concurrency on ci.yml: ${{ github.workflow }}-${{ github.ref }}
with cancel-in-progress: true.
2. THE cache-poisoning doctrine (v0.0.9-v0.0.11 lesson)
The one commandment:
A green check is only trustworthy if its fingerprint cannot be satisfied by another compile-surface's artefacts.
Concretely: any job that compiles with a distinct feature set, distinct
target, distinct sanitiser, distinct MIRIFLAGS, distinct
RUSTDOCFLAGS, or a distinct --cfg — i.e. anything the Swatinem
cache key does not already discriminate — MUST set its own
CARGO_TARGET_DIR AND its own Swatinem workspaces/key. Belt and
braces: the CARGO_TARGET_DIR is the real guarantee; the cache key
prevents cross-restore on cold runners.
How the incident manifested (v0.0.9 and v0.0.10): the no_std leg
shared the default target/ with std-on jobs. cargo check --no-default-features on a warm Swatinem restore would find pre-built
artefacts from an earlier std-on job and short-circuit — silently
returning success while crate::prelude::Vec / the missing vec
import in doc_boundary.rs and the unused crate::span_context import
in de.rs remained broken. Two releases shipped with a broken no_std
surface before the v0.0.11 CI-integrity cut.
Canonical exemplar — shared-no-std.yml's env/workspaces/key triad
is quoted verbatim in reference.md §C. The three isolating knobs are:
env.CARGO_TARGET_DIRmoves the artefact dir offtarget/.workspaces: ". -> target-no-std"points Swatinem at that dir.key: no-stdsplits the cache namespace so cross-restore can't happen.
Every job compiling a distinct surface follows the pattern. Full
list of isolated dirs in reference.md §C. Verify with:
grep -rn "CARGO_TARGET_DIR" .github/workflows/ | head
When you add a new job, the check is: does it compile something with inputs the default cache key can't tell apart from an existing job? If yes, isolate. If in doubt, isolate — the cost is a cold rebuild, the cost of a false green is a shipped bug (see v0.0.9 / v0.0.10).
3. Reading CI failures fast (triage)
Baseline loop (full gh cheat-sheet in reference.md §D):
gh pr checks <PR-number>
gh run list --branch feat/v0.0.14 --workflow ci.yml
gh run view --job <job-id>
The three most-common failure classes on this repo — check these first before deep-diving:
- rustfmt drift after hand-edits.
cargo fmtbefore pushing; the externalcireusable runscargo fmt --checkand refuses on any drift.make fmtlocally. - clippy lints on a new nightly toolchain (recent culprit:
byte_char_slicespromotion). Address the lint or gate with#[allow(clippy::<lint>)]under the specific#[cfg]— never blanket-Aat the crate level. - cargo-deny advisory landing mid-PR. RustSec published a new
entry between PR open and now.
cargo update -p <crate>to a fixed version; if none exists, add a narrow[advisories.ignore]entry indeny.tomlwith a comment (advisory ID, why tolerated, revisit trigger) — and mirror toosv-scanner.toml(§4).
Full failure-class catalogue including the cache-poisoning shape and
the CI-duration-monitor firing is in reference.md §D.
4. Supply-chain gates (compact)
The stack, all enforced on PR: cargo-vet, cargo-deny,
cargo-machete, cargo-semver-checks, REUSE, Dependency Review,
CodeQL (languages: actions), OpenSSF Scorecard.
The two rules that bite most often:
- cargo-deny ↔ osv-scanner mirror rule. Any
[advisories.ignore]entry indeny.tomlMUST also land inosv-scanner.toml— OSV runs a separate code path and would otherwise flag it. Diff the two ignore lists after any change. cargo vet fmtstrips comments fromsupply-chain/config.toml. Rationale for exemptions/trust entries goes in the commit message, not inline in the file.
Full per-tool detail (feed list, publisher scoping, semver-check
short-circuit, REUSE.toml aggregation, Scorecard's Code-Review
mechanism) in reference.md §E.
5. Release flow (compact 9-step)
Doctrine before mechanics:
- Security > velocity. A red security scan (Scorecard, cargo-deny advisory, CodeQL alert, cosign-verify) always trumps the release schedule. CI integrity IS a security control. Do not tag with a known-red gate; do not merge a workaround that dodges the gate for "release-day expedience".
- Don't pre-emptively phase. If the user framed this release as
category-defining, fix the security / correctness / MSRV /
version-refs stragglers in THIS release rather than deferring to
v0.0.(Z+1). Splitting a bang launch across two tags costs credibility that a slightly-later tag does not.
The nine steps, in order — do not skip:
- Version bump —
crates/noyalib/Cargo.tomlversion = "X.Y.Z". - CHANGELOG — new
## [vX.Y.Z] - YYYY-MM-DDunder## [Unreleased], Keep-a-Changelog groupings, reset[Unreleased]. - RELEASE-NOTES-vX.Y.Z.md — headline + why + what changed + what did not change + follow-ups (see v0.0.13/v0.0.14 as templates).
- Version-refs audit — grep the old version across README,
MIGRATION.md, GETTING_STARTED.md,
doc/USER-GUIDE.md, Cargo.toml, CHANGELOG,pkg/,benches/,examples/. Fix all stragglers. - PR against
mainwith Conventional-Commits title (release:orchore(release):); wait for all CI green. - Squash-merge via
gh pr merge --squash --admin(mainis protected; direct pushes refused). - Tag and push —
git tag -s "vX.Y.Z" -m "noyalib vX.Y.Z" && git push origin vX.Y.Z. release.ymltriggers on the tag: validate → artifacts (SLSA L3 + cosign keyless) → cross-verify matrix → github-release → crates-io publish.- Satellite lockstep — each satellite tags
vX.Y.Zin its own repo; all pinnoyalib = "=X.Y.Z".
Full per-step detail (release.yml job order, cosign bundle layout,
per-satellite prereq matrix incl. CARGO_REGISTRY_TOKEN and npm
Trusted Publisher requirements) in reference.md §F.
6. Shared-workflow caller-permissions trap (one-paragraph doctrine)
When a satellite consumes a shared workflow whose callee declares a
permissions: scope the caller does not, GitHub Actions rejects the
whole workflow with a startup_failure — 0 jobs scheduled, no
annotation, no diagnostic in the workflow tab. The symptom is "the
check just doesn't run." The rule: the caller's permissions: block
MUST be the union of every callee's declared permissions:. The
parent ci.yml sits at permissions: read-all and never hits this;
satellites narrow to per-workflow minimums. shared-verify-signatures.yml
is the standalone case — needs pull-requests: read on top of
contents: read because it hits gh api repos/.../pulls/N/commits.
Full caller-permissions matrix and rollout procedure in
reference.md §G.
7. When NOT to use this skill
- Deciding whether a change belongs in this release, what its risk
class is, whether it needs an ADR, whether it's
[Fixed]vs[Changed]in the CHANGELOG →noyalib-change-control. - Local toolchain / MSRV / build env setup, why
cargo +nightlyis required for coverage, how to run Miri locally →noyalib-build-and-env. - Debugging parser / loader / CST correctness at the code level →
noyalib-debugging-playbook. - Editing README / MIGRATION / USER-GUIDE / RELEASE-NOTES prose →
noyalib-docs-and-writing.
This skill is the runbook for the workflow files under
.github/workflows/ and the shape of a release. It does not decide
what should be in a release or how the code inside should behave.
Provenance and maintenance
Volatile facts date-stamped 2026-07-08 against noyalib v0.0.14 on
branch feat/v0.0.14. To re-verify before trusting anything in this
skill:
# The full workflow list this skill describes.
ls .github/workflows/
# The cache-poisoning-guard footprint. Every match should either be
# an env var setting or a documented reason for the pattern.
grep -rn "CARGO_TARGET_DIR" .github/workflows/ | head
# Jobs wired into the orchestrator (compare to reference.md §B).
grep -E '^ [a-z-]+:$' .github/workflows/ci.yml
# The 7 trusted audit feeds cargo-vet imports.
grep -E '^\[imports\.' supply-chain/config.toml
# The advisories that cargo-deny ignores + mirror to osv-scanner.
grep -A2 '^\[advisories\]' deny.toml
grep -B1 -A2 '^ignore' osv-scanner.toml 2>/dev/null
# The release-note templates to model the next one on.
ls RELEASE-NOTES-v0.0.*.md
If any of the workflow names, isolated-target-dir names, permission
tables, or release-flow steps drift from what these commands surface,
the files win — update this skill (and reference.md).