From 1812d4e8ba2664052047723618cfb88723a3fe5a Mon Sep 17 00:00:00 2001 From: Kevin Tang <73975146+vt128@users.noreply.github.com> Date: Mon, 15 Jun 2026 16:09:44 +0800 Subject: [PATCH] [doc] README + CLAUDE.md: document the CI/gate toolkit The README was a 2-line stub; meta is now the ecosystem's CI hub with a reusable workflow + three gate tools. - README.md: what's here, the reusable go-ci.yml caller + full input table, the three gate tools with standalone usage, the single-module layout (one go.mod, three stdlib-only command packages, each independently runnable; selftest/ a separate fixture module), and the self-test chicken-and-egg. - CLAUDE.md (new): architecture, the module-layout rationale, go-ci.yml leg design, and the non-obvious conventions (self-test-before-repin, the @master chicken-and-egg, footprint platform-specificity, CI-only coverage). Co-Authored-By: Claude Opus 4.8 --- CLAUDE.md | 105 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ README.md | 92 +++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 195 insertions(+), 2 deletions(-) create mode 100644 CLAUDE.md diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..c5c1313 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,105 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## What this is + +`1set/meta` is the **shared CI/CD and quality-gate hub** for the entire Star\* +ecosystem. It is not a library anyone imports for runtime behavior — it is the +single source of truth every `1set/*` and `starpkg/*` module *consumes* so the +whole ecosystem stays uniform: one reusable CI workflow, one lint config, and a +trio of gate tools that enforce the three coverage standards. + +## Repository layout + +- **`.github/workflows/go-ci.yml`** — the reusable workflow (`on: workflow_call`). + Every consuming repo's `build.yml` is a thin caller pinned to a SHA here. +- **`doccov/`**, **`covcheck/`**, **`footprint/`** — three `main` command + packages, the gate tools. +- **`revive.toml`** — the shared `revive` lint config (fetched at CI time by the + Analyze step; includes the `exported` GoDoc rule and the Lizard nloc limit). +- **`selftest/`** — a fixture *module* used to exercise `go-ci.yml`. +- **`.github/workflows/selftest.yml`** — runs `go-ci.yml` on the fixture + the + tools' `go test`. + +### Module layout (important — why there's one go.mod) + +The root holds **one** module `github.com/1set/meta` (`go.mod`, go 1.19). The +three tools are command packages *under* it (`github.com/1set/meta/doccov`, +`/covcheck`, `/footprint`), each `package main`. This is deliberate: + +- **All three are standard-library only** — zero third-party deps, so the root + go.mod needs no `go.sum`, and there is nothing to isolate per tool. +- **They still build/run independently**: `go run github.com/1set/meta/@` + (and `go build .//`) compile only that command and its imports — the + other two are not touched. One module ≠ one binary. +- **Per-tool go.mod would be pure overhead** — three go.mod/go.sum to keep in + sync, and no `go test ./...` across them. The idiomatic Go layout for a + multi-command repo is many command packages under one module. +- **`selftest/` is a separate nested module on purpose** — it is the *thing being + tested* and carries its own deps (e.g. go-difflib for a non-empty go.sum); it + must not pollute the tools' module. + +## The three gate tools + +All are tiny, stdlib-only, and run from CI as `go run …@master` (like +`govulncheck`), gated behind opt-in workflow inputs. + +- **`doccov`** — AST-scans non-test `.go` for every `starlark.NewBuiltin()` + (resolving `"mod.fn"` and `ModuleName + ".fn"`), and fails if a builtin's name + isn't a backtick word in the README. Checks **omission, not accuracy**. +- **`covcheck`** — parses a `go test` coverage profile (`coverage.txt`), computes + total statement coverage (same math as `go tool cover -func`), and fails below + `-min`. The ecosystem uses it as a **ratchet**: each repo's `cov-min` sits just + below its current coverage, so coverage can only hold or rise. +- **`footprint`** — builds a baseline starlet host vs the host + + `mod.NewModule().LoadModule()`, so the module + its SDKs link, and reports the + marginal binary size (default + stripped). `-json` emits a shields.io badge; + `-max-mb` gates against bloat. + +GoDoc completeness is *not* a tool here — it is `revive`'s `exported` rule +(`revive.toml`), run in the Analyze step. Keep that division: doccov = README +surface, revive = GoDoc. + +## go-ci.yml design (the part that matters when editing) + +- Matrix: `[.x, 1.25.x] × {ubuntu-22.04, macos-14, windows-2022}`. +- Two env-flag legs: **`IS_CHECKS`** (latest Go + Linux) runs the once-only static + checks (vet/gofmt/tidy/govulncheck/doccov); **`IS_REPORT`** (floor + Linux) runs + `make ci` coverage upload + the covcheck/footprint gates (floor for comparable + footprint numbers). +- New gates are added as **opt-in inputs** (default off) so existing callers and + the core libraries are unaffected until they opt in. + +## Conventions (non-obvious, easy to get wrong) + +- **Self-test before consumers re-pin.** Any change to `go-ci.yml` or a tool must + keep `selftest.yml` green. Consumers pin a SHA; they only get a change after + re-pinning. +- **The `@master` chicken-and-egg.** The workflow runs the tools via + `go run …@master`. A *new* tool isn't on `master` until its PR merges, so its + go-ci.yml step must be gated on an input the `selftest/` fixture does **not** + set — otherwise the self-test PR runs `@master` for a tool that doesn't exist + yet and fails. Add the tool + the (default-off) input together; let real + consumers enable it after merge. +- **Footprint is platform-specific.** linux/amd64 (CI) differs from local + mac/arm64 — gum was 16.5 MB locally, 23.8 MB in CI. Ceilings and badges must use + the **CI value** (read from the PR's footprint step log), or the gate misfires. +- **Coverage is measured without the private suite.** CI has no `starpkg/test` + integration scripts, so `make ci` coverage = unit tests only; set ratchet + floors from that (locally, measure with `starpkg/test` moved aside). +- **Third-party GitHub Actions are pinned to a full commit SHA** (Codacy's + 0-new-issue gate flags unpinned actions); tools like revive/tokei are pinned to + a release tag. + +## Dev commands + +```bash +go test -race ./... # the three tools (selftest fixture is a separate module) +go vet ./... && gofmt -l . # must be clean +go run ./doccov # try a tool locally +``` + +CI/commit style follows the 1set repos (`[ci]`/`[feat]`/`[chore]`/`[doc]` +prefixes). Changes here ripple to every consumer — prefer additive, opt-in +changes and keep the self-test green. diff --git a/README.md b/README.md index 722b7d9..9931888 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,90 @@ -# meta -1set's meta configuration files 🤿 +# meta 🤿 + +The single source of truth for the **Star\*** ecosystem's shared CI/CD and +quality-gate tooling. Every `1set/*` and `starpkg/*` Go module consumes this +repo so the whole ecosystem stays uniform — one place to fix the pipeline, one +place that defines the standards. + +## What's here + +| Path | What it is | +|------|------------| +| [`.github/workflows/go-ci.yml`](.github/workflows/go-ci.yml) | the **reusable CI workflow** every module calls | +| [`doccov/`](doccov/) | **doc-coverage** gate — every script builtin is documented in the README | +| [`covcheck/`](covcheck/) | **test-coverage** gate — total coverage may not drop below a floor (ratchet) | +| [`footprint/`](footprint/) | **binary-footprint** gate + badge — the marginal binary size a module adds | +| [`revive.toml`](revive.toml) | the shared `revive` lint config (incl. the `exported` GoDoc rule) | +| `selftest/`, `.github/workflows/selftest.yml` | proves `go-ci.yml` + the tools end-to-end inside meta | + +`doccov`, `covcheck`, and `footprint` are three `main` command packages under the +**single module `github.com/1set/meta`** (one root `go.mod`, go 1.19, +**standard-library only — no go.sum**). Each builds and runs independently: +`go run github.com/1set/meta/@` compiles just that command. (The +`selftest/` fixture is a separate nested module on purpose — it has its own +deps.) + +## Reusable CI workflow + +A consuming repo's `.github/workflows/build.yml` is a thin caller: + +```yaml +name: Build +on: + push: { branches: ["master"] } + pull_request: { branches: ["master"] } +permissions: read-all +jobs: + ci: + uses: 1set/meta/.github/workflows/go-ci.yml@ + with: + go-floor: "1.19" # this repo's go.mod floor minor version + # doc-coverage: true # opt in to the doccov gate + # cov-min: 78 # test-coverage ratchet floor (0 = no gate) + # footprint: true # measure & badge the binary footprint + # footprint-max-mb: 7 # fail if the stripped footprint delta exceeds this + secrets: inherit +``` + +It runs the matrix `[.x, 1.25.x] × {ubuntu-22.04, macos-14, +windows-2022}`. Static checks (vet, gofmt, `go mod tidy`, govulncheck, doccov) +run once on the latest-Go Linux leg; coverage upload + the covcheck/footprint +gates run on the floor Linux leg. + +### Inputs + +| Input | Type | Default | Meaning | +|-------|------|---------|---------| +| `go-floor` | string | (required) | the repo's go.mod floor minor, e.g. `"1.19"` / `"1.22"` | +| `working-directory` | string | `"."` | path to the Go module within the repo | +| `doc-coverage` | bool | `false` | run the **doccov** README↔builtin gate | +| `cov-min` | number | `0` | **covcheck** test-coverage floor (`0` = no gate) | +| `footprint` | bool | `false` | run **footprint** (badge + bloat gate) | +| `footprint-max-mb` | number | `0` | fail if the stripped footprint delta exceeds this many MB | + +Pin the `@` for supply-chain safety; bump it when this workflow changes. + +## Gate tools + +Each tool also runs standalone for local checks (see its README): + +```bash +go run github.com/1set/meta/doccov@master . # docs ↔ builtins +go run github.com/1set/meta/covcheck@master -min 70 coverage.txt # test coverage floor +go run github.com/1set/meta/footprint@master -modpath github.com/starpkg/sqlite -dir . # binary size +``` + +- **doccov** ([README](doccov/README.md)) — AST-scans every `starlark.NewBuiltin(...)` and fails if it isn't documented (backtick) in the README. +- **covcheck** ([README](covcheck/README.md)) — parses the `make ci` coverage profile and fails below `-min`. Policy is a **ratchet**: each repo's floor sits just below its current coverage, so it can only hold or improve. +- **footprint** ([README](footprint/README.md)) — builds a bare starlet host vs the host + module and reports the marginal binary size (default + stripped); emits a shields.io badge and gates against silent bloat. Numbers are platform-specific — use the CI (linux/amd64) value. + +GoDoc completeness (a doc comment on every exported symbol) is enforced by +`revive`'s `exported` rule from `revive.toml`, in the workflow's Analyze step. + +## Self-test + +`selftest.yml` calls `go-ci.yml` against the `selftest/` fixture (so any change +to the workflow is proven before consumers re-pin) and runs `go test ./...` over +the gate tools. Note the **chicken-and-egg**: a new tool isn't on `master` until +its PR merges, so don't enable its `go-ci.yml` input in the fixture in the same +PR — keep new tool inputs opt-in (default off) and let consumers turn them on +after the merge.