@jakobm/peacekeeper 0.13.0 → 0.14.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md
CHANGED
|
@@ -57,7 +57,9 @@ values cause failure without changing the file. Repeating the command on a
|
|
|
57
57
|
complete valid file leaves it unchanged.
|
|
58
58
|
|
|
59
59
|
All CLI commands validate configuration before executing, except help,
|
|
60
|
-
`check-project --explain`, and `update-config`.
|
|
60
|
+
`check-project --explain`, and `update-config`. Checkpoint hooks instead validate
|
|
61
|
+
the event worktree configuration when the event requires instructions or a check.
|
|
62
|
+
An incomplete existing file fails
|
|
61
63
|
with missing field paths and a repair hint. Updates introducing new fields
|
|
62
64
|
therefore require `peacekeeper update-config` before ordinary commands can run.
|
|
63
65
|
|
|
@@ -92,6 +94,8 @@ Complete example:
|
|
|
92
94
|
|
|
93
95
|
`loggingEnabled` has the bundled default `true`; set it to `false` to disable invocation logs and the background cleanup worker's log file. Existing logs are kept. The setting is read from the primary checkout's configuration, including for linked worktrees. SessionStart and Stop logs include the process and event working directories, event type, primary-checkout classification, and hook response or error. Only selected event fields are logged, never the full incoming payload. These logs require the Peacekeeper script to start; a missing Node.js executable or package must be diagnosed in Codex's own logs.
|
|
94
96
|
|
|
97
|
+
Checkpoint hook failures write the cause to stderr and exit with code 2 instead of reporting success. For `Stop`, this requests continued work under the Codex hook protocol. Invocation logging is advisory: a logging failure is reported on stderr, but the checkpoint instructions or check still run and retain their result. Behavior configuration comes from the event's worktree, while log settings come from the primary checkout. A logging warning alone does not change the exit code.
|
|
98
|
+
|
|
95
99
|
To publish checkpoint branches automatically, set `git.checkpointPushRemotes` (fragment):
|
|
96
100
|
|
|
97
101
|
```json
|
|
@@ -277,7 +281,8 @@ with **Require branches to be up to date before merging** enabled. Classic branc
|
|
|
277
281
|
protection must enforce checks for administrators too. Alternatively, active
|
|
278
282
|
rulesets must require strict checks and have no bypass actors. Rules inherited
|
|
279
283
|
from the organization are included. Merge queues are not currently an alternative
|
|
280
|
-
to this strict policy.
|
|
284
|
+
to this strict policy. Repositories must also enable **Automatically delete head
|
|
285
|
+
branches** (`delete_branch_on_merge=true`).
|
|
281
286
|
|
|
282
287
|
The PR test job runs `peacekeeper verify-release-protection` before its tests.
|
|
283
288
|
The command checks `GITHUB_BASE_REF`, or `git.defaultBranch` outside PR CI.
|
|
@@ -291,8 +296,9 @@ jobs in its latest PR workflow run. Manual tags without that PR are rejected.
|
|
|
291
296
|
API failures, missing permissions, and unverifiable rules stop the commands.
|
|
292
297
|
The workflow expects a `RELEASE_POLICY_TOKEN` Actions secret, exposed to the
|
|
293
298
|
commands as `GH_TOKEN`. Use a fine-grained PAT or GitHub App token with access to
|
|
294
|
-
this repository and Administration read, Contents read, Pull requests read and
|
|
295
|
-
Actions read permissions.
|
|
299
|
+
this repository and Administration read, Contents read/write, Pull requests read and
|
|
300
|
+
Actions read permissions. Contents write is required even to read merge-related
|
|
301
|
+
settings such as `delete_branch_on_merge`. GitHub only exposes ruleset bypass actors to callers
|
|
296
302
|
with write access to the ruleset; ruleset users must additionally grant that
|
|
297
303
|
access (Administration write for repository rulesets, or the appropriate access
|
|
298
304
|
for inherited organization rulesets). Missing bypass information also fails.
|
|
@@ -303,8 +309,8 @@ by executing fork code with `pull_request_target`.
|
|
|
303
309
|
|
|
304
310
|
To set this up for this repository:
|
|
305
311
|
|
|
306
|
-
1. Open the [token creation form with the required
|
|
307
|
-
For repository rulesets, use the [form with Administration write instead](https://github.com/settings/personal-access-tokens/new?name=peacekeeper-release-policy&target_name=jakobmattsson&expires_in=90&administration=write&contents=
|
|
312
|
+
1. Open the [token creation form with the required permissions prefilled](https://github.com/settings/personal-access-tokens/new?name=peacekeeper-release-policy&target_name=jakobmattsson&expires_in=90&administration=read&contents=write&pull_requests=read&actions=read).
|
|
313
|
+
For repository rulesets, use the [form with Administration write instead](https://github.com/settings/personal-access-tokens/new?name=peacekeeper-release-policy&target_name=jakobmattsson&expires_in=90&administration=write&contents=write&pull_requests=read&actions=read)
|
|
308
314
|
so GitHub exposes bypass actors. For another repository, change the resource
|
|
309
315
|
owner. Select **Only select repositories**, choose `peacekeeper`, review
|
|
310
316
|
the permissions and expiration, and generate the token. If the owner requires
|
package/bin/peacekeeper.js
CHANGED
|
@@ -45,7 +45,8 @@ function main() {
|
|
|
45
45
|
}
|
|
46
46
|
const informational = (args.length === 1 && ['--help', '-h'].includes(args[0]))
|
|
47
47
|
|| (command === 'check-project' && args.length === 1 && args[0] === '--explain');
|
|
48
|
-
|
|
48
|
+
const checkpointHook = ['checkpoint-codex-session-start', 'checkpoint-codex-stop'].includes(command);
|
|
49
|
+
if (command !== 'update-config' && !checkpointHook && !informational) require('../scripts/project-config').projectConfig();
|
|
49
50
|
const script = path.resolve(__dirname, '..', 'scripts', `${command}.js`);
|
|
50
51
|
const result = spawnSync(process.execPath, [script, ...args], {
|
|
51
52
|
cwd: process.cwd(),
|
package/package.json
CHANGED
|
@@ -184,6 +184,9 @@ Online release policy and GitHub token setup
|
|
|
184
184
|
local declarations above. Use verify-release-protection to check the branch
|
|
185
185
|
policy and verify-release before publishing to check the release itself.
|
|
186
186
|
|
|
187
|
+
Enable "Automatically delete head branches" (delete_branch_on_merge=true) in
|
|
188
|
+
the repository settings. The online release policy commands require it.
|
|
189
|
+
|
|
187
190
|
Configure the default branch from git.defaultBranch with every exact job name
|
|
188
191
|
in git.releaseRequiredChecks mandatory and "Require branches to be up to date
|
|
189
192
|
before merging" enabled. Choose either:
|
|
@@ -197,7 +200,7 @@ Online release policy and GitHub token setup
|
|
|
197
200
|
Create a fine-grained GitHub PAT or GitHub App installation token with access
|
|
198
201
|
to this repository and these repository permissions:
|
|
199
202
|
Administration: read
|
|
200
|
-
Contents: read
|
|
203
|
+
Contents: read/write
|
|
201
204
|
Pull requests: read
|
|
202
205
|
Actions: read
|
|
203
206
|
For repository rulesets, Administration: write is additionally needed because
|
|
@@ -78,8 +78,18 @@ function runLoggedCheckpointHook(buildResponse, errorPrefix) {
|
|
|
78
78
|
let logPath;
|
|
79
79
|
let event;
|
|
80
80
|
let response;
|
|
81
|
+
function log(action) {
|
|
82
|
+
try {
|
|
83
|
+
action();
|
|
84
|
+
} catch (error) {
|
|
85
|
+
process.stderr.write(`${errorPrefix}: logging failed: ${error.message}\n`);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
log(() => { logPath = logScriptInvocation(); });
|
|
89
|
+
function record(value) {
|
|
90
|
+
if (logPath) log(() => fs.appendFileSync(logPath, `${JSON.stringify(value)}\n`));
|
|
91
|
+
}
|
|
81
92
|
try {
|
|
82
|
-
logPath = logScriptInvocation();
|
|
83
93
|
const input = fs.readFileSync(0, 'utf8').trim();
|
|
84
94
|
event = input === '' ? null : JSON.parse(input);
|
|
85
95
|
const details = {
|
|
@@ -88,16 +98,20 @@ function runLoggedCheckpointHook(buildResponse, errorPrefix) {
|
|
|
88
98
|
source: event?.source,
|
|
89
99
|
stopHookActive: event?.stop_hook_active,
|
|
90
100
|
};
|
|
91
|
-
|
|
101
|
+
record({ event: details });
|
|
92
102
|
if (typeof event?.cwd === 'string') {
|
|
93
103
|
const primaryWorktree = isPrimaryWorktree(event.cwd);
|
|
94
|
-
|
|
104
|
+
record({ primaryWorktree });
|
|
95
105
|
}
|
|
96
106
|
response = buildResponse(event);
|
|
97
107
|
} catch (error) {
|
|
98
|
-
|
|
108
|
+
const message = `${errorPrefix}: ${error.message}`;
|
|
109
|
+
process.stderr.write(`${message}\n`);
|
|
110
|
+
process.exitCode = 2;
|
|
111
|
+
record({ error: message });
|
|
112
|
+
return;
|
|
99
113
|
}
|
|
100
|
-
|
|
114
|
+
record({ response });
|
|
101
115
|
process.stdout.write(`${JSON.stringify(response)}\n`);
|
|
102
116
|
}
|
|
103
117
|
|
|
@@ -11,6 +11,9 @@ function requiredChecks(cwd) {
|
|
|
11
11
|
// other API failures, including permission failures, must propagate.
|
|
12
12
|
function verifyProtection({ api, slug, branch, checks }) {
|
|
13
13
|
const base = `repos/${slug}`;
|
|
14
|
+
if (api(base)?.delete_branch_on_merge !== true) {
|
|
15
|
+
throw new Error(`Repository ${slug} must enable delete_branch_on_merge. Run gh api --method PATCH ${base} -F delete_branch_on_merge=true, then rerun.`);
|
|
16
|
+
}
|
|
14
17
|
let protection;
|
|
15
18
|
try {
|
|
16
19
|
protection = api(`${base}/branches/${encodeURIComponent(branch)}/protection`);
|
|
@@ -56,7 +59,7 @@ function githubApi(exec, cwd, host) {
|
|
|
56
59
|
return endpoint => {
|
|
57
60
|
const response = exec('gh', ['api', '--hostname', host, '--method', 'GET', endpoint], { cwd });
|
|
58
61
|
if (response.status !== 0) {
|
|
59
|
-
const error = new Error(`Cannot verify GitHub release policy (${endpoint}): ${response.stderr?.trim() || 'API request failed'}. Grant the token Administration read, Contents read, Pull requests read and Actions read permissions, then rerun.`);
|
|
62
|
+
const error = new Error(`Cannot verify GitHub release policy (${endpoint}): ${response.stderr?.trim() || 'API request failed'}. Grant the token Administration read, Contents read/write, Pull requests read and Actions read permissions, then rerun.`);
|
|
60
63
|
error.status = Number(/HTTP (\d{3})/u.exec(response.stderr || '')?.[1]);
|
|
61
64
|
throw error;
|
|
62
65
|
}
|