github-labels-template 0.6.0 โ 0.6.1-staging.3ace40c
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 +49 -7
- package/dist/index.js +189 -96
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -14,7 +14,9 @@ A CLI tool to apply a curated set of GitHub labels to any repository using `gh`
|
|
|
14
14
|
- ๐ **One Command Setup**: Apply all labels to any repo with `ghlt apply`
|
|
15
15
|
- ๐ **Auto-Detect Repo**: Automatically detects the current repository from git remote
|
|
16
16
|
- ๐ **Smart Conflict Handling**: Skips existing labels by default, `--force` to update
|
|
17
|
-
-
|
|
17
|
+
- ๐ **List Command**: View all labels on any repo โ name, color, and description at a glance
|
|
18
|
+
- ๐งน **Wipe Command**: Remove all or specific labels with a confirmation prompt
|
|
19
|
+
- ๐ซ **Apply with Exclusions**: Skip specific labels or entire categories with `--exclude` / `--exclude-category`
|
|
18
20
|
- โ
**Pre-Flight Checks**: Validates `gh` CLI is installed and authenticated before doing anything
|
|
19
21
|
- ๐ **Clear Output**: Structured logging powered by [@wgtechlabs/log-engine](https://github.com/wgtechlabs/log-engine) with color-coded levels and emoji
|
|
20
22
|
- ๐จ **ASCII Banner**: Beautiful ANSI Shadow figlet banner with version and author info
|
|
@@ -83,6 +85,15 @@ ghlt apply --category community --label bug
|
|
|
83
85
|
# Combine with force and repo
|
|
84
86
|
ghlt apply --category type --force --repo owner/repo
|
|
85
87
|
|
|
88
|
+
# Apply all labels except specific ones
|
|
89
|
+
ghlt apply --exclude "bug,enhancement"
|
|
90
|
+
|
|
91
|
+
# Apply all labels except an entire category
|
|
92
|
+
ghlt apply --exclude-category type
|
|
93
|
+
|
|
94
|
+
# Combine: apply all community labels except hacktoberfest
|
|
95
|
+
ghlt apply --category community --exclude hacktoberfest
|
|
96
|
+
|
|
86
97
|
# Include custom labels from labels-custom.json
|
|
87
98
|
ghlt apply --custom
|
|
88
99
|
|
|
@@ -90,6 +101,16 @@ ghlt apply --custom
|
|
|
90
101
|
ghlt apply --custom --category type
|
|
91
102
|
```
|
|
92
103
|
|
|
104
|
+
### List Labels
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
# List all labels on the current repo
|
|
108
|
+
ghlt list
|
|
109
|
+
|
|
110
|
+
# List labels on a specific repo
|
|
111
|
+
ghlt list --repo owner/repo
|
|
112
|
+
```
|
|
113
|
+
|
|
93
114
|
### Generate Labels (AI)
|
|
94
115
|
|
|
95
116
|
Generate custom labels using GitHub Copilot โ following the Clean Labels convention. Requires a [GitHub Copilot](https://github.com/features/copilot) subscription.
|
|
@@ -145,6 +166,18 @@ ghlt wipe --repo owner/repo
|
|
|
145
166
|
|
|
146
167
|
# Skip confirmation prompt
|
|
147
168
|
ghlt wipe --yes
|
|
169
|
+
|
|
170
|
+
# Remove specific labels
|
|
171
|
+
ghlt wipe --label "bug,enhancement"
|
|
172
|
+
|
|
173
|
+
# Remove all labels from a category
|
|
174
|
+
ghlt wipe --category type
|
|
175
|
+
|
|
176
|
+
# Remove labels from multiple categories
|
|
177
|
+
ghlt wipe --category "type,status"
|
|
178
|
+
|
|
179
|
+
# Include custom labels in the selective wipe scope
|
|
180
|
+
ghlt wipe --category type --custom
|
|
148
181
|
```
|
|
149
182
|
|
|
150
183
|
### Preview Landing Page
|
|
@@ -243,24 +276,30 @@ Broad software layers โ universal across any project.
|
|
|
243
276
|
ghlt โ GitHub Labels Template CLI
|
|
244
277
|
|
|
245
278
|
USAGE
|
|
246
|
-
ghlt [OPTIONS] apply|wipe|migrate|generate|preview
|
|
279
|
+
ghlt [OPTIONS] apply|wipe|migrate|generate|list|preview
|
|
247
280
|
|
|
248
281
|
OPTIONS
|
|
249
282
|
-v, --version Show version number
|
|
250
283
|
|
|
251
284
|
COMMANDS
|
|
252
285
|
apply Apply labels from the template to a repository
|
|
253
|
-
wipe Remove all
|
|
286
|
+
wipe Remove all or specific labels from a repository
|
|
254
287
|
migrate Wipe all existing labels and apply the template (clean slate)
|
|
255
288
|
generate Generate custom labels using AI (requires GitHub Copilot)
|
|
289
|
+
list List all labels in a repository
|
|
256
290
|
preview Preview the landing page locally in your browser
|
|
257
291
|
|
|
258
292
|
OPTIONS (apply)
|
|
293
|
+
-r, --repo <owner/repo> Target repository (default: auto-detect)
|
|
294
|
+
-f, --force Overwrite existing labels
|
|
295
|
+
-l, --label <name> Apply specific label(s) by name (comma-separated)
|
|
296
|
+
-c, --category <name> Apply labels from specific category(ies) (comma-separated)
|
|
297
|
+
-e, --exclude <name> Exclude specific label(s) by name (comma-separated)
|
|
298
|
+
--exclude-category <name> Exclude labels from specific category(ies) (comma-separated)
|
|
299
|
+
--custom Include custom labels from labels-custom.json
|
|
300
|
+
|
|
301
|
+
OPTIONS (list)
|
|
259
302
|
-r, --repo <owner/repo> Target repository (default: auto-detect)
|
|
260
|
-
-f, --force Overwrite existing labels
|
|
261
|
-
-l, --label <name> Apply specific label(s) by name (comma-separated)
|
|
262
|
-
-c, --category <name> Apply labels from specific category(ies) (comma-separated)
|
|
263
|
-
--custom Include custom labels from labels-custom.json
|
|
264
303
|
|
|
265
304
|
OPTIONS (migrate)
|
|
266
305
|
-r, --repo <owner/repo> Target repository (default: auto-detect)
|
|
@@ -275,6 +314,9 @@ OPTIONS (generate)
|
|
|
275
314
|
OPTIONS (wipe)
|
|
276
315
|
-r, --repo <owner/repo> Target repository (default: auto-detect)
|
|
277
316
|
-y, --yes Skip confirmation prompt
|
|
317
|
+
-l, --label <name> Remove specific label(s) by name (comma-separated)
|
|
318
|
+
-c, --category <name> Remove labels from specific category(ies) (comma-separated)
|
|
319
|
+
--custom Include custom labels when using --label or --category
|
|
278
320
|
|
|
279
321
|
OPTIONS (preview)
|
|
280
322
|
-p, --port <number> Port to serve on (default: 3000)
|
package/dist/index.js
CHANGED
|
@@ -52,6 +52,28 @@ async function detectRepo() {
|
|
|
52
52
|
return null;
|
|
53
53
|
}
|
|
54
54
|
}
|
|
55
|
+
async function listLabelsDetailed(repo) {
|
|
56
|
+
const { exitCode, stdout } = await run([
|
|
57
|
+
"label",
|
|
58
|
+
"list",
|
|
59
|
+
"--repo",
|
|
60
|
+
repo,
|
|
61
|
+
"--json",
|
|
62
|
+
"name,color,description",
|
|
63
|
+
"--limit",
|
|
64
|
+
"100"
|
|
65
|
+
]);
|
|
66
|
+
if (exitCode !== 0)
|
|
67
|
+
return [];
|
|
68
|
+
const text = stdout.trim();
|
|
69
|
+
if (!text)
|
|
70
|
+
return [];
|
|
71
|
+
try {
|
|
72
|
+
return JSON.parse(text);
|
|
73
|
+
} catch {
|
|
74
|
+
return [];
|
|
75
|
+
}
|
|
76
|
+
}
|
|
55
77
|
async function listLabels(repo) {
|
|
56
78
|
const { exitCode, stdout } = await run([
|
|
57
79
|
"label",
|
|
@@ -161,7 +183,9 @@ function filterLabels(allLabels, options) {
|
|
|
161
183
|
const warnings = [];
|
|
162
184
|
const labelFilter = options.label ? options.label.split(",").map((l) => l.trim().toLowerCase()).filter(Boolean) : null;
|
|
163
185
|
const categoryFilter = options.category ? options.category.split(",").map((c) => c.trim().toLowerCase()).filter(Boolean) : null;
|
|
164
|
-
|
|
186
|
+
const excludeLabelFilter = options.excludeLabel ? options.excludeLabel.split(",").map((l) => l.trim().toLowerCase()).filter(Boolean) : null;
|
|
187
|
+
const excludeCategoryFilter = options.excludeCategory ? options.excludeCategory.split(",").map((c) => c.trim().toLowerCase()).filter(Boolean) : null;
|
|
188
|
+
if (!labelFilter && !categoryFilter && !excludeLabelFilter && !excludeCategoryFilter) {
|
|
165
189
|
return {
|
|
166
190
|
entries: Object.entries(allLabels),
|
|
167
191
|
warnings
|
|
@@ -183,7 +207,25 @@ function filterLabels(allLabels, options) {
|
|
|
183
207
|
}
|
|
184
208
|
}
|
|
185
209
|
}
|
|
186
|
-
|
|
210
|
+
if (excludeCategoryFilter) {
|
|
211
|
+
for (const cat of excludeCategoryFilter) {
|
|
212
|
+
if (!validCategories.includes(cat)) {
|
|
213
|
+
warnings.push(`Unknown exclude category "${cat}". Valid categories: ${validCategories.join(", ")}`);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
if (excludeLabelFilter) {
|
|
218
|
+
const allLabelNames = Object.values(allLabels).flat().map((l) => l.name.toLowerCase());
|
|
219
|
+
for (const name of excludeLabelFilter) {
|
|
220
|
+
if (!allLabelNames.includes(name)) {
|
|
221
|
+
warnings.push(`Exclude label "${name}" not found in the template.`);
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
const included = Object.entries(allLabels).map(([category, categoryLabels]) => {
|
|
226
|
+
if (!labelFilter && !categoryFilter) {
|
|
227
|
+
return [category, categoryLabels];
|
|
228
|
+
}
|
|
187
229
|
const categoryMatches = categoryFilter?.includes(category.toLowerCase()) ?? false;
|
|
188
230
|
if (categoryMatches) {
|
|
189
231
|
return [category, categoryLabels];
|
|
@@ -194,6 +236,14 @@ function filterLabels(allLabels, options) {
|
|
|
194
236
|
}
|
|
195
237
|
return [category, []];
|
|
196
238
|
}).filter(([, categoryLabels]) => categoryLabels.length > 0);
|
|
239
|
+
const entries = included.filter(([category]) => excludeCategoryFilter ? !excludeCategoryFilter.includes(category.toLowerCase()) : true).map(([category, categoryLabels]) => {
|
|
240
|
+
if (!excludeLabelFilter)
|
|
241
|
+
return [category, categoryLabels];
|
|
242
|
+
return [
|
|
243
|
+
category,
|
|
244
|
+
categoryLabels.filter((l) => !excludeLabelFilter.includes(l.name.toLowerCase()))
|
|
245
|
+
];
|
|
246
|
+
}).filter(([, categoryLabels]) => categoryLabels.length > 0);
|
|
197
247
|
return { entries, warnings };
|
|
198
248
|
}
|
|
199
249
|
|
|
@@ -306,6 +356,15 @@ var apply_default = defineCommand({
|
|
|
306
356
|
type: "boolean",
|
|
307
357
|
default: false,
|
|
308
358
|
description: "Include custom labels from labels-custom.json (generated via ghlt generate)"
|
|
359
|
+
},
|
|
360
|
+
exclude: {
|
|
361
|
+
type: "string",
|
|
362
|
+
alias: "e",
|
|
363
|
+
description: 'Exclude specific label(s) by name. Comma-separated for multiple (e.g., --exclude "bug,enhancement")'
|
|
364
|
+
},
|
|
365
|
+
"exclude-category": {
|
|
366
|
+
type: "string",
|
|
367
|
+
description: 'Exclude labels from specific category(ies). Comma-separated for multiple (e.g., --exclude-category "type,status")'
|
|
309
368
|
}
|
|
310
369
|
},
|
|
311
370
|
async run({ args }) {
|
|
@@ -350,7 +409,9 @@ var apply_default = defineCommand({
|
|
|
350
409
|
}
|
|
351
410
|
const { entries: filteredEntries, warnings } = filterLabels(labelPool, {
|
|
352
411
|
label: args.label,
|
|
353
|
-
category: args.category
|
|
412
|
+
category: args.category,
|
|
413
|
+
excludeLabel: args.exclude,
|
|
414
|
+
excludeCategory: args["exclude-category"]
|
|
354
415
|
});
|
|
355
416
|
for (const w of warnings) {
|
|
356
417
|
warn(w);
|
|
@@ -361,6 +422,12 @@ var apply_default = defineCommand({
|
|
|
361
422
|
if (args.label) {
|
|
362
423
|
info(`Applying specific labels: ${args.label}`);
|
|
363
424
|
}
|
|
425
|
+
if (args["exclude-category"]) {
|
|
426
|
+
info(`Excluding categories: ${args["exclude-category"]}`);
|
|
427
|
+
}
|
|
428
|
+
if (args.exclude) {
|
|
429
|
+
info(`Excluding labels: ${args.exclude}`);
|
|
430
|
+
}
|
|
364
431
|
if (filteredEntries.length === 0) {
|
|
365
432
|
warn("No labels matched the specified filter(s).");
|
|
366
433
|
return;
|
|
@@ -440,6 +507,21 @@ var wipe_default = defineCommand2({
|
|
|
440
507
|
alias: "y",
|
|
441
508
|
default: false,
|
|
442
509
|
description: "Skip confirmation prompt"
|
|
510
|
+
},
|
|
511
|
+
label: {
|
|
512
|
+
type: "string",
|
|
513
|
+
alias: "l",
|
|
514
|
+
description: 'Remove specific label(s) by name. Comma-separated for multiple (e.g., --label "bug,enhancement")'
|
|
515
|
+
},
|
|
516
|
+
category: {
|
|
517
|
+
type: "string",
|
|
518
|
+
alias: "c",
|
|
519
|
+
description: 'Remove labels from specific category(ies). Comma-separated for multiple (e.g., --category "type,status")'
|
|
520
|
+
},
|
|
521
|
+
custom: {
|
|
522
|
+
type: "boolean",
|
|
523
|
+
default: false,
|
|
524
|
+
description: "Include custom labels from labels-custom.json when using --label or --category"
|
|
443
525
|
}
|
|
444
526
|
},
|
|
445
527
|
async run({ args }) {
|
|
@@ -462,14 +544,57 @@ var wipe_default = defineCommand2({
|
|
|
462
544
|
info("No labels found. Nothing to wipe.");
|
|
463
545
|
return;
|
|
464
546
|
}
|
|
547
|
+
const isSelective = !!(args.label || args.category);
|
|
548
|
+
let toDelete;
|
|
549
|
+
if (isSelective) {
|
|
550
|
+
const labelPool = {
|
|
551
|
+
...labels_default
|
|
552
|
+
};
|
|
553
|
+
if (args.custom) {
|
|
554
|
+
const custom = loadCustomLabels();
|
|
555
|
+
for (const [cat, catLabels] of Object.entries(custom)) {
|
|
556
|
+
if (!labelPool[cat])
|
|
557
|
+
labelPool[cat] = [];
|
|
558
|
+
for (const label of catLabels) {
|
|
559
|
+
const exists = labelPool[cat].some((l) => l.name.toLowerCase() === label.name.toLowerCase());
|
|
560
|
+
if (!exists)
|
|
561
|
+
labelPool[cat].push(label);
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
const { entries: filteredEntries, warnings } = filterLabels(labelPool, {
|
|
566
|
+
label: args.label,
|
|
567
|
+
category: args.category
|
|
568
|
+
});
|
|
569
|
+
for (const w of warnings) {
|
|
570
|
+
warn(w);
|
|
571
|
+
}
|
|
572
|
+
if (filteredEntries.length === 0) {
|
|
573
|
+
warn("No labels matched the specified filter(s).");
|
|
574
|
+
return;
|
|
575
|
+
}
|
|
576
|
+
const existingSet = new Set(existing.map((n) => n.toLowerCase()));
|
|
577
|
+
toDelete = filteredEntries.flatMap(([, categoryLabels]) => categoryLabels.map((l) => l.name)).filter((name) => existingSet.has(name.toLowerCase()));
|
|
578
|
+
if (toDelete.length === 0) {
|
|
579
|
+
info("None of the specified labels exist on the repo. Nothing to remove.");
|
|
580
|
+
return;
|
|
581
|
+
}
|
|
582
|
+
if (args.label)
|
|
583
|
+
info(`Removing specific labels: ${args.label}`);
|
|
584
|
+
if (args.category)
|
|
585
|
+
info(`Removing labels from category: ${args.category}`);
|
|
586
|
+
} else {
|
|
587
|
+
toDelete = existing;
|
|
588
|
+
}
|
|
465
589
|
if (!args.yes) {
|
|
466
|
-
const
|
|
590
|
+
const message = isSelective ? pc3.bold(pc3.red(`This will delete ${toDelete.length} label(s) from ${repo}.`)) : pc3.bold(pc3.red(`This will delete all ${toDelete.length} labels from ${repo}.`));
|
|
591
|
+
const confirmed = await confirmPrompt(message);
|
|
467
592
|
if (!confirmed)
|
|
468
593
|
return;
|
|
469
594
|
}
|
|
470
595
|
heading("Deleting Labels");
|
|
471
596
|
const counts = { deleted: 0, failed: 0 };
|
|
472
|
-
for (const name of
|
|
597
|
+
for (const name of toDelete) {
|
|
473
598
|
const ok = await deleteLabel(repo, name);
|
|
474
599
|
if (ok) {
|
|
475
600
|
success(`${name} (deleted)`);
|
|
@@ -483,85 +608,8 @@ var wipe_default = defineCommand2({
|
|
|
483
608
|
}
|
|
484
609
|
});
|
|
485
610
|
|
|
486
|
-
// src/commands/preview.ts
|
|
487
|
-
import { defineCommand as defineCommand3 } from "citty";
|
|
488
|
-
import { resolve as resolve2, join } from "path";
|
|
489
|
-
import { readFileSync as readFileSync2, existsSync as existsSync2 } from "fs";
|
|
490
|
-
import { createServer } from "http";
|
|
491
|
-
var MIME_TYPES = {
|
|
492
|
-
".html": "text/html",
|
|
493
|
-
".css": "text/css",
|
|
494
|
-
".js": "application/javascript",
|
|
495
|
-
".json": "application/json",
|
|
496
|
-
".png": "image/png",
|
|
497
|
-
".jpg": "image/jpeg",
|
|
498
|
-
".svg": "image/svg+xml",
|
|
499
|
-
".ico": "image/x-icon",
|
|
500
|
-
".woff": "font/woff",
|
|
501
|
-
".woff2": "font/woff2"
|
|
502
|
-
};
|
|
503
|
-
function getMimeType(filePath) {
|
|
504
|
-
const ext = filePath.slice(filePath.lastIndexOf("."));
|
|
505
|
-
return MIME_TYPES[ext] || "application/octet-stream";
|
|
506
|
-
}
|
|
507
|
-
var preview_default = defineCommand3({
|
|
508
|
-
meta: {
|
|
509
|
-
name: "preview",
|
|
510
|
-
description: "Preview the landing page locally in your browser"
|
|
511
|
-
},
|
|
512
|
-
args: {
|
|
513
|
-
port: {
|
|
514
|
-
type: "string",
|
|
515
|
-
alias: "p",
|
|
516
|
-
default: "3000",
|
|
517
|
-
description: "Port to serve on (default: 3000)"
|
|
518
|
-
}
|
|
519
|
-
},
|
|
520
|
-
async run({ args }) {
|
|
521
|
-
const docsDir = resolve2(import.meta.dirname ?? ".", "..", "..", "docs");
|
|
522
|
-
if (!existsSync2(docsDir)) {
|
|
523
|
-
error("docs/ directory not found. Nothing to preview.");
|
|
524
|
-
process.exit(1);
|
|
525
|
-
}
|
|
526
|
-
const indexPath = join(docsDir, "index.html");
|
|
527
|
-
if (!existsSync2(indexPath)) {
|
|
528
|
-
error("docs/index.html not found. Nothing to preview.");
|
|
529
|
-
process.exit(1);
|
|
530
|
-
}
|
|
531
|
-
const port = parseInt(args.port, 10) || 3000;
|
|
532
|
-
const server = createServer((req, res) => {
|
|
533
|
-
const url = req.url === "/" ? "/index.html" : req.url || "/index.html";
|
|
534
|
-
const filePath = join(docsDir, url);
|
|
535
|
-
if (!filePath.startsWith(docsDir)) {
|
|
536
|
-
res.writeHead(403);
|
|
537
|
-
res.end("Forbidden");
|
|
538
|
-
return;
|
|
539
|
-
}
|
|
540
|
-
if (!existsSync2(filePath)) {
|
|
541
|
-
res.writeHead(404);
|
|
542
|
-
res.end("Not Found");
|
|
543
|
-
return;
|
|
544
|
-
}
|
|
545
|
-
try {
|
|
546
|
-
const content = readFileSync2(filePath);
|
|
547
|
-
res.writeHead(200, { "Content-Type": getMimeType(filePath) });
|
|
548
|
-
res.end(content);
|
|
549
|
-
} catch {
|
|
550
|
-
res.writeHead(500);
|
|
551
|
-
res.end("Internal Server Error");
|
|
552
|
-
}
|
|
553
|
-
});
|
|
554
|
-
server.listen(port, () => {
|
|
555
|
-
const url = `http://localhost:${port}`;
|
|
556
|
-
success(`Landing page preview running at ${url}`);
|
|
557
|
-
info("Press Ctrl+C to stop the server");
|
|
558
|
-
});
|
|
559
|
-
await new Promise(() => {});
|
|
560
|
-
}
|
|
561
|
-
});
|
|
562
|
-
|
|
563
611
|
// src/commands/generate.ts
|
|
564
|
-
import { defineCommand as
|
|
612
|
+
import { defineCommand as defineCommand3 } from "citty";
|
|
565
613
|
import { select, input, confirm } from "@inquirer/prompts";
|
|
566
614
|
|
|
567
615
|
// src/utils/copilot.ts
|
|
@@ -705,7 +753,7 @@ var CATEGORIES = [
|
|
|
705
753
|
function formatLabelChoice(label, index) {
|
|
706
754
|
return `${pc4.bold(label.name)} ${pc4.dim(`#${label.color}`)} โ ${label.description}`;
|
|
707
755
|
}
|
|
708
|
-
var generate_default =
|
|
756
|
+
var generate_default = defineCommand3({
|
|
709
757
|
meta: {
|
|
710
758
|
name: "generate",
|
|
711
759
|
description: "Generate custom labels using AI (requires GitHub Copilot subscription)"
|
|
@@ -865,9 +913,9 @@ var generate_default = defineCommand4({
|
|
|
865
913
|
});
|
|
866
914
|
|
|
867
915
|
// src/commands/migrate.ts
|
|
868
|
-
import { defineCommand as
|
|
916
|
+
import { defineCommand as defineCommand4 } from "citty";
|
|
869
917
|
import pc5 from "picocolors";
|
|
870
|
-
var migrate_default =
|
|
918
|
+
var migrate_default = defineCommand4({
|
|
871
919
|
meta: {
|
|
872
920
|
name: "migrate",
|
|
873
921
|
description: "Wipe all existing labels and apply the template (clean slate)"
|
|
@@ -970,13 +1018,58 @@ var migrate_default = defineCommand5({
|
|
|
970
1018
|
}
|
|
971
1019
|
});
|
|
972
1020
|
|
|
1021
|
+
// src/commands/list.ts
|
|
1022
|
+
import { defineCommand as defineCommand5 } from "citty";
|
|
1023
|
+
import pc6 from "picocolors";
|
|
1024
|
+
var list_default = defineCommand5({
|
|
1025
|
+
meta: {
|
|
1026
|
+
name: "list",
|
|
1027
|
+
description: "List all labels in a repository"
|
|
1028
|
+
},
|
|
1029
|
+
args: {
|
|
1030
|
+
repo: {
|
|
1031
|
+
type: "string",
|
|
1032
|
+
alias: "r",
|
|
1033
|
+
description: "Target repository (owner/repo). Defaults to current repo."
|
|
1034
|
+
}
|
|
1035
|
+
},
|
|
1036
|
+
async run({ args }) {
|
|
1037
|
+
if (!await checkGhInstalled()) {
|
|
1038
|
+
error("gh CLI is not installed. Install it from https://cli.github.com");
|
|
1039
|
+
process.exit(1);
|
|
1040
|
+
}
|
|
1041
|
+
if (!await checkGhAuth()) {
|
|
1042
|
+
error("Not authenticated. Run `gh auth login` first.");
|
|
1043
|
+
process.exit(1);
|
|
1044
|
+
}
|
|
1045
|
+
const repo = args.repo || await detectRepo();
|
|
1046
|
+
if (!repo) {
|
|
1047
|
+
error("Could not detect repository. Use --repo <owner/repo> or run inside a git repo.");
|
|
1048
|
+
process.exit(1);
|
|
1049
|
+
}
|
|
1050
|
+
info(`Target: ${repo}`);
|
|
1051
|
+
const labels = await listLabelsDetailed(repo);
|
|
1052
|
+
if (labels.length === 0) {
|
|
1053
|
+
info("No labels found.");
|
|
1054
|
+
return;
|
|
1055
|
+
}
|
|
1056
|
+
heading(`Labels (${labels.length} total)`);
|
|
1057
|
+
for (const label of labels) {
|
|
1058
|
+
const name = pc6.bold(label.name.padEnd(30));
|
|
1059
|
+
const color = pc6.dim(`#${label.color}`);
|
|
1060
|
+
const desc = label.description ? pc6.dim(label.description) : "";
|
|
1061
|
+
console.log(` ${name} ${color} ${desc}`);
|
|
1062
|
+
}
|
|
1063
|
+
}
|
|
1064
|
+
});
|
|
1065
|
+
|
|
973
1066
|
// src/ui/banner.ts
|
|
974
1067
|
import figlet from "figlet";
|
|
975
|
-
import
|
|
1068
|
+
import pc7 from "picocolors";
|
|
976
1069
|
// package.json
|
|
977
1070
|
var package_default = {
|
|
978
1071
|
name: "github-labels-template",
|
|
979
|
-
version: "0.6.
|
|
1072
|
+
version: "0.6.1-staging.3ace40c",
|
|
980
1073
|
description: "A CLI tool to apply a curated GitHub labels template to any repository using gh CLI.",
|
|
981
1074
|
type: "module",
|
|
982
1075
|
bin: {
|
|
@@ -1041,15 +1134,15 @@ function getAuthor() {
|
|
|
1041
1134
|
return package_default.author ?? "unknown";
|
|
1042
1135
|
}
|
|
1043
1136
|
function showBanner(minimal = false) {
|
|
1044
|
-
console.log(
|
|
1137
|
+
console.log(pc7.cyan(`
|
|
1045
1138
|
` + LOGO));
|
|
1046
|
-
console.log(` ${
|
|
1139
|
+
console.log(` ${pc7.dim("v" + getVersion())} ${pc7.dim("โ")} ${pc7.dim("Built by " + getAuthor())}`);
|
|
1047
1140
|
if (!minimal) {
|
|
1048
|
-
console.log(` ${
|
|
1141
|
+
console.log(` ${pc7.dim(package_default.description)}`);
|
|
1049
1142
|
console.log();
|
|
1050
|
-
console.log(` ${
|
|
1051
|
-
console.log(` ${
|
|
1052
|
-
console.log(` ${
|
|
1143
|
+
console.log(` ${pc7.yellow("Star")} ${pc7.cyan("https://gh.waren.build/github-labels-template")}`);
|
|
1144
|
+
console.log(` ${pc7.green("Contribute")} ${pc7.cyan("https://gh.waren.build/github-labels-template/blob/main/CONTRIBUTING.md")}`);
|
|
1145
|
+
console.log(` ${pc7.magenta("Sponsor")} ${pc7.cyan("https://warengonzaga.com/sponsor")}`);
|
|
1053
1146
|
}
|
|
1054
1147
|
console.log();
|
|
1055
1148
|
}
|
|
@@ -1074,8 +1167,8 @@ var main = defineCommand6({
|
|
|
1074
1167
|
apply: apply_default,
|
|
1075
1168
|
wipe: wipe_default,
|
|
1076
1169
|
migrate: migrate_default,
|
|
1077
|
-
|
|
1078
|
-
|
|
1170
|
+
generate: generate_default,
|
|
1171
|
+
list: list_default
|
|
1079
1172
|
},
|
|
1080
1173
|
run({ args }) {
|
|
1081
1174
|
if (args.version) {
|