@asagiri-design/labels-config 0.2.2 → 0.3.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.
@@ -1,7 +1,9 @@
1
1
  "use strict";
2
+ var __create = Object.create;
2
3
  var __defProp = Object.defineProperty;
3
4
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
5
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
5
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
6
8
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
7
9
  var __export = (target, all) => {
@@ -16,12 +18,21 @@ var __copyProps = (to, from, except, desc) => {
16
18
  }
17
19
  return to;
18
20
  };
21
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
22
+ // If the importer is in node compatibility mode or this is not an ESM
23
+ // file that has been converted to a CommonJS file using a Babel-
24
+ // compatible transform (i.e. "__esModule" has not been set), then set
25
+ // "default" to the CommonJS "module.exports" for node compatibility.
26
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
27
+ mod
28
+ ));
19
29
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
20
30
  var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
21
31
 
22
32
  // src/github/index.ts
23
33
  var github_exports = {};
24
34
  __export(github_exports, {
35
+ BatchLabelSync: () => BatchLabelSync,
25
36
  GitHubClient: () => GitHubClient,
26
37
  GitHubLabelSync: () => GitHubLabelSync
27
38
  });
@@ -303,8 +314,209 @@ var _GitHubLabelSync = class _GitHubLabelSync {
303
314
  };
304
315
  __publicField(_GitHubLabelSync, "BATCH_SIZE", 5);
305
316
  var GitHubLabelSync = _GitHubLabelSync;
317
+
318
+ // src/utils/ui.ts
319
+ var colors = {
320
+ reset: "\x1B[0m",
321
+ bright: "\x1B[1m",
322
+ dim: "\x1B[2m",
323
+ // Foreground colors
324
+ red: "\x1B[31m",
325
+ green: "\x1B[32m",
326
+ yellow: "\x1B[33m",
327
+ blue: "\x1B[34m",
328
+ magenta: "\x1B[35m",
329
+ cyan: "\x1B[36m",
330
+ white: "\x1B[37m",
331
+ gray: "\x1B[90m",
332
+ // Background colors
333
+ bgRed: "\x1B[41m",
334
+ bgGreen: "\x1B[42m",
335
+ bgYellow: "\x1B[43m",
336
+ bgBlue: "\x1B[44m"
337
+ };
338
+ function supportsColor() {
339
+ if (process.env.NO_COLOR) {
340
+ return false;
341
+ }
342
+ if (process.env.FORCE_COLOR) {
343
+ return true;
344
+ }
345
+ if (!process.stdout.isTTY) {
346
+ return false;
347
+ }
348
+ if (process.platform === "win32") {
349
+ return true;
350
+ }
351
+ return true;
352
+ }
353
+ function colorize(text, color) {
354
+ if (!supportsColor()) {
355
+ return text;
356
+ }
357
+ return `${colors[color]}${text}${colors.reset}`;
358
+ }
359
+
360
+ // src/github/batch-sync.ts
361
+ var _BatchLabelSync = class _BatchLabelSync {
362
+ /**
363
+ * 複数リポジトリへのラベル一括同期
364
+ */
365
+ async syncMultiple(labels, options) {
366
+ const repos = await this.getTargetRepositories(options);
367
+ const results = [];
368
+ console.log(colorize(`
369
+ \u{1F4CB} Target repositories: ${repos.length}`, "cyan"));
370
+ let completed = 0;
371
+ const parallel = options.parallel || _BatchLabelSync.DEFAULT_PARALLEL;
372
+ for (let i = 0; i < repos.length; i += parallel) {
373
+ const batch = repos.slice(i, i + parallel);
374
+ const batchResults = await Promise.allSettled(
375
+ batch.map((repo) => this.syncSingleRepo(repo, labels, options))
376
+ );
377
+ batchResults.forEach((result, index) => {
378
+ const repo = batch[index];
379
+ if (result.status === "fulfilled") {
380
+ results.push(result.value);
381
+ completed++;
382
+ console.log(colorize(`\u2705 [${completed}/${repos.length}] ${repo}`, "green"));
383
+ } else {
384
+ results.push({
385
+ repository: repo,
386
+ status: "failed",
387
+ error: result.reason?.message || "Unknown error"
388
+ });
389
+ completed++;
390
+ console.log(colorize(`\u274C [${completed}/${repos.length}] ${repo}: ${result.reason}`, "red"));
391
+ }
392
+ });
393
+ }
394
+ return results;
395
+ }
396
+ /**
397
+ * 単一リポジトリへの同期
398
+ */
399
+ async syncSingleRepo(repository, labels, options) {
400
+ try {
401
+ const [owner, repo] = repository.split("/");
402
+ if (!owner || !repo) {
403
+ throw new Error(`Invalid repository format: ${repository}. Expected format: owner/repo`);
404
+ }
405
+ const sync = new GitHubLabelSync({
406
+ owner,
407
+ repo,
408
+ deleteExtra: options.mode === "replace",
409
+ dryRun: options.dryRun || false
410
+ });
411
+ const result = await sync.syncLabels(labels);
412
+ return {
413
+ repository,
414
+ status: "success",
415
+ result
416
+ };
417
+ } catch (error) {
418
+ return {
419
+ repository,
420
+ status: "failed",
421
+ error: error instanceof Error ? error.message : "Unknown error"
422
+ };
423
+ }
424
+ }
425
+ /**
426
+ * 対象リポジトリリストの取得
427
+ */
428
+ async getTargetRepositories(options) {
429
+ if (options.repositories && options.repositories.length > 0) {
430
+ return options.repositories;
431
+ }
432
+ if (options.organization) {
433
+ return this.getOrganizationRepos(options.organization, options.filter);
434
+ }
435
+ if (options.user) {
436
+ return this.getUserRepos(options.user, options.filter);
437
+ }
438
+ throw new Error("No target repositories specified");
439
+ }
440
+ /**
441
+ * 組織のリポジトリ一覧を取得
442
+ */
443
+ async getOrganizationRepos(org, filter) {
444
+ const { execSync: execSync2 } = await import("child_process");
445
+ try {
446
+ const command = `gh repo list ${org} --json nameWithOwner,visibility,language,isArchived --limit 1000`;
447
+ const output = execSync2(command, { encoding: "utf-8" });
448
+ const repos = JSON.parse(output);
449
+ return repos.filter((repo) => {
450
+ if (filter?.visibility && filter.visibility !== "all" && repo.visibility !== filter.visibility) {
451
+ return false;
452
+ }
453
+ if (filter?.language && repo.language !== filter.language) {
454
+ return false;
455
+ }
456
+ if (filter?.archived !== void 0 && repo.isArchived !== filter.archived) {
457
+ return false;
458
+ }
459
+ return true;
460
+ }).map((repo) => repo.nameWithOwner);
461
+ } catch (error) {
462
+ throw new Error(`Failed to fetch organization repos: ${error}`);
463
+ }
464
+ }
465
+ /**
466
+ * ユーザーのリポジトリ一覧を取得
467
+ */
468
+ async getUserRepos(user, filter) {
469
+ const { execSync: execSync2 } = await import("child_process");
470
+ try {
471
+ const command = `gh repo list ${user} --json nameWithOwner,visibility,language,isArchived --limit 1000`;
472
+ const output = execSync2(command, { encoding: "utf-8" });
473
+ const repos = JSON.parse(output);
474
+ return repos.filter((repo) => {
475
+ if (filter?.visibility && filter.visibility !== "all" && repo.visibility !== filter.visibility) {
476
+ return false;
477
+ }
478
+ if (filter?.language && repo.language !== filter.language) {
479
+ return false;
480
+ }
481
+ if (filter?.archived !== void 0 && repo.isArchived !== filter.archived) {
482
+ return false;
483
+ }
484
+ return true;
485
+ }).map((repo) => repo.nameWithOwner);
486
+ } catch (error) {
487
+ throw new Error(`Failed to fetch user repos: ${error}`);
488
+ }
489
+ }
490
+ /**
491
+ * 結果サマリーの生成
492
+ */
493
+ generateSummary(results) {
494
+ const successful = results.filter((r) => r.status === "success").length;
495
+ const failed = results.filter((r) => r.status === "failed").length;
496
+ const skipped = results.filter((r) => r.status === "skipped").length;
497
+ let summary = "\n\u{1F4CA} Batch Sync Summary:\n";
498
+ summary += `\u2705 Successful: ${successful}
499
+ `;
500
+ if (failed > 0) summary += `\u274C Failed: ${failed}
501
+ `;
502
+ if (skipped > 0) summary += `\u23ED\uFE0F Skipped: ${skipped}
503
+ `;
504
+ const failedRepos = results.filter((r) => r.status === "failed");
505
+ if (failedRepos.length > 0) {
506
+ summary += "\n\u274C Failed repositories:\n";
507
+ failedRepos.forEach((repo) => {
508
+ summary += ` - ${repo.repository}: ${repo.error}
509
+ `;
510
+ });
511
+ }
512
+ return summary;
513
+ }
514
+ };
515
+ __publicField(_BatchLabelSync, "DEFAULT_PARALLEL", 3);
516
+ var BatchLabelSync = _BatchLabelSync;
306
517
  // Annotate the CommonJS export names for ESM import in node:
307
518
  0 && (module.exports = {
519
+ BatchLabelSync,
308
520
  GitHubClient,
309
521
  GitHubLabelSync
310
522
  });
@@ -1,9 +1,11 @@
1
1
  import {
2
+ BatchLabelSync,
2
3
  GitHubClient,
3
4
  GitHubLabelSync
4
- } from "../chunk-4ZUJQMV7.mjs";
5
+ } from "../chunk-MM4GCVPE.mjs";
5
6
  import "../chunk-QZ7TP4HQ.mjs";
6
7
  export {
8
+ BatchLabelSync,
7
9
  GitHubClient,
8
10
  GitHubLabelSync
9
11
  };
package/dist/index.d.mts CHANGED
@@ -292,7 +292,7 @@ declare class LabelManager {
292
292
  };
293
293
  }
294
294
 
295
- declare const version = "0.2.2";
295
+ declare const version = "0.3.0";
296
296
 
297
297
  /**
298
298
  * @boxpistols/labels-config
package/dist/index.d.ts CHANGED
@@ -292,7 +292,7 @@ declare class LabelManager {
292
292
  };
293
293
  }
294
294
 
295
- declare const version = "0.2.2";
295
+ declare const version = "0.3.0";
296
296
 
297
297
  /**
298
298
  * @boxpistols/labels-config
package/dist/index.js CHANGED
@@ -279,7 +279,7 @@ var LabelManager = class {
279
279
  };
280
280
 
281
281
  // src/version.ts
282
- var version = "0.2.2";
282
+ var version = "0.3.0";
283
283
 
284
284
  // src/index.ts
285
285
  var index_default = {
package/dist/index.mjs CHANGED
@@ -17,7 +17,7 @@ import {
17
17
  import "./chunk-QZ7TP4HQ.mjs";
18
18
 
19
19
  // src/version.ts
20
- var version = "0.2.2";
20
+ var version = "0.3.0";
21
21
 
22
22
  // src/index.ts
23
23
  var index_default = {
@@ -0,0 +1,396 @@
1
+ # Batch Sync - 複数リポジトリ一括ラベル管理
2
+
3
+ `labels-config` の Batch Sync 機能を使用すると、複数のGitHubリポジトリに対して一括でラベルを同期できます。
4
+
5
+ ## 主要機能
6
+
7
+ ### 1. コマンドラインからの一括同期 (`batch-sync`)
8
+
9
+ 複数のリポジトリに対して、コマンドラインから直接ラベルを同期できます。
10
+
11
+ #### 組織全体のリポジトリに同期
12
+
13
+ ```bash
14
+ # 組織の全リポジトリにテンプレートを適用
15
+ labels-config batch-sync --org BoxPistols --template prod-ja
16
+
17
+ # ドライランで確認
18
+ labels-config batch-sync --org BoxPistols --template prod-ja --dry-run
19
+
20
+ # 特定の言語でフィルタリング
21
+ labels-config batch-sync --org BoxPistols --template react --filter-lang TypeScript
22
+
23
+ # 公開リポジトリのみに適用
24
+ labels-config batch-sync --org BoxPistols --template prod-ja --filter-vis public
25
+ ```
26
+
27
+ #### ユーザーの全リポジトリに同期
28
+
29
+ ```bash
30
+ # ユーザーの全リポジトリに同期
31
+ labels-config batch-sync --user BoxPistols --template prod-ja
32
+
33
+ # プライベートリポジトリのみ
34
+ labels-config batch-sync --user BoxPistols --template prod-ja --filter-vis private
35
+ ```
36
+
37
+ #### 特定のリポジトリリストに同期
38
+
39
+ ```bash
40
+ # カスタムラベルファイルを使用
41
+ labels-config batch-sync \
42
+ --repos BoxPistols/repo1,BoxPistols/repo2,BoxPistols/repo3 \
43
+ --file ./custom-labels.json
44
+
45
+ # テンプレートを使用
46
+ labels-config batch-sync \
47
+ --repos BoxPistols/repo1,BoxPistols/repo2 \
48
+ --template prod-ja
49
+ ```
50
+
51
+ #### オプション
52
+
53
+ | オプション | 説明 | 例 |
54
+ |-----------|------|-----|
55
+ | `--org <name>` | 組織名 | `--org BoxPistols` |
56
+ | `--user <name>` | ユーザー名 | `--user BoxPistols` |
57
+ | `--repos <list>` | リポジトリリスト(カンマ区切り) | `--repos owner/repo1,owner/repo2` |
58
+ | `--template <name>` | テンプレート名 | `--template prod-ja` |
59
+ | `--file <path>` | カスタムラベルファイル | `--file ./labels.json` |
60
+ | `--filter-lang <lang>` | プログラミング言語でフィルタ | `--filter-lang TypeScript` |
61
+ | `--filter-vis <vis>` | 可視性でフィルタ | `--filter-vis public` |
62
+ | `--parallel <num>` | 並列実行数(デフォルト: 3) | `--parallel 5` |
63
+ | `--dry-run` | ドライラン(実際には変更しない) | `--dry-run` |
64
+ | `--delete-extra` | 設定にないラベルを削除(Replace モード) | `--delete-extra` |
65
+
66
+ ---
67
+
68
+ ### 2. 設定ファイルからの一括同期 (`batch-config`)
69
+
70
+ 複雑な一括同期設定を JSON ファイルで定義して実行できます。
71
+
72
+ #### 設定ファイルの作成
73
+
74
+ ```json
75
+ {
76
+ "version": "1.0.0",
77
+ "description": "BoxPistols organization batch label sync",
78
+ "defaults": {
79
+ "template": "prod-ja",
80
+ "mode": "append",
81
+ "parallel": 3
82
+ },
83
+ "targets": [
84
+ {
85
+ "organization": "BoxPistols",
86
+ "filter": {
87
+ "visibility": "public",
88
+ "language": "TypeScript",
89
+ "archived": false
90
+ },
91
+ "template": "react",
92
+ "mode": "append"
93
+ },
94
+ {
95
+ "repositories": [
96
+ "BoxPistols/labels-config",
97
+ "BoxPistols/my-project"
98
+ ],
99
+ "template": "prod-ja",
100
+ "mode": "replace"
101
+ },
102
+ {
103
+ "user": "BoxPistols",
104
+ "filter": {
105
+ "visibility": "private"
106
+ },
107
+ "file": "./custom-labels.json"
108
+ }
109
+ ]
110
+ }
111
+ ```
112
+
113
+ #### 設定ファイルの実行
114
+
115
+ ```bash
116
+ # 設定ファイルを実行
117
+ labels-config batch-config batch-config.json
118
+
119
+ # ドライランで確認
120
+ labels-config batch-config batch-config.json --dry-run
121
+ ```
122
+
123
+ #### 設定ファイルの構造
124
+
125
+ **ルート要素:**
126
+
127
+ | フィールド | 型 | 必須 | 説明 |
128
+ |-----------|-----|------|------|
129
+ | `version` | string | ✓ | 設定ファイルのバージョン |
130
+ | `description` | string | | 説明 |
131
+ | `defaults` | object | | デフォルト設定 |
132
+ | `targets` | array | ✓ | ターゲット設定のリスト |
133
+
134
+ **defaults オブジェクト:**
135
+
136
+ | フィールド | 型 | デフォルト | 説明 |
137
+ |-----------|-----|-----------|------|
138
+ | `template` | string | | デフォルトテンプレート |
139
+ | `mode` | `"append"` \| `"replace"` | `"append"` | デフォルト同期モード |
140
+ | `parallel` | number | `3` | デフォルト並列実行数 |
141
+
142
+ **target オブジェクト:**
143
+
144
+ | フィールド | 型 | 必須 | 説明 |
145
+ |-----------|-----|------|------|
146
+ | `organization` | string | * | 組織名 |
147
+ | `user` | string | * | ユーザー名 |
148
+ | `repositories` | string[] | * | リポジトリリスト |
149
+ | `template` | string | ** | テンプレート名 |
150
+ | `file` | string | ** | ラベルファイルパス |
151
+ | `mode` | `"append"` \| `"replace"` | | 同期モード |
152
+ | `parallel` | number | | 並列実行数 |
153
+ | `filter` | object | | フィルタ設定 |
154
+
155
+ \* いずれか1つ必須
156
+ \*\* いずれか1つ必須
157
+
158
+ **filter オブジェクト:**
159
+
160
+ | フィールド | 型 | 説明 |
161
+ |-----------|-----|------|
162
+ | `visibility` | `"public"` \| `"private"` \| `"all"` | リポジトリの可視性 |
163
+ | `language` | string | プログラミング言語 |
164
+ | `archived` | boolean | アーカイブ済みリポジトリを含むか |
165
+
166
+ ---
167
+
168
+ ## 同期モード
169
+
170
+ ### Append モード(デフォルト)
171
+
172
+ - 新しいラベルを追加
173
+ - 既存のラベルを更新
174
+ - 設定にないラベルは**保持**
175
+
176
+ ```bash
177
+ labels-config batch-sync --org BoxPistols --template prod-ja
178
+ ```
179
+
180
+ ### Replace モード
181
+
182
+ - 新しいラベルを追加
183
+ - 既存のラベルを更新
184
+ - 設定にないラベルを**削除**
185
+
186
+ ```bash
187
+ labels-config batch-sync --org BoxPistols --template prod-ja --delete-extra
188
+ ```
189
+
190
+ ---
191
+
192
+ ## 利用例
193
+
194
+ ### 例1: 組織の全TypeScriptリポジトリにReactテンプレートを適用
195
+
196
+ ```bash
197
+ labels-config batch-sync \
198
+ --org BoxPistols \
199
+ --template react \
200
+ --filter-lang TypeScript \
201
+ --filter-vis public \
202
+ --dry-run
203
+ ```
204
+
205
+ ### 例2: 複数の設定を一度に実行
206
+
207
+ batch-config.json:
208
+ ```json
209
+ {
210
+ "version": "1.0.0",
211
+ "defaults": {
212
+ "parallel": 5
213
+ },
214
+ "targets": [
215
+ {
216
+ "organization": "BoxPistols",
217
+ "filter": { "language": "TypeScript" },
218
+ "template": "react"
219
+ },
220
+ {
221
+ "organization": "BoxPistols",
222
+ "filter": { "language": "Go" },
223
+ "template": "minimal"
224
+ },
225
+ {
226
+ "repositories": ["BoxPistols/special-project"],
227
+ "file": "./special-labels.json",
228
+ "mode": "replace"
229
+ }
230
+ ]
231
+ }
232
+ ```
233
+
234
+ 実行:
235
+ ```bash
236
+ labels-config batch-config batch-config.json
237
+ ```
238
+
239
+ ### 例3: 新規リポジトリへのラベル自動設置(GitHub Actionsと組み合わせ)
240
+
241
+ `.github/workflows/auto-label.yml`:
242
+ ```yaml
243
+ name: Auto Label New Repositories
244
+ on:
245
+ repository_dispatch:
246
+ types: [new-repo-created]
247
+
248
+ jobs:
249
+ apply-labels:
250
+ runs-on: ubuntu-latest
251
+ steps:
252
+ - uses: actions/checkout@v4
253
+
254
+ - name: Setup Node.js
255
+ uses: actions/setup-node@v4
256
+ with:
257
+ node-version: '20'
258
+
259
+ - name: Install labels-config
260
+ run: npm install -g @asagiri-design/labels-config
261
+
262
+ - name: Apply labels
263
+ run: |
264
+ labels-config batch-sync \
265
+ --repos ${{ github.event.client_payload.repository }} \
266
+ --template prod-ja
267
+ env:
268
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
269
+ ```
270
+
271
+ ---
272
+
273
+ ## パフォーマンス最適化
274
+
275
+ ### 並列処理
276
+
277
+ デフォルトでは3つのリポジトリを並列処理します。`--parallel` オプションで調整可能:
278
+
279
+ ```bash
280
+ # 並列数を増やす(高速化)
281
+ labels-config batch-sync --org BoxPistols --template prod-ja --parallel 10
282
+
283
+ # 並列数を減らす(安定性重視)
284
+ labels-config batch-sync --org BoxPistols --template prod-ja --parallel 1
285
+ ```
286
+
287
+ ### レート制限への対応
288
+
289
+ GitHub API のレート制限を考慮して、並列数を調整してください:
290
+
291
+ - **認証済み**: 5000リクエスト/時間
292
+ - **並列数3**: 約100リポジトリ/分
293
+ - **並列数10**: 約300リポジトリ/分
294
+
295
+ ---
296
+
297
+ ## エラーハンドリング
298
+
299
+ ### 部分的な失敗
300
+
301
+ 一部のリポジトリで失敗しても、他のリポジトリの処理は継続されます:
302
+
303
+ ```
304
+ ✅ [1/10] BoxPistols/repo1
305
+ ❌ [2/10] BoxPistols/repo2: Permission denied
306
+ ✅ [3/10] BoxPistols/repo3
307
+ ...
308
+
309
+ 📊 Batch Sync Summary:
310
+ ✅ Successful: 8
311
+ ❌ Failed: 2
312
+
313
+ ❌ Failed repositories:
314
+ - BoxPistols/repo2: Permission denied
315
+ - BoxPistols/repo5: Repository not found
316
+ ```
317
+
318
+ ### ドライランでの事前確認
319
+
320
+ 本番実行前に必ずドライランで確認してください:
321
+
322
+ ```bash
323
+ labels-config batch-sync --org BoxPistols --template prod-ja --dry-run
324
+ ```
325
+
326
+ ---
327
+
328
+ ## よくある質問
329
+
330
+ ### Q: 新規リポジトリ作成時に自動でラベルを設置できますか?
331
+
332
+ A: はい、GitHub Actions と組み合わせることで可能です。上記の「例3」を参照してください。
333
+
334
+ ### Q: 既存のラベルを削除せずに追加だけできますか?
335
+
336
+ A: はい、デフォルトの Append モードで可能です(`--delete-extra` を指定しない)。
337
+
338
+ ### Q: 組織の全リポジトリに一括適用できますか?
339
+
340
+ A: はい、`--org` オプションで可能です:
341
+ ```bash
342
+ labels-config batch-sync --org BoxPistols --template prod-ja
343
+ ```
344
+
345
+ ### Q: 特定の条件でフィルタリングできますか?
346
+
347
+ A: はい、以下のフィルタが利用可能です:
348
+ - プログラミング言語(`--filter-lang`)
349
+ - 可視性(`--filter-vis`)
350
+ - アーカイブ状態(設定ファイルのみ)
351
+
352
+ ---
353
+
354
+ ## トラブルシューティング
355
+
356
+ ### 権限エラー
357
+
358
+ ```
359
+ Error: Permission denied for BoxPistols/repo1
360
+ ```
361
+
362
+ **解決方法:**
363
+ 1. `gh auth status` で認証状態を確認
364
+ 2. `gh auth refresh` で認証を更新
365
+ 3. リポジトリへの管理者権限を確認
366
+
367
+ ### レート制限エラー
368
+
369
+ ```
370
+ Error: API rate limit exceeded
371
+ ```
372
+
373
+ **解決方法:**
374
+ 1. 並列数を減らす(`--parallel 1`)
375
+ 2. 時間を置いて再実行
376
+ 3. GitHub Token の認証状態を確認
377
+
378
+ ### リポジトリが見つからない
379
+
380
+ ```
381
+ Error: Repository not found: BoxPistols/repo1
382
+ ```
383
+
384
+ **解決方法:**
385
+ 1. リポジトリ名のスペルを確認
386
+ 2. リポジトリへのアクセス権限を確認
387
+ 3. `gh repo list BoxPistols` でリポジトリ一覧を確認
388
+
389
+ ---
390
+
391
+ ## 参考資料
392
+
393
+ - [Getting Started](./GETTING_STARTED.md)
394
+ - [API Documentation](./API.md)
395
+ - [Templates](../templates/)
396
+ - [Examples](../examples/)