@kevinrabun/judges 3.42.0 → 3.44.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.
Files changed (74) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/dist/cli.d.ts.map +1 -1
  3. package/dist/cli.js +112 -0
  4. package/dist/cli.js.map +1 -1
  5. package/dist/commands/assign-findings.d.ts +37 -0
  6. package/dist/commands/assign-findings.d.ts.map +1 -0
  7. package/dist/commands/assign-findings.js +178 -0
  8. package/dist/commands/assign-findings.js.map +1 -0
  9. package/dist/commands/burndown.d.ts +27 -0
  10. package/dist/commands/burndown.d.ts.map +1 -0
  11. package/dist/commands/burndown.js +180 -0
  12. package/dist/commands/burndown.js.map +1 -0
  13. package/dist/commands/ci-template.d.ts +15 -0
  14. package/dist/commands/ci-template.d.ts.map +1 -0
  15. package/dist/commands/ci-template.js +212 -0
  16. package/dist/commands/ci-template.js.map +1 -0
  17. package/dist/commands/false-negatives.d.ts +35 -0
  18. package/dist/commands/false-negatives.d.ts.map +1 -0
  19. package/dist/commands/false-negatives.js +166 -0
  20. package/dist/commands/false-negatives.js.map +1 -0
  21. package/dist/commands/hook-install.d.ts +22 -0
  22. package/dist/commands/hook-install.d.ts.map +1 -0
  23. package/dist/commands/hook-install.js +143 -0
  24. package/dist/commands/hook-install.js.map +1 -0
  25. package/dist/commands/kb.d.ts +41 -0
  26. package/dist/commands/kb.d.ts.map +1 -0
  27. package/dist/commands/kb.js +231 -0
  28. package/dist/commands/kb.js.map +1 -0
  29. package/dist/commands/noise-advisor.d.ts +30 -0
  30. package/dist/commands/noise-advisor.d.ts.map +1 -0
  31. package/dist/commands/noise-advisor.js +171 -0
  32. package/dist/commands/noise-advisor.js.map +1 -0
  33. package/dist/commands/policy-audit.d.ts +53 -0
  34. package/dist/commands/policy-audit.d.ts.map +1 -0
  35. package/dist/commands/policy-audit.js +161 -0
  36. package/dist/commands/policy-audit.js.map +1 -0
  37. package/dist/commands/recommend.d.ts +21 -0
  38. package/dist/commands/recommend.d.ts.map +1 -0
  39. package/dist/commands/recommend.js +283 -0
  40. package/dist/commands/recommend.js.map +1 -0
  41. package/dist/commands/regression-alert.d.ts +32 -0
  42. package/dist/commands/regression-alert.d.ts.map +1 -0
  43. package/dist/commands/regression-alert.js +216 -0
  44. package/dist/commands/regression-alert.js.map +1 -0
  45. package/dist/commands/remediation.d.ts +21 -0
  46. package/dist/commands/remediation.d.ts.map +1 -0
  47. package/dist/commands/remediation.js +257 -0
  48. package/dist/commands/remediation.js.map +1 -0
  49. package/dist/commands/report-template.d.ts +17 -0
  50. package/dist/commands/report-template.d.ts.map +1 -0
  51. package/dist/commands/report-template.js +291 -0
  52. package/dist/commands/report-template.js.map +1 -0
  53. package/dist/commands/review-queue.d.ts +34 -0
  54. package/dist/commands/review-queue.d.ts.map +1 -0
  55. package/dist/commands/review-queue.js +226 -0
  56. package/dist/commands/review-queue.js.map +1 -0
  57. package/dist/commands/rule-owner.d.ts +31 -0
  58. package/dist/commands/rule-owner.d.ts.map +1 -0
  59. package/dist/commands/rule-owner.js +182 -0
  60. package/dist/commands/rule-owner.js.map +1 -0
  61. package/dist/commands/sla-track.d.ts +57 -0
  62. package/dist/commands/sla-track.d.ts.map +1 -0
  63. package/dist/commands/sla-track.js +269 -0
  64. package/dist/commands/sla-track.js.map +1 -0
  65. package/dist/commands/suppress.d.ts +40 -0
  66. package/dist/commands/suppress.d.ts.map +1 -0
  67. package/dist/commands/suppress.js +209 -0
  68. package/dist/commands/suppress.js.map +1 -0
  69. package/dist/commands/ticket-sync.d.ts +26 -0
  70. package/dist/commands/ticket-sync.d.ts.map +1 -0
  71. package/dist/commands/ticket-sync.js +236 -0
  72. package/dist/commands/ticket-sync.js.map +1 -0
  73. package/package.json +1 -1
  74. package/server.json +2 -2
@@ -0,0 +1,178 @@
1
+ /**
2
+ * Finding assignment — assign findings to team members for resolution.
3
+ *
4
+ * Uses a local assignment database (.judges-assignments.json) to track
5
+ * who is responsible for fixing each finding, enabling team workflows
6
+ * without requiring an external service.
7
+ */
8
+ import { createHash } from "crypto";
9
+ // ─── Database ───────────────────────────────────────────────────────────────
10
+ const DB_FILE = ".judges-assignments.json";
11
+ function loadDb() {
12
+ const { readFileSync, existsSync } = require("fs");
13
+ if (existsSync(DB_FILE)) {
14
+ try {
15
+ return JSON.parse(readFileSync(DB_FILE, "utf-8"));
16
+ }
17
+ catch {
18
+ /* corrupt */
19
+ }
20
+ }
21
+ return { assignments: [], version: "1.0" };
22
+ }
23
+ function saveDb(db) {
24
+ const { writeFileSync } = require("fs");
25
+ writeFileSync(DB_FILE, JSON.stringify(db, null, 2), "utf-8");
26
+ }
27
+ export function assignFinding(finding, assignee) {
28
+ const db = loadDb();
29
+ const assignment = {
30
+ id: createHash("sha256")
31
+ .update(finding.ruleId + finding.title + Date.now())
32
+ .digest("hex")
33
+ .slice(0, 10),
34
+ findingRuleId: finding.ruleId,
35
+ findingTitle: finding.title,
36
+ severity: finding.severity,
37
+ assignee,
38
+ assignedAt: new Date().toISOString(),
39
+ status: "open",
40
+ };
41
+ db.assignments.push(assignment);
42
+ saveDb(db);
43
+ return assignment;
44
+ }
45
+ export function resolveAssignment(id, status) {
46
+ const db = loadDb();
47
+ const assignment = db.assignments.find((a) => a.id === id);
48
+ if (!assignment)
49
+ return false;
50
+ assignment.status = status;
51
+ assignment.resolvedAt = new Date().toISOString();
52
+ saveDb(db);
53
+ return true;
54
+ }
55
+ export function getAssignmentStats(db) {
56
+ const byAssignee = {};
57
+ const bySeverity = {};
58
+ let open = 0;
59
+ let fixed = 0;
60
+ for (const a of db.assignments) {
61
+ if (a.status === "open" || a.status === "in-progress")
62
+ open++;
63
+ if (a.status === "fixed")
64
+ fixed++;
65
+ bySeverity[a.severity] = (bySeverity[a.severity] || 0) + 1;
66
+ if (!byAssignee[a.assignee])
67
+ byAssignee[a.assignee] = { open: 0, fixed: 0 };
68
+ if (a.status === "open" || a.status === "in-progress")
69
+ byAssignee[a.assignee].open++;
70
+ if (a.status === "fixed")
71
+ byAssignee[a.assignee].fixed++;
72
+ }
73
+ return { total: db.assignments.length, open, fixed, byAssignee, bySeverity };
74
+ }
75
+ // ─── CLI ────────────────────────────────────────────────────────────────────
76
+ export function runAssignFindings(argv) {
77
+ if (argv.includes("--help") || argv.includes("-h")) {
78
+ console.log(`
79
+ judges assign — Assign findings to team members
80
+
81
+ Usage:
82
+ judges assign --input results.json --assignee alice Assign all findings
83
+ judges assign --resolve <id> --status fixed Resolve an assignment
84
+ judges assign --list Show all assignments
85
+ judges assign --stats Show assignment stats
86
+
87
+ Options:
88
+ --input <path> JSON results file to assign findings from
89
+ --assignee <name> Team member to assign to
90
+ --severity <level> Only assign findings of this severity+
91
+ --resolve <id> Resolve an assignment
92
+ --status <status> Resolution status: fixed, wont-fix
93
+ --list List all assignments
94
+ --stats Show assignment statistics
95
+ --format json JSON output
96
+ --help, -h Show this help
97
+ `);
98
+ return;
99
+ }
100
+ const format = argv.find((_a, i) => argv[i - 1] === "--format") || "text";
101
+ const { readFileSync, existsSync } = require("fs");
102
+ // Resolve
103
+ const resolveId = argv.find((_a, i) => argv[i - 1] === "--resolve");
104
+ if (resolveId) {
105
+ const status = (argv.find((_a, i) => argv[i - 1] === "--status") || "fixed");
106
+ if (resolveAssignment(resolveId, status)) {
107
+ console.log(` ✅ Assignment ${resolveId} marked as ${status}`);
108
+ }
109
+ else {
110
+ console.error(` Error: assignment ${resolveId} not found`);
111
+ }
112
+ return;
113
+ }
114
+ // Stats
115
+ if (argv.includes("--stats")) {
116
+ const db = loadDb();
117
+ const stats = getAssignmentStats(db);
118
+ if (format === "json") {
119
+ console.log(JSON.stringify(stats, null, 2));
120
+ return;
121
+ }
122
+ console.log(`\n Assignment Statistics\n`);
123
+ console.log(` Total: ${stats.total} | Open: ${stats.open} | Fixed: ${stats.fixed}\n`);
124
+ console.log(" By Assignee:");
125
+ for (const [name, counts] of Object.entries(stats.byAssignee)) {
126
+ console.log(` ${name.padEnd(20)} open: ${counts.open} fixed: ${counts.fixed}`);
127
+ }
128
+ console.log("");
129
+ return;
130
+ }
131
+ // List
132
+ if (argv.includes("--list")) {
133
+ const db = loadDb();
134
+ if (format === "json") {
135
+ console.log(JSON.stringify(db.assignments, null, 2));
136
+ return;
137
+ }
138
+ console.log(`\n Assignments (${db.assignments.length})\n`);
139
+ for (const a of db.assignments) {
140
+ const status = a.status === "open" ? "🔴" : a.status === "in-progress" ? "🟡" : "✅";
141
+ console.log(` ${status} ${a.id} ${a.severity.padEnd(8)} ${a.assignee.padEnd(15)} ${a.findingTitle.slice(0, 40)}`);
142
+ }
143
+ console.log("");
144
+ return;
145
+ }
146
+ // Assign
147
+ const inputPath = argv.find((_a, i) => argv[i - 1] === "--input");
148
+ const assignee = argv.find((_a, i) => argv[i - 1] === "--assignee");
149
+ if (!inputPath || !assignee) {
150
+ console.error("Error: --input and --assignee required. Use --help for usage.");
151
+ process.exit(1);
152
+ }
153
+ if (!existsSync(inputPath)) {
154
+ console.error(`Error: file not found: ${inputPath}`);
155
+ process.exit(1);
156
+ }
157
+ const data = JSON.parse(readFileSync(inputPath, "utf-8"));
158
+ const findings = data.evaluations
159
+ ? data.evaluations.flatMap((e) => e.findings || [])
160
+ : data.findings || data;
161
+ const severityFilter = argv.find((_a, i) => argv[i - 1] === "--severity");
162
+ const severityOrder = ["critical", "high", "medium", "low", "info"];
163
+ let filtered = findings;
164
+ if (severityFilter) {
165
+ const idx = severityOrder.indexOf(severityFilter);
166
+ if (idx >= 0) {
167
+ const allowed = new Set(severityOrder.slice(0, idx + 1));
168
+ filtered = findings.filter((f) => allowed.has(f.severity));
169
+ }
170
+ }
171
+ let assigned = 0;
172
+ for (const f of filtered) {
173
+ assignFinding(f, assignee);
174
+ assigned++;
175
+ }
176
+ console.log(` ✅ Assigned ${assigned} findings to ${assignee}`);
177
+ }
178
+ //# sourceMappingURL=assign-findings.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"assign-findings.js","sourceRoot":"","sources":["../../src/commands/assign-findings.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Burndown — track finding resolution progress over time and
3
+ * visualize whether the team is on track to meet targets.
4
+ *
5
+ * Data stored locally in .judges-burndown.json.
6
+ */
7
+ import type { Finding } from "../types.js";
8
+ export interface BurndownEntry {
9
+ timestamp: string;
10
+ date: string;
11
+ totalFindings: number;
12
+ bySeverity: Record<string, number>;
13
+ gitCommit?: string;
14
+ }
15
+ interface BurndownDb {
16
+ entries: BurndownEntry[];
17
+ target?: {
18
+ count: number;
19
+ deadline: string;
20
+ };
21
+ }
22
+ export declare function recordSnapshot(findings: Finding[]): BurndownEntry;
23
+ export declare function setTarget(count: number, deadline: string): void;
24
+ export declare function getBurndownData(): BurndownDb;
25
+ export declare function runBurndown(argv: string[]): Promise<void>;
26
+ export {};
27
+ //# sourceMappingURL=burndown.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"burndown.d.ts","sourceRoot":"","sources":["../../src/commands/burndown.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAI3C,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,UAAU,UAAU;IAClB,OAAO,EAAE,aAAa,EAAE,CAAC;IACzB,MAAM,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;CAC9C;AAwBD,wBAAgB,cAAc,CAAC,QAAQ,EAAE,OAAO,EAAE,GAAG,aAAa,CAyBjE;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAI/D;AAED,wBAAgB,eAAe,IAAI,UAAU,CAE5C;AAyDD,wBAAsB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAgF/D"}
@@ -0,0 +1,180 @@
1
+ /**
2
+ * Burndown — track finding resolution progress over time and
3
+ * visualize whether the team is on track to meet targets.
4
+ *
5
+ * Data stored locally in .judges-burndown.json.
6
+ */
7
+ import { readFileSync, writeFileSync, existsSync } from "fs";
8
+ const BURNDOWN_FILE = ".judges-burndown.json";
9
+ // ─── Core ───────────────────────────────────────────────────────────────────
10
+ function loadDb(file = BURNDOWN_FILE) {
11
+ if (!existsSync(file))
12
+ return { entries: [] };
13
+ return JSON.parse(readFileSync(file, "utf-8"));
14
+ }
15
+ function saveDb(db, file = BURNDOWN_FILE) {
16
+ writeFileSync(file, JSON.stringify(db, null, 2));
17
+ }
18
+ function getGitCommit() {
19
+ try {
20
+ const { execSync } = require("child_process");
21
+ return execSync("git rev-parse --short HEAD", { encoding: "utf-8" }).trim();
22
+ }
23
+ catch {
24
+ return undefined;
25
+ }
26
+ }
27
+ export function recordSnapshot(findings) {
28
+ const db = loadDb();
29
+ const now = new Date();
30
+ const bySeverity = {};
31
+ for (const f of findings) {
32
+ bySeverity[f.severity] = (bySeverity[f.severity] || 0) + 1;
33
+ }
34
+ const entry = {
35
+ timestamp: now.toISOString(),
36
+ date: now.toISOString().split("T")[0],
37
+ totalFindings: findings.length,
38
+ bySeverity,
39
+ gitCommit: getGitCommit(),
40
+ };
41
+ db.entries.push(entry);
42
+ // Keep last 365 entries max
43
+ if (db.entries.length > 365) {
44
+ db.entries = db.entries.slice(-365);
45
+ }
46
+ saveDb(db);
47
+ return entry;
48
+ }
49
+ export function setTarget(count, deadline) {
50
+ const db = loadDb();
51
+ db.target = { count, deadline };
52
+ saveDb(db);
53
+ }
54
+ export function getBurndownData() {
55
+ return loadDb();
56
+ }
57
+ function renderChart(db) {
58
+ if (db.entries.length === 0)
59
+ return " No data points. Run evaluations to populate.";
60
+ const lines = [];
61
+ const maxFindings = Math.max(...db.entries.map((e) => e.totalFindings), 1);
62
+ const chartWidth = 50;
63
+ const recent = db.entries.slice(-20); // Last 20 entries
64
+ for (const entry of recent) {
65
+ const barLen = Math.round((entry.totalFindings / maxFindings) * chartWidth);
66
+ const bar = "█".repeat(barLen) + "░".repeat(chartWidth - barLen);
67
+ lines.push(` ${entry.date} ${bar} ${entry.totalFindings}`);
68
+ }
69
+ return lines.join("\n");
70
+ }
71
+ function calculateTrajectory(db) {
72
+ if (db.entries.length < 2)
73
+ return " Need at least 2 data points for trajectory.";
74
+ const first = db.entries[0];
75
+ const last = db.entries[db.entries.length - 1];
76
+ const daysBetween = (new Date(last.timestamp).getTime() - new Date(first.timestamp).getTime()) / 86_400_000;
77
+ const delta = last.totalFindings - first.totalFindings;
78
+ const ratePerDay = daysBetween > 0 ? Math.round((delta / daysBetween) * 10) / 10 : 0;
79
+ const parts = [
80
+ ` Start: ${first.totalFindings} findings (${first.date})`,
81
+ ` Now: ${last.totalFindings} findings (${last.date})`,
82
+ ` Rate: ${ratePerDay >= 0 ? "+" : ""}${ratePerDay}/day`,
83
+ ];
84
+ if (db.target) {
85
+ const remaining = last.totalFindings - db.target.count;
86
+ if (remaining <= 0) {
87
+ parts.push(` Target: ${db.target.count} by ${db.target.deadline} — ✅ ACHIEVED`);
88
+ }
89
+ else if (ratePerDay >= 0) {
90
+ parts.push(` Target: ${db.target.count} by ${db.target.deadline} — ⚠️ Findings increasing`);
91
+ }
92
+ else {
93
+ const daysNeeded = Math.abs(Math.ceil(remaining / ratePerDay));
94
+ const eta = new Date();
95
+ eta.setDate(eta.getDate() + daysNeeded);
96
+ const onTrack = eta.getTime() <= new Date(db.target.deadline).getTime();
97
+ parts.push(` Target: ${db.target.count} by ${db.target.deadline} — ${onTrack ? "✅ On track" : "⚠️ Behind schedule"}`, ` ETA: ${eta.toISOString().split("T")[0]} (${daysNeeded} days at current rate)`);
98
+ }
99
+ }
100
+ return parts.join("\n");
101
+ }
102
+ // ─── CLI ────────────────────────────────────────────────────────────────────
103
+ export async function runBurndown(argv) {
104
+ if (argv.includes("--help") || argv.includes("-h")) {
105
+ console.log(`
106
+ judges burndown — Track finding resolution progress
107
+
108
+ Usage:
109
+ judges burndown --record --input results.json Record a data point
110
+ judges burndown --show Show burndown chart
111
+ judges burndown --set-target 50 --deadline 2025-06-01
112
+ judges burndown --trajectory Show trajectory analysis
113
+
114
+ Options:
115
+ --record Record current findings as data point
116
+ --input <path> Results JSON file
117
+ --show Display burndown chart
118
+ --set-target <n> Set target finding count
119
+ --deadline <date> Target deadline (YYYY-MM-DD)
120
+ --trajectory Show rate and ETA analysis
121
+ --format json JSON output
122
+ --help, -h Show this help
123
+ `);
124
+ return;
125
+ }
126
+ const format = argv.find((_a, i) => argv[i - 1] === "--format") || "text";
127
+ // Record snapshot
128
+ const inputPath = argv.find((_a, i) => argv[i - 1] === "--input");
129
+ if (argv.includes("--record") && inputPath) {
130
+ if (!existsSync(inputPath)) {
131
+ console.error(`Error: file not found: ${inputPath}`);
132
+ process.exit(1);
133
+ }
134
+ const data = JSON.parse(readFileSync(inputPath, "utf-8"));
135
+ const findings = data.evaluations
136
+ ? data.evaluations.flatMap((e) => e.findings || [])
137
+ : data.findings || data;
138
+ const entry = recordSnapshot(findings);
139
+ if (format === "json") {
140
+ console.log(JSON.stringify(entry, null, 2));
141
+ }
142
+ else {
143
+ console.log(` Recorded: ${entry.totalFindings} findings on ${entry.date}`);
144
+ }
145
+ return;
146
+ }
147
+ // Set target
148
+ const targetStr = argv.find((_a, i) => argv[i - 1] === "--set-target");
149
+ const deadline = argv.find((_a, i) => argv[i - 1] === "--deadline");
150
+ if (targetStr && deadline) {
151
+ setTarget(parseInt(targetStr, 10), deadline);
152
+ console.log(` Target set: ${targetStr} findings by ${deadline}`);
153
+ return;
154
+ }
155
+ const db = getBurndownData();
156
+ // Trajectory
157
+ if (argv.includes("--trajectory")) {
158
+ if (format === "json") {
159
+ console.log(JSON.stringify(db, null, 2));
160
+ }
161
+ else {
162
+ console.log("\n Trajectory Analysis\n ───────────────────");
163
+ console.log(calculateTrajectory(db));
164
+ console.log("");
165
+ }
166
+ return;
167
+ }
168
+ // Show chart (default)
169
+ if (format === "json") {
170
+ console.log(JSON.stringify(db, null, 2));
171
+ }
172
+ else {
173
+ console.log("\n Finding Burndown\n ────────────────");
174
+ console.log(renderChart(db));
175
+ console.log("");
176
+ console.log(calculateTrajectory(db));
177
+ console.log("");
178
+ }
179
+ }
180
+ //# sourceMappingURL=burndown.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"burndown.js","sourceRoot":"","sources":["../../src/commands/burndown.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * CI templates — generate ready-to-use CI/CD pipeline configs for
3
+ * GitHub Actions, GitLab CI, Azure Pipelines, Bitbucket Pipelines,
4
+ * and CircleCI. Eliminates manual YAML authoring for teams adopting Judges.
5
+ */
6
+ export interface CiTemplate {
7
+ id: string;
8
+ name: string;
9
+ file: string;
10
+ content: string;
11
+ }
12
+ export declare function getTemplate(id: string): CiTemplate | undefined;
13
+ export declare function listTemplates(): CiTemplate[];
14
+ export declare function runCiTemplate(argv: string[]): void;
15
+ //# sourceMappingURL=ci-template.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ci-template.d.ts","sourceRoot":"","sources":["../../src/commands/ci-template.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AA8HH,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAUD,wBAAgB,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS,CAE9D;AAED,wBAAgB,aAAa,IAAI,UAAU,EAAE,CAE5C;AAgBD,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAiElD"}
@@ -0,0 +1,212 @@
1
+ /**
2
+ * CI templates — generate ready-to-use CI/CD pipeline configs for
3
+ * GitHub Actions, GitLab CI, Azure Pipelines, Bitbucket Pipelines,
4
+ * and CircleCI. Eliminates manual YAML authoring for teams adopting Judges.
5
+ */
6
+ // ─── Templates ──────────────────────────────────────────────────────────────
7
+ const GITHUB_ACTIONS = `# .github/workflows/judges.yml
8
+ name: Judges Code Review
9
+ on:
10
+ pull_request:
11
+ types: [opened, synchronize]
12
+
13
+ permissions:
14
+ contents: read
15
+ pull-requests: write
16
+ security-events: write
17
+
18
+ jobs:
19
+ judges:
20
+ runs-on: ubuntu-latest
21
+ steps:
22
+ - uses: actions/checkout@v4
23
+ - uses: actions/setup-node@v4
24
+ with:
25
+ node-version: "20"
26
+ - run: npm install -g @kevinrabun/judges
27
+ - name: Run Judges evaluation
28
+ run: |
29
+ judges eval --file "src/**/*.ts" --format sarif --fail-on-findings > judges.sarif
30
+ continue-on-error: true
31
+ - name: Upload SARIF
32
+ if: always()
33
+ run: judges upload --file judges.sarif
34
+ env:
35
+ GITHUB_TOKEN: \${{ secrets.GITHUB_TOKEN }}
36
+ - name: Post PR summary
37
+ if: always()
38
+ run: judges pr-summary --sarif judges.sarif --pr \${{ github.event.pull_request.number }}
39
+ env:
40
+ GITHUB_TOKEN: \${{ secrets.GITHUB_TOKEN }}
41
+ `;
42
+ const GITLAB_CI = `# .gitlab-ci.yml
43
+ judges-review:
44
+ image: node:20
45
+ stage: test
46
+ script:
47
+ - npm install -g @kevinrabun/judges
48
+ - judges eval --file "src/**/*.ts" --format sarif > judges.sarif
49
+ - judges eval --file "src/**/*.ts" --format codeclimate > codeclimate.json
50
+ artifacts:
51
+ reports:
52
+ sast: judges.sarif
53
+ codequality: codeclimate.json
54
+ rules:
55
+ - if: $CI_MERGE_REQUEST_IID
56
+ `;
57
+ const AZURE_PIPELINES = `# azure-pipelines.yml
58
+ trigger:
59
+ - main
60
+
61
+ pool:
62
+ vmImage: "ubuntu-latest"
63
+
64
+ steps:
65
+ - task: NodeTool@0
66
+ inputs:
67
+ versionSpec: "20.x"
68
+
69
+ - script: npm install -g @kevinrabun/judges
70
+ displayName: "Install Judges"
71
+
72
+ - script: judges eval --file "src/**/*.ts" --format sarif > judges.sarif
73
+ displayName: "Run Judges evaluation"
74
+
75
+ - task: PublishBuildArtifacts@1
76
+ inputs:
77
+ PathtoPublish: judges.sarif
78
+ ArtifactName: judges-results
79
+ condition: always()
80
+ `;
81
+ const BITBUCKET_PIPELINES = `# bitbucket-pipelines.yml
82
+ image: node:20
83
+
84
+ pipelines:
85
+ pull-requests:
86
+ "**":
87
+ - step:
88
+ name: Judges Code Review
89
+ caches:
90
+ - node
91
+ script:
92
+ - npm install -g @kevinrabun/judges
93
+ - judges eval --file "src/**/*.ts" --format json > judges-results.json
94
+ - judges eval --file "src/**/*.ts" --format text
95
+ artifacts:
96
+ - judges-results.json
97
+ `;
98
+ const CIRCLECI = `# .circleci/config.yml
99
+ version: 2.1
100
+
101
+ jobs:
102
+ judges-review:
103
+ docker:
104
+ - image: cimg/node:20.0
105
+ steps:
106
+ - checkout
107
+ - run:
108
+ name: Install Judges
109
+ command: npm install -g @kevinrabun/judges
110
+ - run:
111
+ name: Run evaluation
112
+ command: judges eval --file "src/**/*.ts" --format sarif > judges.sarif
113
+ - store_artifacts:
114
+ path: judges.sarif
115
+ destination: judges-results
116
+
117
+ workflows:
118
+ review:
119
+ jobs:
120
+ - judges-review
121
+ `;
122
+ const TEMPLATES = [
123
+ { id: "github", name: "GitHub Actions", file: ".github/workflows/judges.yml", content: GITHUB_ACTIONS },
124
+ { id: "gitlab", name: "GitLab CI", file: ".gitlab-ci.yml", content: GITLAB_CI },
125
+ { id: "azure", name: "Azure Pipelines", file: "azure-pipelines.yml", content: AZURE_PIPELINES },
126
+ { id: "bitbucket", name: "Bitbucket Pipelines", file: "bitbucket-pipelines.yml", content: BITBUCKET_PIPELINES },
127
+ { id: "circleci", name: "CircleCI", file: ".circleci/config.yml", content: CIRCLECI },
128
+ ];
129
+ export function getTemplate(id) {
130
+ return TEMPLATES.find((t) => t.id === id);
131
+ }
132
+ export function listTemplates() {
133
+ return TEMPLATES;
134
+ }
135
+ // ─── Auto-Detect Platform ──────────────────────────────────────────────────
136
+ function detectPlatform() {
137
+ const { existsSync } = require("fs");
138
+ if (existsSync(".github"))
139
+ return "github";
140
+ if (existsSync(".gitlab-ci.yml"))
141
+ return "gitlab";
142
+ if (existsSync("azure-pipelines.yml"))
143
+ return "azure";
144
+ if (existsSync("bitbucket-pipelines.yml"))
145
+ return "bitbucket";
146
+ if (existsSync(".circleci"))
147
+ return "circleci";
148
+ return undefined;
149
+ }
150
+ // ─── CLI ────────────────────────────────────────────────────────────────────
151
+ export function runCiTemplate(argv) {
152
+ if (argv.includes("--help") || argv.includes("-h")) {
153
+ console.log(`
154
+ judges ci-template — Generate CI/CD pipeline config for Judges
155
+
156
+ Usage:
157
+ judges ci-template --platform github Generate GitHub Actions workflow
158
+ judges ci-template --platform gitlab Generate GitLab CI config
159
+ judges ci-template --platform azure Generate Azure Pipelines config
160
+ judges ci-template --platform bitbucket Generate Bitbucket Pipelines config
161
+ judges ci-template --platform circleci Generate CircleCI config
162
+ judges ci-template --list List available templates
163
+ judges ci-template --auto Auto-detect platform
164
+
165
+ Options:
166
+ --platform <id> CI platform (github, gitlab, azure, bitbucket, circleci)
167
+ --write Write to the appropriate file location
168
+ --list List all available templates
169
+ --auto Auto-detect platform from repo structure
170
+ --help, -h Show this help
171
+ `);
172
+ return;
173
+ }
174
+ if (argv.includes("--list")) {
175
+ console.log("\n Available CI Templates:\n");
176
+ for (const t of TEMPLATES) {
177
+ console.log(` ${t.id.padEnd(12)} ${t.name.padEnd(25)} → ${t.file}`);
178
+ }
179
+ console.log("");
180
+ return;
181
+ }
182
+ let platform = argv.find((_a, i) => argv[i - 1] === "--platform");
183
+ if (argv.includes("--auto")) {
184
+ platform = detectPlatform();
185
+ if (!platform) {
186
+ console.error("Error: could not auto-detect CI platform");
187
+ process.exit(1);
188
+ }
189
+ console.log(` Auto-detected platform: ${platform}`);
190
+ }
191
+ if (!platform) {
192
+ console.error("Error: --platform <id> required. Use --list to see options.");
193
+ process.exit(1);
194
+ }
195
+ const template = getTemplate(platform);
196
+ if (!template) {
197
+ console.error(`Error: unknown platform "${platform}". Use --list to see options.`);
198
+ process.exit(1);
199
+ }
200
+ if (argv.includes("--write")) {
201
+ const { writeFileSync, mkdirSync } = require("fs");
202
+ const { dirname } = require("path");
203
+ const dir = dirname(template.file);
204
+ if (dir !== ".")
205
+ mkdirSync(dir, { recursive: true });
206
+ writeFileSync(template.file, template.content, "utf-8");
207
+ console.log(` ✅ Written ${template.file}`);
208
+ return;
209
+ }
210
+ console.log(template.content);
211
+ }
212
+ //# sourceMappingURL=ci-template.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ci-template.js","sourceRoot":"","sources":["../../src/commands/ci-template.ts"],"names":[],"mappings":"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"}