diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 56aece2316..1fb71f5dfe 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -5,7 +5,7 @@ scripts/release*.sh @cryppadotta @devinfoley @nickyleach @forgottendev scripts/release-*.mjs @cryppadotta @devinfoley @nickyleach @forgottendev scripts/create-github-release.sh @cryppadotta @devinfoley @nickyleach @forgottendev scripts/rollback-latest.sh @cryppadotta @devinfoley @nickyleach @forgottendev -doc/RELEASING.md @cryppadotta @devinfoley @nickyleach @forgottendev +doc/RELEASING.md @cryppadotta @devinfoley @nickyleach @forgottendev @tonio-alucema @scotttong doc/PUBLISHING.md @cryppadotta @devinfoley @nickyleach @forgottendev doc/RELEASE-AUTOMATION-SETUP.md @cryppadotta @devinfoley @nickyleach @forgottendev skills/** @cryppadotta @devinfoley @nickyleach @forgottendev diff --git a/doc/DEVELOPING.md b/doc/DEVELOPING.md index c88890e98a..5387361143 100644 --- a/doc/DEVELOPING.md +++ b/doc/DEVELOPING.md @@ -228,10 +228,14 @@ are not automatically deleted and will accumulate until an operator prunes them. Publishing requires both the original actor and the current rerunner to be individual GitHub accounts named in `.github/CODEOWNERS` on the current default -branch. Comments, teams and email entries do not grant access. Authorization runs -before the build and again before deployment, including deployment-only reruns. +branch. Individual accounts from every ownership rule are included, regardless +of which paths they own. Comments, teams and email entries do not grant access. +Authorization runs before the build and again before deployment, including +deployment-only reruns. GitHub also requires a CODEOWNER environment approval, so editing authorization code on a branch cannot grant AWS access without an authorized reviewer. +CODEOWNERS membership does not automatically add an account to the environment's +required reviewers; a configured reviewer must approve each deployment. The build downloads the public source archive with no GitHub token permissions, AWS credentials or repository secrets. Dependency caching and install lifecycle diff --git a/scripts/__tests__/storybook-deploy.test.mjs b/scripts/__tests__/storybook-deploy.test.mjs index 01b2b25272..ec32bbf061 100644 --- a/scripts/__tests__/storybook-deploy.test.mjs +++ b/scripts/__tests__/storybook-deploy.test.mjs @@ -43,6 +43,29 @@ test("allows each current CODEOWNER on a feature branch; reads policy from maste assert.equal(f.calls[0].path, ".github/CODEOWNERS"); } }); +test("owners listed only for release docs may initiate and rerun Storybook", async (t) => { + const triggeringActor = process.env.GITHUB_TRIGGERING_ACTOR; + t.after(() => { process.env.GITHUB_TRIGGERING_ACTOR = triggeringActor; }); + const codeowners = `${ownerFile}doc/RELEASING.md @release-owner @release-reviewer\n`; + for (const actor of ["cryppadotta", "release-owner", "release-reviewer"]) { + for (const rerunner of ["cryppadotta", "release-owner", "release-reviewer"]) { + process.env.GITHUB_TRIGGERING_ACTOR = rerunner; + const f = fixture({ context: { actor }, codeowners }); + await authorize(f); + assert.equal(f.calls[0].ref, "master"); + } + } +}); +test("removing an owner from CODEOWNERS revokes initiating and rerunning access", async (t) => { + const triggeringActor = process.env.GITHUB_TRIGGERING_ACTOR; + t.after(() => { process.env.GITHUB_TRIGGERING_ACTOR = triggeringActor; }); + for (const actor of ["release-owner", "release-reviewer"]) { + process.env.GITHUB_TRIGGERING_ACTOR = "cryppadotta"; + await assert.rejects(authorize(fixture({ context: { actor } })), /Only default-branch CODEOWNERS/); + process.env.GITHUB_TRIGGERING_ACTOR = actor; + await assert.rejects(authorize(fixture()), /Only default-branch CODEOWNERS/); + } +}); test("rejects non-owner initiators", async () => { await assert.rejects(authorize(fixture({ context: { actor: "contributor" } })), /Only default-branch CODEOWNERS/); });