@jakobm/peacekeeper 0.15.0 → 0.16.0
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 +37 -15
- package/package.json +1 -2
- package/scripts/check-project-requirements.txt +28 -4
- package/scripts/check-project.js +12 -0
- package/scripts/release-core.js +4 -3
- package/scripts/release-protection.js +37 -11
- package/scripts/run-tests.js +9 -0
- package/scripts/verify-release-protection.js +1 -1
package/README.md
CHANGED
|
@@ -90,7 +90,7 @@ Complete example:
|
|
|
90
90
|
}
|
|
91
91
|
```
|
|
92
92
|
|
|
93
|
-
`git.remote` and `git.defaultBranch` identify the branch used for checkpointing and cleanup. `git.branchPrefix` names new task branches. `tests.commands` are complete shell commands, run in order from the caller's Git root; install any executables they use. The test runner stops on the first failure and records a receipt only after every command succeeds. `receiptMaxAgeMinutes` controls how long a receipt can be reused. Set `npmTestUsesRunner` to `true` only when the caller's `npm test` script invokes `peacekeeper run-tests`; this makes the rerun hint `npm test -- rerun`. Otherwise the hint uses the explicit package path. `loggingDirectory` stores hook invocation logs relative to the primary Git worktree's root.
|
|
93
|
+
`git.remote` and `git.defaultBranch` identify the branch used for checkpointing and cleanup. `git.branchPrefix` names new task branches. `run-tests` always runs the local `check-project` validation first, even when reusing a test receipt. Explicit `check-project` invocations in `tests.commands` are rejected as redundant. The configured commands are complete shell commands, run in order from the caller's Git root; install any executables they use. The test runner stops on the first failure and records a receipt only after every command succeeds. `receiptMaxAgeMinutes` controls how long a receipt can be reused. Set `npmTestUsesRunner` to `true` only when the caller's `npm test` script invokes `peacekeeper run-tests`; this makes the rerun hint `npm test -- rerun`. Otherwise the hint uses the explicit package path. `loggingDirectory` stores hook invocation logs relative to the primary Git worktree's root.
|
|
94
94
|
|
|
95
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.
|
|
96
96
|
|
|
@@ -287,8 +287,39 @@ from the organization are included. Merge queues are not currently an alternativ
|
|
|
287
287
|
to this strict policy. Repositories must also enable **Automatically delete head
|
|
288
288
|
branches** (`delete_branch_on_merge=true`).
|
|
289
289
|
|
|
290
|
+
The default branch must require pull requests (zero required reviewer approvals
|
|
291
|
+
is allowed), and only merge commits may be used. Either disable squash and rebase
|
|
292
|
+
in repository settings, or restrict the default branch's pull-request ruleset to
|
|
293
|
+
`allowed_merge_methods: ["merge"]`. Other branches are outside this policy.
|
|
294
|
+
Required linear history and any applicable PR rule excluding merge commits fail
|
|
295
|
+
verification. PR and strict-check rules must enforce the policy without bypass.
|
|
296
|
+
Enable `allow_auto_merge` in repository settings: this permits opting in per PR;
|
|
297
|
+
Peacekeeper never enables auto-merge on individual PRs.
|
|
298
|
+
|
|
299
|
+
`check-project` makes no network requests. It runs implicitly before
|
|
300
|
+
`tests.commands`, including when reusing a receipt, and checks that the configured
|
|
301
|
+
PR workflow covers the default branch and runs `verify-release-protection` with `GH_TOKEN` after `npm ci` and
|
|
302
|
+
before tests in a job listed in `git.releaseRequiredChecks`. The job and step must
|
|
303
|
+
not skip verification or ignore failures. The online verifier then checks that
|
|
304
|
+
all those configured check names are mandatory on GitHub, including its own job.
|
|
305
|
+
For example, in a required `test` job:
|
|
306
|
+
|
|
307
|
+
```yaml
|
|
308
|
+
- run: npm ci
|
|
309
|
+
- run: peacekeeper verify-release-protection
|
|
310
|
+
env:
|
|
311
|
+
GH_TOKEN: ${{ secrets.RELEASE_POLICY_TOKEN }}
|
|
312
|
+
- run: npm test
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
This creates a local-to-CI chain: missing workflows are detected on the next local
|
|
316
|
+
`npm test`; incorrect GitHub settings are detected on the next PR run. It is not
|
|
317
|
+
continuous monitoring. Removing both CI and the local invocation prevents this
|
|
318
|
+
chain from running. No central scheduled audit is required by this setup.
|
|
319
|
+
|
|
290
320
|
The PR test job runs `peacekeeper verify-release-protection` before its tests.
|
|
291
|
-
The command
|
|
321
|
+
The command reads the actual default branch from GitHub, regardless of the PR
|
|
322
|
+
base. Other release commands require their configured branch to match it.
|
|
292
323
|
`peacekeeper release` checks the default branch before preparing a release
|
|
293
324
|
and again immediately before each merge attempt. Before publishing,
|
|
294
325
|
`peacekeeper verify-release` checks the policy, matching package/tag/lockfile
|
|
@@ -350,19 +381,10 @@ not retain historical proof of the tested file tree if administrators change
|
|
|
350
381
|
settings between CI and merge. Keep the `package.yml` filename unchanged: npm
|
|
351
382
|
trusted publishing is configured for that workflow file.
|
|
352
383
|
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
- If multiple methods are allowed, `git.releaseMergeMethod` selects
|
|
358
|
-
`"merge"` (merge commit), `"rebase"`, or `"squash"`. A configured method that
|
|
359
|
-
GitHub disallows causes the release to stop before creating a branch or PR.
|
|
360
|
-
- The bundled preference is `"merge"`.
|
|
361
|
-
|
|
362
|
-
For example, set `"releaseMergeMethod": "rebase"` inside the existing `git` object.
|
|
363
|
-
A caller without a configuration file uses the bundled defaults.
|
|
364
|
-
The chosen method is saved with release state and reused on retries; unfinished
|
|
365
|
-
releases created by older versions retain their original squash behavior.
|
|
384
|
+
Releases use merge commits on the default branch, including retries of legacy
|
|
385
|
+
state without a merge method. Saved unfinished releases that explicitly select
|
|
386
|
+
squash or rebase must be restarted. `git.releaseMergeMethod` remains accepted for
|
|
387
|
+
configuration compatibility, but no longer selects the default-branch merge method.
|
|
366
388
|
|
|
367
389
|
From a clean repository root, run `npm run release -- patch`, `minor`, or `major`.
|
|
368
390
|
The command fetches the default branch and uses a temporary detached worktree to
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jakobm/peacekeeper",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.16.0",
|
|
4
4
|
"description": "Shared repository test, Git worktree, and Codex hook commands",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Jakob Mattsson",
|
|
@@ -20,7 +20,6 @@
|
|
|
20
20
|
"scripts/"
|
|
21
21
|
],
|
|
22
22
|
"scripts": {
|
|
23
|
-
"pretest": "node bin/peacekeeper.js check-project",
|
|
24
23
|
"test": "node bin/peacekeeper.js run-tests",
|
|
25
24
|
"release": "node bin/peacekeeper.js release",
|
|
26
25
|
"cleanup:branches": "node bin/peacekeeper.js cleanup-merged-branches",
|
|
@@ -332,7 +332,31 @@ What a passing check does and does not establish
|
|
|
332
332
|
online verification; verify-release handles the release checks it supports.
|
|
333
333
|
|
|
334
334
|
Using this check in the test chain
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
335
|
+
run-tests always runs check-project as an implicit first step before
|
|
336
|
+
tests.commands, including when a valid receipt skips the configured commands.
|
|
337
|
+
Explicit check-project invocations in tests.commands are rejected as redundant
|
|
338
|
+
because the runner always includes this step automatically. Supported direct
|
|
339
|
+
peacekeeper, npm exec, npx and node CLI forms are checked, including commands
|
|
340
|
+
separated by shell control operators. Failure stops the run and invalidates any
|
|
341
|
+
existing receipt. This check remains entirely local.
|
|
342
|
+
|
|
343
|
+
Default-branch GitHub policy chain
|
|
344
|
+
The configured PR workflow must run verify-release-protection with step GH_TOKEN
|
|
345
|
+
after npm ci and before tests in at least one job in git.releaseRequiredChecks.
|
|
346
|
+
Verification must be unconditional and must not allow failure. The existing
|
|
347
|
+
required-job validation applies to that job and its dependencies.
|
|
348
|
+
This applies to private projects too; configure nonempty releaseRequiredChecks.
|
|
349
|
+
|
|
350
|
+
Online verification reads the actual GitHub default branch and requires PRs,
|
|
351
|
+
strict mandatory configured checks without bypass, and merge commits only.
|
|
352
|
+
Zero reviewer approvals is allowed. Enable repository allow_auto_merge; this
|
|
353
|
+
only offers per-PR opt-in and does not activate auto-merge for any PR.
|
|
354
|
+
Restrict merge methods either repository-wide (merge enabled, squash and rebase
|
|
355
|
+
disabled) or with a default-branch PR ruleset allowing only merge. Other branches
|
|
356
|
+
are not checked. Linear-history rules or PR rules excluding merge are errors.
|
|
357
|
+
Ruleset PR requirements, like status checks, require active rules without bypass.
|
|
358
|
+
Existing automatic head-branch deletion requirements still apply.
|
|
359
|
+
|
|
360
|
+
Missing CI is detected on the next local npm test. GitHub settings are checked
|
|
361
|
+
on the next PR run, before release merges and before publication. This is not
|
|
362
|
+
continuous monitoring and cannot run if both local checks and CI are removed.
|
package/scripts/check-project.js
CHANGED
|
@@ -40,6 +40,13 @@ function checkProject(cwd = process.cwd()) {
|
|
|
40
40
|
try { action(); } catch (error) { errors.push(`[${category}] ${error.message}`); }
|
|
41
41
|
finally { category = previous; }
|
|
42
42
|
};
|
|
43
|
+
check('tests', () => {
|
|
44
|
+
const projectCheck = /(?:^|&&|\|\||;|\n)\s*(?:peacekeeper|npm\s+exec\s+--no\s+--\s+peacekeeper|npx\s+--no-install\s+peacekeeper|node\s+(?:\.\/)?(?:node_modules\/@jakobm\/peacekeeper\/)?bin\/peacekeeper\.js)\s+check-project(?=\s|$|;|&|\|)/u;
|
|
45
|
+
for (const [index, command] of config.tests.commands.entries()) {
|
|
46
|
+
requireThat(!projectCheck.test(command),
|
|
47
|
+
`tests.commands[${index}]: remove check-project; it is redundant because Peacekeeper always includes it automatically before the configured test commands, even when reusing a test receipt.`);
|
|
48
|
+
}
|
|
49
|
+
});
|
|
43
50
|
check('package', () => {
|
|
44
51
|
const nonblank = value => typeof value === 'string' && value.trim().length > 0;
|
|
45
52
|
requireThat(nonblank(manifest.author) || nonblank(manifest.author?.name),
|
|
@@ -161,6 +168,7 @@ function checkProject(cwd = process.cwd()) {
|
|
|
161
168
|
&& !['paths', 'paths-ignore', 'branches-ignore', 'types'].some(key => Object.hasOwn(filters, key))
|
|
162
169
|
&& (!filters.branches || (Array.isArray(filters.branches) && filters.branches.includes(config.git.defaultBranch)))),
|
|
163
170
|
`${filename}: PR filters must include the default branch and must not skip required checks by path or event type.`);
|
|
171
|
+
let policyJobs = 0;
|
|
164
172
|
const checked = new Set();
|
|
165
173
|
function requiredJob(id, job, testsRequired) {
|
|
166
174
|
if (!requireThat(job && typeof job === 'object', `${filename}/${id}: required job is missing; checks for this job are blocked.`)) return;
|
|
@@ -174,6 +182,9 @@ function checkProject(cwd = process.cwd()) {
|
|
|
174
182
|
const steps = job.steps || [];
|
|
175
183
|
const installed = steps.findIndex(step => directCommand(step, installCommand) && unconditional(step.if) && !step['continue-on-error']);
|
|
176
184
|
const tested = steps.findIndex(step => directCommand(step, testCommand) && unconditional(step.if) && !step['continue-on-error']);
|
|
185
|
+
const policy = steps.findIndex(step => directCommand(step, /^(?:peacekeeper|npm exec --no -- peacekeeper|node (?:\.\/)?(?:node_modules\/@jakobm\/peacekeeper\/)?bin\/peacekeeper\.js) verify-release-protection$/u)
|
|
186
|
+
&& unconditional(step.if) && !step['continue-on-error'] && step.env?.GH_TOKEN);
|
|
187
|
+
if (policy > installed && installed >= 0 && policy < tested && config.git.releaseRequiredChecks.includes(job.name || id)) policyJobs += 1;
|
|
177
188
|
requireThat(installed >= 0 && tested > installed, `${filename}/${id}: run unconditional npm ci before npm test, npm run test:<name>, or npm pack --dry-run (without continue-on-error).`);
|
|
178
189
|
}
|
|
179
190
|
for (const name of required) {
|
|
@@ -183,6 +194,7 @@ function checkProject(cwd = process.cwd()) {
|
|
|
183
194
|
checked.clear();
|
|
184
195
|
requiredJob(...matching[0], true);
|
|
185
196
|
}
|
|
197
|
+
requireThat(policyJobs > 0, `${filename}: a job in git.releaseRequiredChecks must run unconditional verify-release-protection with GH_TOKEN after npm ci and before tests.`);
|
|
186
198
|
});
|
|
187
199
|
|
|
188
200
|
if (published) check('publication', () => {
|
package/scripts/release-core.js
CHANGED
|
@@ -223,12 +223,12 @@ function prepare(exec, cwd, bump, log) {
|
|
|
223
223
|
const remote = checked(exec, 'git', ['remote', 'get-url', 'origin'], cwd);
|
|
224
224
|
const { host, slug } = originRepository(remote);
|
|
225
225
|
const repository = github(exec, cwd, host, `repos/${slug}`, {});
|
|
226
|
-
|
|
226
|
+
projectConfig(cwd);
|
|
227
227
|
const allowed = ['merge', 'rebase', 'squash'].filter((method) =>
|
|
228
228
|
repository[{ merge: 'allow_merge_commit', rebase: 'allow_rebase_merge', squash: 'allow_squash_merge' }[method]] === true);
|
|
229
229
|
if (!allowed.length)
|
|
230
230
|
throw new ReleaseError('No supported PR merge method is enabled.');
|
|
231
|
-
const mergeMethod =
|
|
231
|
+
const mergeMethod = 'merge';
|
|
232
232
|
if (!allowed.includes(mergeMethod))
|
|
233
233
|
throw new ReleaseError(`Configured release merge method ${mergeMethod} is not enabled on GitHub.`);
|
|
234
234
|
const defaultBranch = repository.default_branch;
|
|
@@ -374,10 +374,11 @@ async function mergeRelease(exec, cwd, details, now, sleep, log) {
|
|
|
374
374
|
throw new ReleaseError(`Release PR #${details.pr} has conflicts; inspect it before continuing.`);
|
|
375
375
|
verifyProtection({ api: githubApi(exec, cwd, details.host), slug: details.slug,
|
|
376
376
|
branch: details.defaultBranch, checks: requiredChecks(cwd) });
|
|
377
|
+
if (details.mergeMethod && details.mergeMethod !== 'merge') throw new ReleaseError('Release must use merge commits on the default branch; restart this release.');
|
|
377
378
|
// GitHub enforces required checks, reviews, and branch freshness on this request.
|
|
378
379
|
const result = exec('gh', ['api', '--hostname', details.host, '--method', 'PUT',
|
|
379
380
|
`repos/${details.slug}/pulls/${details.pr}/merge`,
|
|
380
|
-
'-f', `merge_method=${details.mergeMethod || '
|
|
381
|
+
'-f', `merge_method=${details.mergeMethod || 'merge'}`, '-f', `sha=${details.sha}`], { cwd });
|
|
381
382
|
if (result.status === 0) {
|
|
382
383
|
const merged = JSON.parse(result.stdout);
|
|
383
384
|
if (merged.merged)
|
|
@@ -11,9 +11,12 @@ 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
|
-
|
|
14
|
+
const repository = api(base);
|
|
15
|
+
if (repository?.delete_branch_on_merge !== true) {
|
|
15
16
|
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
17
|
}
|
|
18
|
+
if (repository.allow_auto_merge !== true) throw new Error('Repository must enable allow_auto_merge; this only makes auto-merge available per PR.');
|
|
19
|
+
if (repository.default_branch !== branch) throw new Error(`Verify the actual default branch (${repository.default_branch}), not ${branch}.`);
|
|
17
20
|
let protection;
|
|
18
21
|
try {
|
|
19
22
|
protection = api(`${base}/branches/${encodeURIComponent(branch)}/protection`);
|
|
@@ -27,6 +30,33 @@ function verifyProtection({ api, slug, branch, checks }) {
|
|
|
27
30
|
rules.push(...batch);
|
|
28
31
|
if (batch.length < 100) break;
|
|
29
32
|
}
|
|
33
|
+
if (protection?.required_linear_history?.enabled || rules.some(rule => rule.type === 'required_linear_history')) {
|
|
34
|
+
throw new Error('Default branch must allow merge commits; disable required linear history.');
|
|
35
|
+
}
|
|
36
|
+
const pullRules = rules.filter(rule => rule.type === 'pull_request');
|
|
37
|
+
let requiresPullRequest = Boolean(protection?.required_pull_request_reviews && protection.enforce_admins?.enabled === true
|
|
38
|
+
&& !(protection.required_pull_request_reviews.bypass_pull_request_allowances?.users?.length)
|
|
39
|
+
&& !(protection.required_pull_request_reviews.bypass_pull_request_allowances?.teams?.length)
|
|
40
|
+
&& !(protection.required_pull_request_reviews.bypass_pull_request_allowances?.apps?.length));
|
|
41
|
+
let branchMergeOnly = false;
|
|
42
|
+
const verifiedRulesets = new Set();
|
|
43
|
+
function verifyRuleset(rule) {
|
|
44
|
+
if (!Number.isInteger(rule.ruleset_id)) throw new Error('GitHub did not identify the policy ruleset.');
|
|
45
|
+
if (verifiedRulesets.has(rule.ruleset_id)) return;
|
|
46
|
+
const ruleset = api(`${base}/rulesets/${rule.ruleset_id}`);
|
|
47
|
+
if (ruleset.enforcement !== 'active' || !Array.isArray(ruleset.bypass_actors)) {
|
|
48
|
+
throw new Error('Cannot verify active ruleset bypass settings; grant write access to the ruleset so GitHub exposes bypass actors, then rerun.');
|
|
49
|
+
}
|
|
50
|
+
if (ruleset.bypass_actors.length) throw new Error('Default branch rulesets must not allow bypass actors.');
|
|
51
|
+
verifiedRulesets.add(rule.ruleset_id);
|
|
52
|
+
}
|
|
53
|
+
for (const rule of pullRules) {
|
|
54
|
+
verifyRuleset(rule);
|
|
55
|
+
requiresPullRequest = true;
|
|
56
|
+
const methods = rule.parameters?.allowed_merge_methods;
|
|
57
|
+
if (methods && !methods.includes('merge')) throw new Error('Default branch PR rules must allow merge commits.');
|
|
58
|
+
if (Array.isArray(methods) && methods.length === 1 && methods[0] === 'merge') branchMergeOnly = true;
|
|
59
|
+
}
|
|
30
60
|
const strictChecks = new Set();
|
|
31
61
|
const classic = protection?.required_status_checks;
|
|
32
62
|
if (classic?.strict === true && protection.enforce_admins?.enabled === true) {
|
|
@@ -35,24 +65,20 @@ function verifyProtection({ api, slug, branch, checks }) {
|
|
|
35
65
|
}
|
|
36
66
|
// Ruleset bypass actors are not included in the effective-rules response.
|
|
37
67
|
// Read every contributing ruleset and require that it has no bypass actors.
|
|
38
|
-
const checkedRulesets = new Set();
|
|
39
68
|
for (const rule of rules.filter(rule => rule.type === 'required_status_checks')) {
|
|
40
69
|
if (rule.parameters?.strict_required_status_checks_policy !== true) continue;
|
|
41
|
-
|
|
42
|
-
if (!checkedRulesets.has(rule.ruleset_id)) {
|
|
43
|
-
const ruleset = api(`${base}/rulesets/${rule.ruleset_id}`);
|
|
44
|
-
if (ruleset.enforcement !== 'active' || !Array.isArray(ruleset.bypass_actors)) {
|
|
45
|
-
throw new Error('Cannot verify active ruleset bypass settings; grant write access to the ruleset so GitHub exposes bypass actors, then rerun.');
|
|
46
|
-
}
|
|
47
|
-
if (ruleset.bypass_actors.length) throw new Error('Strict release rulesets must not allow bypass actors.');
|
|
48
|
-
checkedRulesets.add(rule.ruleset_id);
|
|
49
|
-
}
|
|
70
|
+
verifyRuleset(rule);
|
|
50
71
|
for (const check of rule.parameters.required_status_checks || []) strictChecks.add(check.context);
|
|
51
72
|
}
|
|
52
73
|
const missing = checks.filter(check => !strictChecks.has(check));
|
|
53
74
|
if (!checks.length || missing.length) {
|
|
54
75
|
throw new Error(`Branch ${branch} must require strict status checks without bypass for: ${missing.join(', ') || '(no checks configured)'}. Enable strict checks and enforce them for administrators, or use an active ruleset without bypass actors; then rerun.`);
|
|
55
76
|
}
|
|
77
|
+
if (!requiresPullRequest) throw new Error('Default branch must require pull requests without bypass.');
|
|
78
|
+
if (repository.allow_merge_commit !== true || (!branchMergeOnly
|
|
79
|
+
&& (repository.allow_squash_merge !== false || repository.allow_rebase_merge !== false))) {
|
|
80
|
+
throw new Error('Default branch must allow only merge commits: restrict its pull request ruleset to merge, or disable repository squash and rebase merging.');
|
|
81
|
+
}
|
|
56
82
|
}
|
|
57
83
|
|
|
58
84
|
function githubApi(exec, cwd, host) {
|
package/scripts/run-tests.js
CHANGED
|
@@ -31,6 +31,15 @@ function main() {
|
|
|
31
31
|
process.exitCode = 2;
|
|
32
32
|
return;
|
|
33
33
|
}
|
|
34
|
+
const projectStatus = spawnSync(process.execPath, [require.resolve('./check-project.js')], {
|
|
35
|
+
cwd: config.root, stdio: 'inherit',
|
|
36
|
+
});
|
|
37
|
+
if (projectStatus.error) throw projectStatus.error;
|
|
38
|
+
if (projectStatus.status !== 0) {
|
|
39
|
+
fs.rmSync(receiptPath(config.root), { force: true });
|
|
40
|
+
process.exitCode = projectStatus.status ?? 1;
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
34
43
|
if (!force && !process.env.CI && hasReusableReceipt()) {
|
|
35
44
|
console.log(successMessage(config.root));
|
|
36
45
|
return;
|
|
@@ -12,7 +12,7 @@ try {
|
|
|
12
12
|
if (remote.status !== 0) throw new Error(remote.stderr);
|
|
13
13
|
const { host, slug } = originRepository(remote.stdout.trim());
|
|
14
14
|
const api = githubApi((command, args, options) => spawnSync(command, args, { ...options, encoding: 'utf8' }), cwd, host);
|
|
15
|
-
verifyProtection({ api, slug, branch:
|
|
15
|
+
verifyProtection({ api, slug, branch: api(`repos/${slug}`).default_branch, checks: requiredChecks(cwd) });
|
|
16
16
|
} catch (error) {
|
|
17
17
|
console.error(error.message);
|
|
18
18
|
process.exitCode = 1;
|