Merge pull request 'docs: pin governance records to Forgejo ceremony 0.6.3' (#42) from build/36-ceremony-pin-proof into main
All checks were successful
ci / test (push) Successful in 16s
All checks were successful
ci / test (push) Successful in 16s
Reviewed-on: #42 Reviewed-by: claude-bot-andresmgsl <andres+1@heavyduty.builders> Reviewed-by: kimi-bot-andresmgsl <andres+4@heavyduty.builders> Reviewed-by: glm-bot-andresmgsl <andres+5@heavyduty.builders>
This commit is contained in:
commit
21b91e870e
4 changed files with 35 additions and 6 deletions
|
|
@ -2,12 +2,13 @@
|
||||||
|
|
||||||
Never edit these files ad hoc. The six manifest-listed doctrine files are
|
Never edit these files ad hoc. The six manifest-listed doctrine files are
|
||||||
byte-identical copies of
|
byte-identical copies of
|
||||||
[heavy-duty/ceremony](https://github.com/heavy-duty/ceremony) at 0.6.3, but
|
[heavy-duty/ceremony](https://forgejo.heavyduty.builders/heavy-duty/ceremony) at 0.6.3, but
|
||||||
stoke does not run `docs-sync` or re-diff the mirror in CI. Change doctrine
|
stoke does not run `docs-sync` or re-diff the mirror in CI. Change doctrine
|
||||||
upstream through its own flow, then re-vendor it here when the pin moves.
|
upstream through its own flow, then re-vendor it here when the pin moves.
|
||||||
|
|
||||||
The labels doctrine is vendored manually from heavy-duty/ceremony at 0.6.3
|
The labels doctrine is vendored manually from
|
||||||
because stoke keeps its own tag-driven `.forgejo/workflows/release.yml`.
|
[heavy-duty/ceremony](https://forgejo.heavyduty.builders/heavy-duty/ceremony) at 0.6.3 because
|
||||||
|
stoke keeps its own tag-driven `.forgejo/workflows/release.yml`.
|
||||||
`docs-sync --fix` cannot run until or unless a future issue adopts the
|
`docs-sync --fix` cannot run until or unless a future issue adopts the
|
||||||
ceremony release-workflow pin; until then, doctrine updates must re-vendor
|
ceremony release-workflow pin; until then, doctrine updates must re-vendor
|
||||||
the pinned manifest manually.
|
the pinned manifest manually.
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
# AGENTS.md — start at .ceremony/
|
# AGENTS.md — start at .ceremony/
|
||||||
|
|
||||||
This repository is governed by
|
This repository is governed by
|
||||||
[heavy-duty/ceremony](https://github.com/heavy-duty/ceremony). Read
|
[heavy-duty/ceremony](https://forgejo.heavyduty.builders/heavy-duty/ceremony). Read
|
||||||
`.ceremony/AGENTS.md` first — it routes you to your role file, vendored
|
`.ceremony/AGENTS.md` first — it routes you to your role file, vendored
|
||||||
beside it. Repo specifics (the review panel roster, the scope labels, what
|
beside it. Repo specifics (the review panel roster, the scope labels, what
|
||||||
a drill means here, code conventions) live in CONTRIBUTING.md.
|
a drill means here, code conventions) live in CONTRIBUTING.md.
|
||||||
|
|
|
||||||
1
changelog.d/36.md
Normal file
1
changelog.d/36.md
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
- Enforced the exact Forgejo ceremony source and version across governance records and workflow pins. (#36).
|
||||||
|
|
@ -11,6 +11,9 @@ const REPOSITORY_CONFIG = path.join(__dirname, '..', '.github', 'labels.conf');
|
||||||
const REPOSITORY_LABELER = path.join(__dirname, '..', '.github', 'labeler.yml');
|
const REPOSITORY_LABELER = path.join(__dirname, '..', '.github', 'labeler.yml');
|
||||||
const REPOSITORY_MIRROR = path.join(__dirname, '..', '.ceremony');
|
const REPOSITORY_MIRROR = path.join(__dirname, '..', '.ceremony');
|
||||||
const ROOT_AGENTS = path.join(__dirname, '..', 'AGENTS.md');
|
const ROOT_AGENTS = path.join(__dirname, '..', 'AGENTS.md');
|
||||||
|
const CEREMONY_REPOSITORY = 'https://forgejo.heavyduty.builders/heavy-duty/ceremony';
|
||||||
|
const CEREMONY_VERSION = '0.6.3';
|
||||||
|
const CEREMONY_WORKFLOWS = ['labels.yml', 'labels-sweep.yml'];
|
||||||
const cleanups = [];
|
const cleanups = [];
|
||||||
process.on('exit', () => {
|
process.on('exit', () => {
|
||||||
for (const dir of cleanups) fs.rmSync(dir, { recursive: true, force: true });
|
for (const dir of cleanups) fs.rmSync(dir, { recursive: true, force: true });
|
||||||
|
|
@ -131,14 +134,38 @@ test('repository scope mapping covers every configured scope with the ruled path
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
test('repository carries the complete 0.6.1 doctrine mirror and root router', () => {
|
test('repository carries the complete Forgejo 0.6.3 doctrine mirror and root router', () => {
|
||||||
const vendored = ['AGENTS.md', 'TRIAGE.md', 'BUILDER.md', 'REVIEWER.md', 'LABELS.md', 'RELEASES.md'];
|
const vendored = ['AGENTS.md', 'TRIAGE.md', 'BUILDER.md', 'REVIEWER.md', 'LABELS.md', 'RELEASES.md'];
|
||||||
for (const filename of vendored) {
|
for (const filename of vendored) {
|
||||||
assert.ok(fs.statSync(path.join(REPOSITORY_MIRROR, filename)).isFile(), `${filename} is missing`);
|
assert.ok(fs.statSync(path.join(REPOSITORY_MIRROR, filename)).isFile(), `${filename} is missing`);
|
||||||
}
|
}
|
||||||
const mirrorReadme = fs.readFileSync(path.join(REPOSITORY_MIRROR, 'README.md'), 'utf8');
|
const mirrorReadme = fs.readFileSync(path.join(REPOSITORY_MIRROR, 'README.md'), 'utf8');
|
||||||
|
const sourceVersionRecord = `[heavy-duty/ceremony](${CEREMONY_REPOSITORY}) at ${CEREMONY_VERSION}`;
|
||||||
|
assert.equal(
|
||||||
|
mirrorReadme.split(sourceVersionRecord).length - 1,
|
||||||
|
2,
|
||||||
|
'mirror README does not identify the exact Forgejo ceremony source and version in both records',
|
||||||
|
);
|
||||||
assert.match(mirrorReadme, /labels doctrine is vendored manually/);
|
assert.match(mirrorReadme, /labels doctrine is vendored manually/);
|
||||||
assert.doesNotMatch(mirrorReadme, /The pin lives in `.github\/workflows\/release\.yml`/);
|
assert.doesNotMatch(mirrorReadme, /The pin lives in `.github\/workflows\/release\.yml`/);
|
||||||
assert.doesNotMatch(mirrorReadme, /Machine-managed by|CI re-diffs them/);
|
assert.doesNotMatch(mirrorReadme, /Machine-managed by|CI re-diffs them/);
|
||||||
assert.match(fs.readFileSync(ROOT_AGENTS, 'utf8'), /read\s+`.ceremony\/AGENTS\.md` first/i);
|
const rootAgents = fs.readFileSync(ROOT_AGENTS, 'utf8');
|
||||||
|
assert.ok(
|
||||||
|
rootAgents.includes(`[heavy-duty/ceremony](${CEREMONY_REPOSITORY})`),
|
||||||
|
'root router does not identify the Forgejo ceremony repository',
|
||||||
|
);
|
||||||
|
assert.match(rootAgents, /read\s+`.ceremony\/AGENTS\.md` first/i);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('repository workflow pins use the exact Forgejo ceremony version', () => {
|
||||||
|
for (const workflow of CEREMONY_WORKFLOWS) {
|
||||||
|
const contents = fs.readFileSync(path.join(__dirname, '..', '.forgejo', 'workflows', workflow), 'utf8');
|
||||||
|
const prefix = `uses: heavy-duty/ceremony/.github/workflows/${workflow}@`;
|
||||||
|
const pins = contents.split(/\r?\n/).map((line) => line.trim()).filter((line) => line.startsWith(prefix));
|
||||||
|
assert.deepEqual(
|
||||||
|
pins,
|
||||||
|
[`${prefix}${CEREMONY_VERSION}`],
|
||||||
|
`${workflow} does not pin ceremony ${CEREMONY_VERSION}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue