diff --git a/AGENTS.md b/AGENTS.md index cd1f567..10eb8a3 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -207,6 +207,18 @@ the tool is not installed, with a one-line install hint. CI runs them unconditionally. Any failure means the ticket is not done. Fix it, do not bypass. +### Vendored assets + +A few workspace-root files (`schemas/v1.json`, `schemas/pipe/v0.json`, +`pricing.yaml`, the agent-skill markdown) are embedded into publishable crates +with `include_str!`, and `cargo publish` only packages files inside a crate +directory, so each is vendored as a byte-identical in-crate copy (for example +`schemas/v1.json` has copies under both `crates/mcptest-config/` and +`crates/mcptest/`). After editing one of these canonical files, run **`make +sync-vendored`** to propagate it to every vendored copy in one step, then commit +the copies alongside the source. `make vendored-check` (also part of the check +gate) fails on any drift; the pair list lives in `scripts/check-vendored-assets.sh`. + ### cargo-nextest The test step uses `cargo-nextest` when it is installed (`cargo install diff --git a/Makefile b/Makefile index e51b5b0..22d92a9 100644 --- a/Makefile +++ b/Makefile @@ -6,7 +6,7 @@ # the two cannot drift. Run `make` or `make help` to list targets. .DEFAULT_GOAL := help -.PHONY: help check fmt fmt-check lint doc build test module-size stats clean +.PHONY: help check fmt fmt-check lint doc build test module-size sync-vendored vendored-check stats clean help: ## List the available targets @grep -E '^[a-zA-Z_-]+:.*## ' $(MAKEFILE_LIST) | sort \ @@ -36,6 +36,12 @@ test: ## Run the workspace test suite module-size: ## Enforce the production module-size guard ./scripts/check-module-size.sh +sync-vendored: ## Copy each canonical asset (schemas, pricing, skill) over its vendored crate copies + ./scripts/check-vendored-assets.sh --fix + +vendored-check: ## Fail if a vendored in-crate copy drifted from its canonical source (CI gate) + ./scripts/check-vendored-assets.sh + stats: ## Report adoption from public registries (no in-binary telemetry) ./scripts/usage-stats.sh diff --git a/scripts/check-vendored-assets.sh b/scripts/check-vendored-assets.sh index f98ea60..e7792a7 100755 --- a/scripts/check-vendored-assets.sh +++ b/scripts/check-vendored-assets.sh @@ -4,17 +4,34 @@ # Some publishable crates embed workspace-root files (the JSON Schemas and the # pricing table) with `include_str!`. `cargo publish` only packages files that # live inside the crate directory, so each of those files is vendored as an -# in-crate copy. This check fails if a vendored copy drifts from its canonical -# source, so the embedded copy and the source of truth never diverge. +# in-crate copy. This script keeps the embedded copies byte-identical to their +# canonical source so the two never diverge. # -# Canonical source -> vendored copy pairs are listed in PAIRS below. When you -# edit a canonical file, copy it over its vendored sibling(s) in the same -# commit (or run this script to find the drift). +# Two modes, one PAIRS list (the single source of truth for what mirrors what): +# +# check-vendored-assets.sh # CHECK: fail if any vendored copy drifted +# # (the CI gate; the default) +# check-vendored-assets.sh --fix # SYNC: copy each canonical file over its +# # vendored sibling(s) +# +# Workflow: edit a canonical file, then run `make sync-vendored` (or this script +# with `--fix`) to propagate it to every vendored copy in one step. The no-arg +# check then gates the commit and CI against any remaining drift. set -euo pipefail ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" cd "$ROOT" +FIX=0 +case "${1:-}" in + --fix) FIX=1 ;; + "") ;; + *) + printf "usage: %s [--fix]\n" "$(basename "$0")" >&2 + exit 2 + ;; +esac + # "canonical|vendored" pairs. PAIRS=( "schemas/v1.json|crates/mcptest-config/schemas/v1.json" @@ -26,6 +43,7 @@ PAIRS=( ) drift=0 +synced=0 for pair in "${PAIRS[@]}"; do canonical="${pair%%|*}" vendored="${pair##*|}" @@ -34,18 +52,34 @@ for pair in "${PAIRS[@]}"; do drift=1 continue fi - if [[ ! -f "$vendored" ]]; then - printf "error: vendored copy missing: %s (copy %s there)\n" "$vendored" "$canonical" >&2 - drift=1 + if [[ -f "$vendored" ]] && cmp -s "$canonical" "$vendored"; then continue fi - if ! cmp -s "$canonical" "$vendored"; then - printf "error: vendored asset out of sync:\n %s\n differs from %s\n fix: cp %s %s\n" \ - "$vendored" "$canonical" "$canonical" "$vendored" >&2 - drift=1 + if [[ "$FIX" -eq 1 ]]; then + mkdir -p "$(dirname "$vendored")" + cp "$canonical" "$vendored" + printf "synced %s -> %s\n" "$canonical" "$vendored" + synced=$((synced + 1)) + continue + fi + if [[ ! -f "$vendored" ]]; then + printf "error: vendored copy missing: %s (run \`make sync-vendored\`)\n" "$vendored" >&2 + else + printf "error: vendored asset out of sync:\n %s\n differs from %s\n fix: run \`make sync-vendored\`\n" \ + "$vendored" "$canonical" >&2 fi + drift=1 done +if [[ "$FIX" -eq 1 ]]; then + if [[ "$synced" -eq 0 ]]; then + printf "vendored assets already in sync; nothing to do.\n" + else + printf "synced %d vendored asset(s); review and commit the copies.\n" "$synced" + fi + exit 0 +fi + if [[ "$drift" -ne 0 ]]; then exit 1 fi