Skip to content

Commit fdf1b3f

Browse files
authored
Merge pull request #341 from ndycode/audit/pr5-release-docs-safety
align stable release docs with 1.2.2
2 parents 7d7fcff + 1044774 commit fdf1b3f

4 files changed

Lines changed: 111 additions & 43 deletions

File tree

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -308,9 +308,9 @@ codex auth doctor --json
308308

309309
## Release Notes
310310

311-
- Current stable: [docs/releases/v1.1.10.md](docs/releases/v1.1.10.md)
312-
- Previous stable: [docs/releases/v0.1.9.md](docs/releases/v0.1.9.md)
313-
- Earlier stable: [docs/releases/v0.1.8.md](docs/releases/v0.1.8.md)
311+
- Current stable: [docs/releases/v1.2.2.md](docs/releases/v1.2.2.md)
312+
- Previous stable: [docs/releases/v1.2.1.md](docs/releases/v1.2.1.md)
313+
- Earlier stable: [docs/releases/v1.2.0.md](docs/releases/v1.2.0.md)
314314
- Archived prerelease: [docs/releases/v0.1.0-beta.0.md](docs/releases/v0.1.0-beta.0.md)
315315

316316
## License

docs/README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,9 @@ Public documentation for `codex-multi-auth`.
2323
| [configuration.md](configuration.md) | Stable defaults, precedence, and environment overrides |
2424
| [architecture.md](architecture.md) | Public system overview of the wrapper, storage, and optional plugin runtime |
2525
| [privacy.md](privacy.md) | Data handling and local storage behavior |
26-
| [releases/v1.1.10.md](releases/v1.1.10.md) | Stable release notes |
27-
| [releases/v0.1.9.md](releases/v0.1.9.md) | Previous stable release notes |
28-
| [releases/v0.1.8.md](releases/v0.1.8.md) | Earlier stable release notes |
26+
| [releases/v1.2.2.md](releases/v1.2.2.md) | Stable release notes |
27+
| [releases/v1.2.1.md](releases/v1.2.1.md) | Previous stable release notes |
28+
| [releases/v1.2.0.md](releases/v1.2.0.md) | Earlier stable release notes |
2929
| [releases/v0.1.7.md](releases/v0.1.7.md) | Archived stable release notes |
3030
| [releases/v0.1.6.md](releases/v0.1.6.md) | Archived stable release notes |
3131
| [releases/v0.1.5.md](releases/v0.1.5.md) | Archived stable release notes |
@@ -51,7 +51,7 @@ Public documentation for `codex-multi-auth`.
5151
| [reference/storage-paths.md](reference/storage-paths.md) | Canonical and compatibility storage paths |
5252
| [reference/public-api.md](reference/public-api.md) | Public API stability and semver contract |
5353
| [reference/error-contracts.md](reference/error-contracts.md) | CLI, JSON, and helper error semantics |
54-
| [releases/v1.1.10.md](releases/v1.1.10.md) | Current stable release notes |
54+
| [releases/v1.2.2.md](releases/v1.2.2.md) | Current stable release notes |
5555
| [releases/v0.1.0-beta.0.md](releases/v0.1.0-beta.0.md) | Archived prerelease reference |
5656
| [Daily Use release notes](#daily-use) | Stable, previous, and archived release notes |
5757
| [releases/legacy-pre-0.1-history.md](releases/legacy-pre-0.1-history.md) | Archived pre-0.1 changelog history |

docs/releases/v1.2.2.md

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# Release v1.2.2
2+
3+
Release line: `stable`
4+
5+
This document anchors the current stable release reference used by the docs portal.
6+
7+
## Scope
8+
9+
- Current package version in `package.json` is `1.2.2`.
10+
- Canonical command family remains `codex auth ...`.
11+
- Canonical package name remains `codex-multi-auth`.
12+
- Keeps the docs portal and root README aligned with the currently published package version.
13+
14+
## What Changed
15+
16+
- aligned the root README and docs portal release links to the published `v1.2.2` stable line
17+
- added a dedicated `docs/releases/v1.2.2.md` entry so the current stable docs target exists as a first-class release note
18+
- updated the documentation integrity test to derive the current stable release note from `package.json` while keeping the previous and earlier stable slots explicit
19+
20+
## Why This Exists
21+
22+
- prevents the docs portal from pointing at retired stable release pages after version bumps
23+
- gives maintainers one stable note to refresh when the package version advances again
24+
- keeps release discoverability consistent between the README, docs portal, and test suite
25+
26+
## Related
27+
28+
- [../getting-started.md](../getting-started.md)
29+
- [../upgrade.md](../upgrade.md)
30+
- [../reference/commands.md](../reference/commands.md)
31+
- [../reference/public-api.md](../reference/public-api.md)

test/documentation.test.ts

Lines changed: 73 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -9,40 +9,65 @@ import {
99
} from "node:fs";
1010
import { tmpdir } from "node:os";
1111
import { dirname, join, resolve } from "node:path";
12-
import { describe, expect, it, vi } from "vitest";
12+
import { beforeAll, describe, expect, it, vi } from "vitest";
1313
import { UI_COPY } from "../lib/ui/copy.js";
1414

1515
const projectRoot = resolve(process.cwd());
1616

17-
const userDocs = [
18-
"docs/index.md",
19-
"docs/README.md",
20-
"docs/getting-started.md",
21-
"docs/faq.md",
22-
"docs/architecture.md",
23-
"docs/features.md",
24-
"docs/configuration.md",
25-
"docs/troubleshooting.md",
26-
"docs/privacy.md",
27-
"docs/upgrade.md",
28-
"docs/reference/commands.md",
29-
"docs/reference/public-api.md",
30-
"docs/reference/error-contracts.md",
31-
"docs/reference/settings.md",
32-
"docs/reference/storage-paths.md",
33-
"docs/releases/v1.1.10.md",
34-
"docs/releases/v0.1.9.md",
35-
"docs/releases/v0.1.8.md",
36-
"docs/releases/v0.1.7.md",
37-
"docs/releases/v0.1.6.md",
38-
"docs/releases/v0.1.5.md",
39-
"docs/releases/v0.1.4.md",
40-
"docs/releases/v0.1.3.md",
41-
"docs/releases/v0.1.1.md",
42-
"docs/releases/v0.1.0.md",
43-
"docs/releases/v0.1.0-beta.0.md",
44-
"docs/releases/legacy-pre-0.1-history.md",
45-
];
17+
function readPackageVersion(): string {
18+
const packagePath = join(projectRoot, "package.json");
19+
let parsed: { version?: unknown };
20+
try {
21+
parsed = JSON.parse(readFileSync(packagePath, "utf-8")) as {
22+
version?: unknown;
23+
};
24+
} catch (error) {
25+
const message = error instanceof Error ? error.message : String(error);
26+
throw new Error(`Failed to read ${packagePath}: ${message}`);
27+
}
28+
if (typeof parsed.version !== "string" || parsed.version.trim().length === 0) {
29+
throw new Error("package.json must define a non-empty version string");
30+
}
31+
return parsed.version.trim();
32+
}
33+
34+
let packageVersion = "";
35+
let currentStableReleaseDoc = "";
36+
// These stay manual so the docs portal keeps an intentional short stable-history window.
37+
const previousStableReleaseDoc = "docs/releases/v1.2.1.md";
38+
const earlierStableReleaseDoc = "docs/releases/v1.2.0.md";
39+
40+
function getUserDocs(): string[] {
41+
return [
42+
"docs/index.md",
43+
"docs/README.md",
44+
"docs/getting-started.md",
45+
"docs/faq.md",
46+
"docs/architecture.md",
47+
"docs/features.md",
48+
"docs/configuration.md",
49+
"docs/troubleshooting.md",
50+
"docs/privacy.md",
51+
"docs/upgrade.md",
52+
"docs/reference/commands.md",
53+
"docs/reference/public-api.md",
54+
"docs/reference/error-contracts.md",
55+
"docs/reference/settings.md",
56+
"docs/reference/storage-paths.md",
57+
currentStableReleaseDoc,
58+
previousStableReleaseDoc,
59+
earlierStableReleaseDoc,
60+
"docs/releases/v0.1.7.md",
61+
"docs/releases/v0.1.6.md",
62+
"docs/releases/v0.1.5.md",
63+
"docs/releases/v0.1.4.md",
64+
"docs/releases/v0.1.3.md",
65+
"docs/releases/v0.1.1.md",
66+
"docs/releases/v0.1.0.md",
67+
"docs/releases/v0.1.0-beta.0.md",
68+
"docs/releases/legacy-pre-0.1-history.md",
69+
];
70+
}
4671

4772
const scopedLegacyAllowedFiles = new Set([
4873
"README.md",
@@ -65,6 +90,11 @@ const maintainerRunbooks = [
6590
"docs/development/RUNBOOK_CHANGE_ROUTING_POLICY.md",
6691
];
6792

93+
beforeAll(() => {
94+
packageVersion = readPackageVersion();
95+
currentStableReleaseDoc = `docs/releases/v${packageVersion}.md`;
96+
});
97+
6898
function read(filePath: string): string {
6999
return readFileSync(join(projectRoot, filePath), "utf-8");
70100
}
@@ -110,9 +140,9 @@ function compareSemverDescending(left: string, right: string): number {
110140
return 0;
111141
}
112142

113-
describe("Documentation Integrity", () => {
143+
describe("Documentation Integrity", () => {
114144
it("has all required user docs and release notes", () => {
115-
for (const docPath of userDocs) {
145+
for (const docPath of getUserDocs()) {
116146
const fullPath = join(projectRoot, docPath);
117147
expect(existsSync(fullPath), `${docPath} should exist`).toBe(true);
118148
expect(
@@ -122,10 +152,14 @@ describe("Documentation Integrity", () => {
122152
}
123153
});
124154

125-
it("docs portal links to stable, beta, and archived release history", () => {
155+
it("docs portal and root README link to stable, beta, and archived release history", () => {
126156
const portal = read("docs/README.md");
157+
const readme = read("README.md");
127158
expect(portal).toContain("reference/public-api.md");
128159
expect(portal).toContain("reference/error-contracts.md");
160+
expect(portal).toContain(`releases/v${packageVersion}.md`);
161+
expect(portal).toContain(previousStableReleaseDoc.replace("docs/", ""));
162+
expect(portal).toContain(earlierStableReleaseDoc.replace("docs/", ""));
129163
expect(portal).toContain("releases/v0.1.7.md");
130164
expect(portal).toContain("releases/v0.1.6.md");
131165
expect(portal).toContain("releases/v0.1.5.md");
@@ -134,6 +168,9 @@ describe("Documentation Integrity", () => {
134168
expect(portal).toContain(
135169
"| [Daily Use release notes](#daily-use) | Stable, previous, and archived release notes |",
136170
);
171+
expect(readme).toContain(currentStableReleaseDoc);
172+
expect(readme).toContain(previousStableReleaseDoc);
173+
expect(readme).toContain(earlierStableReleaseDoc);
137174

138175
const beta = read("docs/releases/v0.1.0-beta.0.md");
139176
expect(beta).toContain("Archived");
@@ -158,7 +195,7 @@ describe("Documentation Integrity", () => {
158195
});
159196

160197
it("uses scoped package only in explicit legacy migration notes", () => {
161-
const files = ["README.md", ...userDocs];
198+
const files = ["README.md", ...getUserDocs()];
162199

163200
for (const filePath of files) {
164201
const content = read(filePath);
@@ -176,7 +213,7 @@ describe("Documentation Integrity", () => {
176213

177214
it("does not include opencode wording in user docs", () => {
178215
const allowedOpencodeFiles = new Set(["docs/reference/storage-paths.md"]);
179-
for (const filePath of userDocs) {
216+
for (const filePath of getUserDocs()) {
180217
const content = read(filePath).toLowerCase();
181218
const hasLegacyHostWord = content.includes("opencode");
182219
if (hasLegacyHostWord) {
@@ -189,7 +226,7 @@ describe("Documentation Integrity", () => {
189226
});
190227

191228
it("keeps compatibility command aliases scoped to reference, troubleshooting, or migration docs", () => {
192-
const files = ["README.md", ...userDocs];
229+
const files = ["README.md", ...getUserDocs()];
193230
const aliasPattern = /\bcodex (multi auth|multi-auth|multiauth)\b/i;
194231

195232
for (const filePath of files) {

0 commit comments

Comments
 (0)