actions/* + lib/* + CHANGELOG — merge upstream 0.6.0 onto the forge tree, and port every gh call site it brought (#198) #204

Merged
andres merged 211 commits from build/198-upstream-0.6.0 into main 2026-08-05 13:10:55 +00:00
2 changed files with 45 additions and 0 deletions
Showing only changes of commit 7909383ca0 - Show all commits

14
changelog.d/251.md Normal file
View file

@ -0,0 +1,14 @@
### Added
- CI now refuses a root `*.md` declared in neither `docs/VENDORED.txt` nor the
guard's short exemption list, so a new doctrine file can no longer reach a
tag undeclared and stay invisible to every consumer's `docs-sync` (#251).
- The same guard reads the manifest the other way: every entry must resolve to
a regular, non-empty, tracked file — no symlink, no directory, no `../`
escape (#251).
### Changed
- Consumer guidance: re-vendor tooling reads the pin's `docs/VENDORED.txt`,
never a hardcoded list, so a new doctrine file propagates at the next
ordinary pin bump with zero list edits (#251).

View file

@ -598,6 +598,37 @@ It is **unreleased** (#248) until that tag exists: consumers add
`.ceremony/RELEASES.md` only with the ordinary pin bump and re-sync, never by `.ceremony/RELEASES.md` only with the ordinary pin bump and re-sync, never by
copying it ahead of their pinned doctrine set. copying it ahead of their pinned doctrine set.
### Read the manifest, never a copy of it
Anything on the consumer's side that needs to know *which* documents are
vendored — a re-vendor script, a `docs-sync` equivalent, the task list of a
conversion issue — reads **the pin's `docs/VENDORED.txt`** and never names
the files itself. The manifest is available at the pinned ref from `0.5.0`
and later (ceremony#251); it is one path per line, relative to ceremony's
root, and blank lines are ignored:
```sh
# the vendored doc set at the ref this repo is pinned to
curl -fsSL "https://raw.githubusercontent.com/heavy-duty/ceremony/<pinned-tag>/docs/VENDORED.txt"
```
That is the whole benefit: a doctrine file added in ceremony — `RELEASES.md`
was the last, ceremony#248 — reaches every consumer at its next **ordinary
pin bump**, with **zero list edits** anywhere. A hardcoded list propagates
nothing, and its staleness is silent rather than red: `docs-sync --check`
asserts byte-identity for the files the list names and says nothing at all
about one it omits, so a consumer keeps a green guard while governing
itself with doctrine it no longer has.
What makes reading the manifest *sufficient* — rather than merely better
than a copy — is that ceremony's CI now refuses a root doctrine file that is
declared in neither the manifest nor a short in-script exemption list
(`.github/scripts/vendored-check.sh`), so the manifest at a tag is the
complete set as of that tag. That guarantee is **unreleased** (#251) until
the first tag carrying it exists; the manifest is worth reading at every
earlier pin regardless, since it is what `actions/docs-sync` has always
mirrored.
The consumer's ci.yml gains the guard alongside the others: The consumer's ci.yml gains the guard alongside the others:
```yaml ```yaml