Skip to content

Commit 86c4e00

Browse files
pungoyalclaude
andcommitted
ci(docs): guard a manual deploy against the published CLI
Deploying on the release tag stopped the site drifting ahead of npm, but left one way back in: `workflow_dispatch` from main publishes main's docs, unreleased flags included. That is the drift this workflow exists to prevent, reachable by one button. So check it instead of trusting the operator. On a dispatch from a branch, the job installs the published CLI, regenerates the command reference from its `--help` via KITE_DOCS_CLI, and fails if the checked-in reference differs. A prose fix still goes out; a reference documenting flags nobody can install does not. Dispatching from a `v*` tag skips the check — CI already proved the reference matches that tag's source — and CONTRIBUTING now names that as the way to republish. Verified locally: the check fails against the published 0.7.0 (whose --help predates the per-command examples) and passes against dist/. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 83c914a commit 86c4e00

4 files changed

Lines changed: 44 additions & 5 deletions

File tree

.github/workflows/docs.yml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,21 @@ jobs:
6969
run: npm run build
7070
working-directory: docs
7171

72+
# A manual deploy from a branch is the one path that can publish a command
73+
# reference the released package does not match — the drift this workflow
74+
# exists to prevent, reachable by one button. So check it rather than trust
75+
# the operator: install the published CLI, regenerate the reference from
76+
# *its* `--help`, and fail if what would be deployed differs. Dispatching
77+
# from a `v*` tag needs no check — CI already proved the reference matches
78+
# that tag's source.
79+
- name: Verify the command reference matches the published CLI
80+
if: github.event_name == 'workflow_dispatch' && !startsWith(github.ref, 'refs/tags/v')
81+
run: |
82+
npm ci --ignore-scripts
83+
npm install --prefix "$RUNNER_TEMP/published" --no-save --ignore-scripts @pungoyal/kite-cli@latest
84+
KITE_DOCS_CLI="$RUNNER_TEMP/published/node_modules/@pungoyal/kite-cli/dist/cli.js" \
85+
node scripts/generate-command-reference.mjs --check
86+
7287
# Pages plumbing is only meaningful on a real deployment — a tag push or a
7388
# manual dispatch. A PR or a plain push to main stops at the build above.
7489
- uses: actions/configure-pages@45bfe0192ca1faeb007ade9deae92b16b8254a0d # v6.0.0

CHANGELOG.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,12 @@ While the version is `0.x`, minor releases may contain breaking changes.
4444
forwards instead of backwards. The site and the npm package now move together
4545
on the `v*` tag; pull requests and `main` still build the site as a
4646
dead-link gate, and a documentation fix can be published between releases by
47-
running the workflow manually.
47+
dispatching the workflow from the release tag.
48+
49+
Dispatching from `main` instead is guarded rather than forbidden: the job
50+
installs the published CLI, regenerates the command reference from *its*
51+
`--help`, and refuses to deploy if the checked-in reference differs. Prose
52+
fixes go out; unreleased flags cannot ride along.
4853

4954
- **The README is an introduction again, not a second copy of the reference.**
5055
It had grown a full config-key table, the multi-account walkthrough and

CONTRIBUTING.md

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,8 +73,19 @@ The `Docs` workflow builds the site on every pull request and every push to
7373
but **deploys only on a `v*` release tag**. The published site therefore matches
7474
the published package: `docs/commands.md` is generated from `--help`, so
7575
deploying from `main` would advertise flags that `npm i -g @pungoyal/kite-cli`
76-
does not yet ship. To publish a documentation fix between releases, run the
77-
workflow by hand (**Actions → Docs → Run workflow**, from `main`).
76+
does not yet ship.
77+
78+
To republish the site between releases, dispatch the workflow **from the release
79+
tag**, which carries exactly what was published:
80+
81+
```bash
82+
gh workflow run Docs --ref v0.7.0
83+
```
84+
85+
Dispatching from `main` is allowed but guarded: the job installs the published
86+
CLI, regenerates the command reference from *its* `--help`, and fails if the
87+
checked-in reference differs — so a prose fix goes out fine, while unreleased
88+
flags cannot ride along.
7889

7990
Links from a docs page to source files or README sections use absolute
8091
`github.com` URLs (they live outside the site); links between docs pages stay as

scripts/generate-command-reference.mjs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,11 @@ import stripAnsi from 'strip-ansi';
2222
const execFileAsync = promisify(execFile);
2323

2424
const root = join(dirname(fileURLToPath(import.meta.url)), '..');
25-
const cli = join(root, 'dist', 'cli.js');
25+
// Normally the freshly built CLI in dist/. `KITE_DOCS_CLI` points it at another
26+
// binary — the docs deploy uses it to check the checked-in reference against the
27+
// *published* package, so a manual deploy cannot put flags on the site that the
28+
// released CLI does not have.
29+
const cli = process.env.KITE_DOCS_CLI ?? join(root, 'dist', 'cli.js');
2630
const outFile = join(root, 'docs', 'commands.md');
2731

2832
const env = {
@@ -137,7 +141,11 @@ async function main() {
137141
existing = null;
138142
}
139143
if (existing !== content) {
140-
console.error(`docs/commands.md is out of date. Run \`npm run docs:commands\` and commit the result.`);
144+
console.error(
145+
process.env.KITE_DOCS_CLI
146+
? `docs/commands.md does not match the help printed by ${cli}.`
147+
: 'docs/commands.md is out of date. Run `npm run docs:commands` and commit the result.',
148+
);
141149
process.exit(1);
142150
}
143151
console.log('docs/commands.md is up to date.');

0 commit comments

Comments
 (0)