@lilpacy/setup-github-rules 0.1.1 → 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 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 && (!Number.isInteger(args.approvals) || args.approvals < 0 || args.approvals > 6)) {
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. Default: 1.
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 = args.approvals ?? 1;
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
- main().catch((error) => {
322
- console.error(`\nError: ${error.message}`);
323
- process.exit(1);
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,6 +1,6 @@
1
1
  {
2
2
  "name": "@lilpacy/setup-github-rules",
3
- "version": "0.1.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": {