@lilpacy/setup-github-rules 0.1.0 → 0.1.2
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 +12 -0
- package/bin/setup-github-rules.js +41 -8
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -74,6 +74,18 @@ npx @lilpacy/setup-github-rules \
|
|
|
74
74
|
--yes
|
|
75
75
|
```
|
|
76
76
|
|
|
77
|
+
### required approvals を対話で選ぶ
|
|
78
|
+
|
|
79
|
+
`--required-approvals` を省略すると、実行中に `0` から `6` を選べます。Enter だけ押した場合は `1` です。
|
|
80
|
+
|
|
81
|
+
```txt
|
|
82
|
+
Choose the number of required approving reviews.
|
|
83
|
+
Use 0 for solo repositories where nobody else can approve your PR.
|
|
84
|
+
Required approvals [0-6] (default: 1):
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
1 人で開発している repository なら、通常は `0` を選ぶのが安全です。
|
|
88
|
+
|
|
77
89
|
### dry-run
|
|
78
90
|
|
|
79
91
|
```bash
|
|
@@ -6,11 +6,12 @@ import { tmpdir } from "node:os";
|
|
|
6
6
|
import path from "node:path";
|
|
7
7
|
import readline from "node:readline/promises";
|
|
8
8
|
import { stdin as input, stdout as output } from "node:process";
|
|
9
|
+
import { fileURLToPath } from "node:url";
|
|
9
10
|
|
|
10
11
|
const API_VERSION = "2022-11-28";
|
|
11
12
|
const DEFAULT_RULESET_NAME_PREFIX = "Require PR to";
|
|
12
13
|
|
|
13
|
-
function parseArgs(argv) {
|
|
14
|
+
export function parseArgs(argv) {
|
|
14
15
|
const args = {
|
|
15
16
|
repo: null,
|
|
16
17
|
branch: null,
|
|
@@ -33,13 +34,17 @@ function parseArgs(argv) {
|
|
|
33
34
|
else throw new Error(`Unknown option: ${arg}`);
|
|
34
35
|
}
|
|
35
36
|
|
|
36
|
-
if (args.approvals !== null &&
|
|
37
|
+
if (args.approvals !== null && !isValidApprovalCount(args.approvals)) {
|
|
37
38
|
throw new Error("--required-approvals must be an integer between 0 and 6.");
|
|
38
39
|
}
|
|
39
40
|
|
|
40
41
|
return args;
|
|
41
42
|
}
|
|
42
43
|
|
|
44
|
+
function isValidApprovalCount(value) {
|
|
45
|
+
return Number.isInteger(value) && value >= 0 && value <= 6;
|
|
46
|
+
}
|
|
47
|
+
|
|
43
48
|
function printHelp() {
|
|
44
49
|
console.log(`setup-github-rules
|
|
45
50
|
|
|
@@ -53,7 +58,7 @@ Usage:
|
|
|
53
58
|
Options:
|
|
54
59
|
--repo OWNER/REPO Target repository. Defaults to current git remote.
|
|
55
60
|
--branch BRANCH Default branch to set and protect. Skips branch prompt.
|
|
56
|
-
--required-approvals N Required approving reviews.
|
|
61
|
+
--required-approvals N Required approving reviews. If omitted, prompt with default 1.
|
|
57
62
|
--ruleset-name NAME Ruleset name. Default: "Require PR to <branch>".
|
|
58
63
|
--yes, -y Skip final confirmation.
|
|
59
64
|
--dry-run Print planned operations without changing GitHub.
|
|
@@ -168,6 +173,29 @@ async function selectBranch(rl, preselectedBranch) {
|
|
|
168
173
|
}
|
|
169
174
|
}
|
|
170
175
|
|
|
176
|
+
export async function selectApprovals(rl, preselectedApprovals) {
|
|
177
|
+
if (preselectedApprovals !== null) return preselectedApprovals;
|
|
178
|
+
|
|
179
|
+
console.log("\nChoose the number of required approving reviews.");
|
|
180
|
+
console.log("Use 0 for solo repositories where nobody else can approve your PR.");
|
|
181
|
+
|
|
182
|
+
while (true) {
|
|
183
|
+
const answer = (await rl.question("Required approvals [0-6] (default: 1): ")).trim();
|
|
184
|
+
const approvals = answer === "" ? 1 : Number(answer);
|
|
185
|
+
if (isValidApprovalCount(approvals)) return approvals;
|
|
186
|
+
console.log("Please enter an integer between 0 and 6.");
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
export async function resolveApprovals(rl, {
|
|
191
|
+
preselectedApprovals,
|
|
192
|
+
isInteractive
|
|
193
|
+
}) {
|
|
194
|
+
if (preselectedApprovals !== null) return preselectedApprovals;
|
|
195
|
+
if (!isInteractive) return 1;
|
|
196
|
+
return selectApprovals(rl, null);
|
|
197
|
+
}
|
|
198
|
+
|
|
171
199
|
function isValidBranchName(branch) {
|
|
172
200
|
return Boolean(branch) &&
|
|
173
201
|
!branch.startsWith("/") &&
|
|
@@ -253,7 +281,10 @@ async function main() {
|
|
|
253
281
|
const repoInfo = ghApi(`/repos/${owner}/${repo}`);
|
|
254
282
|
const currentDefaultBranch = repoInfo.default_branch;
|
|
255
283
|
const selectedBranch = await selectBranch(rl, args.branch);
|
|
256
|
-
const approvals =
|
|
284
|
+
const approvals = await resolveApprovals(rl, {
|
|
285
|
+
preselectedApprovals: args.approvals,
|
|
286
|
+
isInteractive: Boolean(input.isTTY && output.isTTY)
|
|
287
|
+
});
|
|
257
288
|
const rulesetName = args.rulesetName ?? `${DEFAULT_RULESET_NAME_PREFIX} ${selectedBranch}`;
|
|
258
289
|
|
|
259
290
|
console.log("\nPlan:");
|
|
@@ -318,7 +349,9 @@ async function main() {
|
|
|
318
349
|
}
|
|
319
350
|
}
|
|
320
351
|
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
352
|
+
if (process.argv[1] && path.resolve(process.argv[1]) === fileURLToPath(import.meta.url)) {
|
|
353
|
+
main().catch((error) => {
|
|
354
|
+
console.error(`\nError: ${error.message}`);
|
|
355
|
+
process.exit(1);
|
|
356
|
+
});
|
|
357
|
+
}
|
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lilpacy/setup-github-rules",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "One-shot interactive GitHub repository rules setup using gh CLI. No Terraform state, no generated files.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
|
-
"setup-github-rules": "
|
|
7
|
+
"setup-github-rules": "bin/setup-github-rules.js"
|
|
8
8
|
},
|
|
9
9
|
"files": [
|
|
10
10
|
"bin/",
|