registrystack / registrystack/registry-stack

A docs content change between recording an archive lock and publishing it breaks the candidate, and CI cannot see it

Open
#808 1 comment 0 reactions 0 assignees View on GitHub
area:docs area:release bug criticality:p2 github_actions needs-jeremi-decision
Dominant language
Rust
Stars
2
Forks
0
Avg merge
2h 55m
Merged PRs (30d)
130

Description

## What happened

The v0.24.0 release PR recorded the immutable archive digests for the new
docset in `docs/site/src/data/archive-lock.yaml`. #799 then merged, changing
`docs/site/src/content/**` before the candidate was dispatched. The candidate
failed at `archive:snapshot --verify-lock`, because the built docset no longer
matched the lock.

There is no supported repair once the entry exists:
`assertArchiveLockImmutable` rejects a change to an existing entry,
`addArchiveLockEntry` throws `already exists`, and `isLockBackedDocset` has no
carve-out for `availability: candidate`. The release had to revert #799
(`d1a6c7b92`), publish, and re-land it (#806).

## Why CI did not catch it

The `docs-archives` job runs `check:archives`, which is the gate that would have
failed. But `needs.changes.outputs.docs_archives` is computed in
`.github/scripts/ci_changes.py` from an exact allow-list: `ci.yml`,
`astro.config.mjs`, `package.json`, `package-lock.json`, a fixed set of
`docs/site/scripts/*.mjs`, and `src/data/{archive-lock,docsets,repo-docs}.yaml`.

A pure prose change matches none of them, so the job skips. That is visible on
#806 right now: `Immutable docs archives: skipping`.

The comment above the filter explains the intent, and the intent is sound for
the steady state: "Publication workflows and this classifier do not alter
archived bytes; their focused tests cover those contracts without replaying
every historical docset."

## The gap is a window, not a permanent hole

The assumption behind the filter, that content changes cannot move archived
bytes, holds once a docset is published, because `assemble-archives.mjs`
restores a published bundle rather than rebuilding it. Note that the pinned
source tag does **not** provide this: `currentSourceGeneratedArtifacts` binds
only `docs/site/src/content/docs/reference/cli` and
`docs/site/src/data/generated/cli-reference.json` to the tag. Prose is built from
the checked-out tree.

So the assumption is false for exactly one window: between the commit that
records a lock entry and the publication of that docset's bundle. In that
window any `docs/site/src/content/**` change silently breaks the candidate, and
CI stays green.

## Possible fixes

Not proposing a specific one, since this is a design call:

1. Make `docs_archives` true when `docs/site/src/content/**` changes **and** the
lock contains an entry whose bundle is not yet published. Narrow, but needs
the classifier to know publication state.
2. Add a cheap standalone check, not the full `check:archives` replay, that fails
a PR touching `docs/site/src/content/**` while an unpublished lock entry
exists.
3. Leave the classifier alone and encode the ordering rule in
`release/OPERATIONS.md`: merge the release PR last, dispatch the candidate
immediately, and freeze `docs/site/src/content/**` until the release
publishes.

Option 3 alone is what the process relies on today, and it is unwritten.

Contributor guide

Open the contributing guide

Research direction

Start with .github/scripts/ci_changes.py and the docs archive checks, then read the archive-lock handling and relevant focused tests. Compare the three proposed approaches and inspect release/OPERATIONS.md for the current ordering assumptions. Done means the selected policy is documented and covered by a regression check for content changes during the unpublished-lock window.

Written by the indexing model from the issue text.

Assessment

Tech stack
javascript, python
Domain
ci-cd, documentation, release
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Needs clarification
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.