specweave 0.17.12 → 0.17.15
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/CLAUDE.md +456 -0
- package/README.md +38 -1
- package/dist/src/cli/commands/cicd-monitor.d.ts +11 -0
- package/dist/src/cli/commands/cicd-monitor.d.ts.map +1 -0
- package/dist/src/cli/commands/cicd-monitor.js +154 -0
- package/dist/src/cli/commands/cicd-monitor.js.map +1 -0
- package/dist/src/cli/commands/validate-parent-repo.d.ts +8 -0
- package/dist/src/cli/commands/validate-parent-repo.d.ts.map +1 -0
- package/dist/src/cli/commands/validate-parent-repo.js +15 -0
- package/dist/src/cli/commands/validate-parent-repo.js.map +1 -0
- package/dist/src/cli/helpers/issue-tracker/types.d.ts +5 -0
- package/dist/src/cli/helpers/issue-tracker/types.d.ts.map +1 -1
- package/dist/src/cli/helpers/issue-tracker/types.js.map +1 -1
- package/dist/src/core/cicd/config-loader.d.ts +21 -0
- package/dist/src/core/cicd/config-loader.d.ts.map +1 -0
- package/dist/src/core/cicd/config-loader.js +190 -0
- package/dist/src/core/cicd/config-loader.js.map +1 -0
- package/dist/src/core/cicd/index.d.ts +12 -0
- package/dist/src/core/cicd/index.d.ts.map +1 -0
- package/dist/src/core/cicd/index.js +18 -0
- package/dist/src/core/cicd/index.js.map +1 -0
- package/dist/src/core/cicd/monitor-service.d.ts +92 -0
- package/dist/src/core/cicd/monitor-service.d.ts.map +1 -0
- package/dist/src/core/cicd/monitor-service.js +132 -0
- package/dist/src/core/cicd/monitor-service.js.map +1 -0
- package/dist/src/core/cicd/notifier.d.ts +102 -0
- package/dist/src/core/cicd/notifier.d.ts.map +1 -0
- package/dist/src/core/cicd/notifier.js +184 -0
- package/dist/src/core/cicd/notifier.js.map +1 -0
- package/dist/src/core/cicd/parent-repo-validator.d.ts +42 -0
- package/dist/src/core/cicd/parent-repo-validator.d.ts.map +1 -0
- package/dist/src/core/cicd/parent-repo-validator.js +201 -0
- package/dist/src/core/cicd/parent-repo-validator.js.map +1 -0
- package/dist/src/core/cicd/state-manager.d.ts +79 -0
- package/dist/src/core/cicd/state-manager.d.ts.map +1 -0
- package/dist/src/core/cicd/state-manager.js +197 -0
- package/dist/src/core/cicd/state-manager.js.map +1 -0
- package/dist/src/core/cicd/types.d.ts +119 -0
- package/dist/src/core/cicd/types.d.ts.map +1 -0
- package/dist/src/core/cicd/types.js +18 -0
- package/dist/src/core/cicd/types.js.map +1 -0
- package/dist/src/core/cicd/workflow-monitor.d.ts +98 -0
- package/dist/src/core/cicd/workflow-monitor.d.ts.map +1 -0
- package/dist/src/core/cicd/workflow-monitor.js +215 -0
- package/dist/src/core/cicd/workflow-monitor.js.map +1 -0
- package/dist/src/core/repo-structure/repo-structure-manager.d.ts +3 -0
- package/dist/src/core/repo-structure/repo-structure-manager.d.ts.map +1 -1
- package/dist/src/core/repo-structure/repo-structure-manager.js +5 -2
- package/dist/src/core/repo-structure/repo-structure-manager.js.map +1 -1
- package/dist/src/core/spec-content-sync.d.ts.map +1 -1
- package/dist/src/core/spec-content-sync.js +14 -6
- package/dist/src/core/spec-content-sync.js.map +1 -1
- package/package.json +2 -2
- package/plugins/specweave/agents/pm/AGENT.md +170 -2
- package/plugins/specweave/hooks/post-increment-planning.sh +89 -26
- package/plugins/specweave/hooks/user-prompt-submit.sh +4 -4
- package/plugins/specweave/skills/increment-planner/SKILL.md +15 -10
- package/plugins/specweave-ado/lib/ado-project-detector.js +32 -5
- package/plugins/specweave-ado/lib/ado-project-detector.ts +44 -5
- package/src/templates/AGENTS.md.template +55 -1
- package/src/templates/CLAUDE.md.template +51 -1
- package/dist/locales/de/.gitkeep +0 -0
- package/dist/locales/de/cli.json +0 -108
- package/dist/locales/en/cli.json +0 -287
- package/dist/locales/en/errors.json +0 -7
- package/dist/locales/en/templates.json +0 -6
- package/dist/locales/es/.gitkeep +0 -0
- package/dist/locales/es/cli.json +0 -41
- package/dist/locales/fr/.gitkeep +0 -0
- package/dist/locales/fr/cli.json +0 -108
- package/dist/locales/ja/.gitkeep +0 -0
- package/dist/locales/ja/cli.json +0 -108
- package/dist/locales/ko/.gitkeep +0 -0
- package/dist/locales/ko/cli.json +0 -108
- package/dist/locales/pt/.gitkeep +0 -0
- package/dist/locales/pt/cli.json +0 -108
- package/dist/locales/ru/.gitkeep +0 -0
- package/dist/locales/ru/cli.json +0 -269
- package/dist/locales/zh/.gitkeep +0 -0
- package/dist/locales/zh/cli.json +0 -108
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CI/CD Failure Notifier
|
|
3
|
+
*
|
|
4
|
+
* Sends notifications when workflow failures are detected.
|
|
5
|
+
* Supports multiple notification channels (console, file, webhook).
|
|
6
|
+
*/
|
|
7
|
+
import { FailureRecord } from './types';
|
|
8
|
+
/**
|
|
9
|
+
* Notification channel types
|
|
10
|
+
*/
|
|
11
|
+
export type NotificationChannel = 'console' | 'file' | 'webhook';
|
|
12
|
+
/**
|
|
13
|
+
* Notification configuration
|
|
14
|
+
*/
|
|
15
|
+
export interface NotifierConfig {
|
|
16
|
+
/** Enabled channels */
|
|
17
|
+
channels: NotificationChannel[];
|
|
18
|
+
/** Log file path (for 'file' channel) */
|
|
19
|
+
logFile?: string;
|
|
20
|
+
/** Webhook URL (for 'webhook' channel) */
|
|
21
|
+
webhookUrl?: string;
|
|
22
|
+
/** Enable debug logging */
|
|
23
|
+
debug?: boolean;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Notification payload
|
|
27
|
+
*/
|
|
28
|
+
export interface Notification {
|
|
29
|
+
/** Notification type */
|
|
30
|
+
type: 'failure_detected' | 'analysis_complete' | 'fix_applied';
|
|
31
|
+
/** Failure record */
|
|
32
|
+
failure: FailureRecord;
|
|
33
|
+
/** Additional message */
|
|
34
|
+
message?: string;
|
|
35
|
+
/** Timestamp */
|
|
36
|
+
timestamp: string;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Notifier - Sends failure notifications to configured channels
|
|
40
|
+
*
|
|
41
|
+
* Features:
|
|
42
|
+
* - Multiple notification channels (console, file, webhook)
|
|
43
|
+
* - Structured notification format
|
|
44
|
+
* - Async delivery (non-blocking)
|
|
45
|
+
* - Error handling and retry logic
|
|
46
|
+
*/
|
|
47
|
+
export declare class Notifier {
|
|
48
|
+
private config;
|
|
49
|
+
/**
|
|
50
|
+
* Create notifier
|
|
51
|
+
*
|
|
52
|
+
* @param config - Notification configuration
|
|
53
|
+
*/
|
|
54
|
+
constructor(config: NotifierConfig);
|
|
55
|
+
/**
|
|
56
|
+
* Send notification about failure detection
|
|
57
|
+
*
|
|
58
|
+
* @param failure - Failure record
|
|
59
|
+
*/
|
|
60
|
+
notifyFailureDetected(failure: FailureRecord): Promise<void>;
|
|
61
|
+
/**
|
|
62
|
+
* Send notification about analysis completion
|
|
63
|
+
*
|
|
64
|
+
* @param failure - Failure record
|
|
65
|
+
* @param analysis - Analysis result
|
|
66
|
+
*/
|
|
67
|
+
notifyAnalysisComplete(failure: FailureRecord, analysis: string): Promise<void>;
|
|
68
|
+
/**
|
|
69
|
+
* Send notification about fix application
|
|
70
|
+
*
|
|
71
|
+
* @param failure - Failure record
|
|
72
|
+
* @param fixDetails - Fix details
|
|
73
|
+
*/
|
|
74
|
+
notifyFixApplied(failure: FailureRecord, fixDetails: string): Promise<void>;
|
|
75
|
+
/**
|
|
76
|
+
* Send notification to all configured channels
|
|
77
|
+
*
|
|
78
|
+
* @param notification - Notification payload
|
|
79
|
+
*/
|
|
80
|
+
private send;
|
|
81
|
+
/**
|
|
82
|
+
* Send notification to console (stderr for visibility)
|
|
83
|
+
*/
|
|
84
|
+
private sendToConsole;
|
|
85
|
+
/**
|
|
86
|
+
* Send notification to log file
|
|
87
|
+
*/
|
|
88
|
+
private sendToFile;
|
|
89
|
+
/**
|
|
90
|
+
* Send notification to webhook
|
|
91
|
+
*/
|
|
92
|
+
private sendToWebhook;
|
|
93
|
+
/**
|
|
94
|
+
* Get icon for notification type
|
|
95
|
+
*/
|
|
96
|
+
private getIcon;
|
|
97
|
+
/**
|
|
98
|
+
* Get ANSI color code for notification type
|
|
99
|
+
*/
|
|
100
|
+
private getColor;
|
|
101
|
+
}
|
|
102
|
+
//# sourceMappingURL=notifier.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"notifier.d.ts","sourceRoot":"","sources":["../../../../src/core/cicd/notifier.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAExC;;GAEG;AACH,MAAM,MAAM,mBAAmB,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAAC;AAEjE;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,uBAAuB;IACvB,QAAQ,EAAE,mBAAmB,EAAE,CAAC;IAEhC,yCAAyC;IACzC,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB,0CAA0C;IAC1C,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB,2BAA2B;IAC3B,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,wBAAwB;IACxB,IAAI,EAAE,kBAAkB,GAAG,mBAAmB,GAAG,aAAa,CAAC;IAE/D,qBAAqB;IACrB,OAAO,EAAE,aAAa,CAAC;IAEvB,yBAAyB;IACzB,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB,gBAAgB;IAChB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;;;GAQG;AACH,qBAAa,QAAQ;IACnB,OAAO,CAAC,MAAM,CAA2B;IAEzC;;;;OAIG;gBACS,MAAM,EAAE,cAAc;IASlC;;;;OAIG;IACG,qBAAqB,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IAWlE;;;;;OAKG;IACG,sBAAsB,CAC1B,OAAO,EAAE,aAAa,EACtB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,CAAC;IAWhB;;;;;OAKG;IACG,gBAAgB,CACpB,OAAO,EAAE,aAAa,EACtB,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,IAAI,CAAC;IAWhB;;;;OAIG;YACW,IAAI;IAmBlB;;OAEG;YACW,aAAa;IAW3B;;OAEG;YACW,UAAU;IAmBxB;;OAEG;YACW,aAAa;IA4B3B;;OAEG;IACH,OAAO,CAAC,OAAO;IAaf;;OAEG;IACH,OAAO,CAAC,QAAQ;CAYjB"}
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CI/CD Failure Notifier
|
|
3
|
+
*
|
|
4
|
+
* Sends notifications when workflow failures are detected.
|
|
5
|
+
* Supports multiple notification channels (console, file, webhook).
|
|
6
|
+
*/
|
|
7
|
+
import * as fs from 'fs-extra';
|
|
8
|
+
import * as path from 'path';
|
|
9
|
+
/**
|
|
10
|
+
* Notifier - Sends failure notifications to configured channels
|
|
11
|
+
*
|
|
12
|
+
* Features:
|
|
13
|
+
* - Multiple notification channels (console, file, webhook)
|
|
14
|
+
* - Structured notification format
|
|
15
|
+
* - Async delivery (non-blocking)
|
|
16
|
+
* - Error handling and retry logic
|
|
17
|
+
*/
|
|
18
|
+
export class Notifier {
|
|
19
|
+
/**
|
|
20
|
+
* Create notifier
|
|
21
|
+
*
|
|
22
|
+
* @param config - Notification configuration
|
|
23
|
+
*/
|
|
24
|
+
constructor(config) {
|
|
25
|
+
this.config = {
|
|
26
|
+
channels: config.channels,
|
|
27
|
+
logFile: config.logFile ?? '.specweave/logs/cicd-notifications.log',
|
|
28
|
+
webhookUrl: config.webhookUrl ?? '',
|
|
29
|
+
debug: config.debug ?? false
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Send notification about failure detection
|
|
34
|
+
*
|
|
35
|
+
* @param failure - Failure record
|
|
36
|
+
*/
|
|
37
|
+
async notifyFailureDetected(failure) {
|
|
38
|
+
const notification = {
|
|
39
|
+
type: 'failure_detected',
|
|
40
|
+
failure,
|
|
41
|
+
message: `Workflow "${failure.workflowName}" failed (run #${failure.runId})`,
|
|
42
|
+
timestamp: new Date().toISOString()
|
|
43
|
+
};
|
|
44
|
+
await this.send(notification);
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Send notification about analysis completion
|
|
48
|
+
*
|
|
49
|
+
* @param failure - Failure record
|
|
50
|
+
* @param analysis - Analysis result
|
|
51
|
+
*/
|
|
52
|
+
async notifyAnalysisComplete(failure, analysis) {
|
|
53
|
+
const notification = {
|
|
54
|
+
type: 'analysis_complete',
|
|
55
|
+
failure,
|
|
56
|
+
message: `Root cause analysis complete for ${failure.workflowName}:\n${analysis}`,
|
|
57
|
+
timestamp: new Date().toISOString()
|
|
58
|
+
};
|
|
59
|
+
await this.send(notification);
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Send notification about fix application
|
|
63
|
+
*
|
|
64
|
+
* @param failure - Failure record
|
|
65
|
+
* @param fixDetails - Fix details
|
|
66
|
+
*/
|
|
67
|
+
async notifyFixApplied(failure, fixDetails) {
|
|
68
|
+
const notification = {
|
|
69
|
+
type: 'fix_applied',
|
|
70
|
+
failure,
|
|
71
|
+
message: `Fix applied for ${failure.workflowName}:\n${fixDetails}`,
|
|
72
|
+
timestamp: new Date().toISOString()
|
|
73
|
+
};
|
|
74
|
+
await this.send(notification);
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Send notification to all configured channels
|
|
78
|
+
*
|
|
79
|
+
* @param notification - Notification payload
|
|
80
|
+
*/
|
|
81
|
+
async send(notification) {
|
|
82
|
+
const promises = this.config.channels.map((channel) => {
|
|
83
|
+
switch (channel) {
|
|
84
|
+
case 'console':
|
|
85
|
+
return this.sendToConsole(notification);
|
|
86
|
+
case 'file':
|
|
87
|
+
return this.sendToFile(notification);
|
|
88
|
+
case 'webhook':
|
|
89
|
+
return this.sendToWebhook(notification);
|
|
90
|
+
default:
|
|
91
|
+
console.warn(`Unknown notification channel: ${channel}`);
|
|
92
|
+
return Promise.resolve();
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
// Send to all channels (non-blocking, errors logged)
|
|
96
|
+
await Promise.allSettled(promises);
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Send notification to console (stderr for visibility)
|
|
100
|
+
*/
|
|
101
|
+
async sendToConsole(notification) {
|
|
102
|
+
const icon = this.getIcon(notification.type);
|
|
103
|
+
const color = this.getColor(notification.type);
|
|
104
|
+
console.error(`${color}${icon} ${notification.message}\x1b[0m`);
|
|
105
|
+
if (this.config.debug) {
|
|
106
|
+
console.error('Full notification:', JSON.stringify(notification, null, 2));
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Send notification to log file
|
|
111
|
+
*/
|
|
112
|
+
async sendToFile(notification) {
|
|
113
|
+
try {
|
|
114
|
+
await fs.ensureDir(path.dirname(this.config.logFile));
|
|
115
|
+
const logLine = `${notification.timestamp} [${notification.type}] ${notification.message}\n`;
|
|
116
|
+
await fs.appendFile(this.config.logFile, logLine, 'utf-8');
|
|
117
|
+
if (this.config.debug) {
|
|
118
|
+
await fs.appendFile(this.config.logFile, `${JSON.stringify(notification, null, 2)}\n`, 'utf-8');
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
catch (error) {
|
|
122
|
+
console.error('Failed to write notification to file:', error);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Send notification to webhook
|
|
127
|
+
*/
|
|
128
|
+
async sendToWebhook(notification) {
|
|
129
|
+
if (!this.config.webhookUrl) {
|
|
130
|
+
console.warn('Webhook URL not configured, skipping webhook notification');
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
try {
|
|
134
|
+
// Use native fetch (Node.js 18+)
|
|
135
|
+
const response = await fetch(this.config.webhookUrl, {
|
|
136
|
+
method: 'POST',
|
|
137
|
+
headers: {
|
|
138
|
+
'Content-Type': 'application/json'
|
|
139
|
+
},
|
|
140
|
+
body: JSON.stringify(notification)
|
|
141
|
+
});
|
|
142
|
+
if (!response.ok) {
|
|
143
|
+
throw new Error(`Webhook returned ${response.status}: ${response.statusText}`);
|
|
144
|
+
}
|
|
145
|
+
if (this.config.debug) {
|
|
146
|
+
console.log('Webhook notification sent successfully');
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
catch (error) {
|
|
150
|
+
console.error('Failed to send webhook notification:', error);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Get icon for notification type
|
|
155
|
+
*/
|
|
156
|
+
getIcon(type) {
|
|
157
|
+
switch (type) {
|
|
158
|
+
case 'failure_detected':
|
|
159
|
+
return '🚨';
|
|
160
|
+
case 'analysis_complete':
|
|
161
|
+
return '🔍';
|
|
162
|
+
case 'fix_applied':
|
|
163
|
+
return '✅';
|
|
164
|
+
default:
|
|
165
|
+
return '📢';
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Get ANSI color code for notification type
|
|
170
|
+
*/
|
|
171
|
+
getColor(type) {
|
|
172
|
+
switch (type) {
|
|
173
|
+
case 'failure_detected':
|
|
174
|
+
return '\x1b[31m'; // Red
|
|
175
|
+
case 'analysis_complete':
|
|
176
|
+
return '\x1b[33m'; // Yellow
|
|
177
|
+
case 'fix_applied':
|
|
178
|
+
return '\x1b[32m'; // Green
|
|
179
|
+
default:
|
|
180
|
+
return '\x1b[37m'; // White
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
//# sourceMappingURL=notifier.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"notifier.js","sourceRoot":"","sources":["../../../../src/core/cicd/notifier.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parent Repository Validation Utility
|
|
3
|
+
*
|
|
4
|
+
* Validates consistency of parent repo naming across:
|
|
5
|
+
* - .specweave/config.json (source of truth)
|
|
6
|
+
* - Git remote (origin)
|
|
7
|
+
* - .env file (if exists)
|
|
8
|
+
*
|
|
9
|
+
* Prevents the common mistake of creating duplicate parent repos
|
|
10
|
+
* when using multi-project mode with -shared flag.
|
|
11
|
+
*/
|
|
12
|
+
export interface ValidationResult {
|
|
13
|
+
valid: boolean;
|
|
14
|
+
errors: string[];
|
|
15
|
+
warnings: string[];
|
|
16
|
+
configName?: string;
|
|
17
|
+
gitRemoteName?: string;
|
|
18
|
+
envName?: string;
|
|
19
|
+
}
|
|
20
|
+
export interface ParentRepoCheck {
|
|
21
|
+
configParentName: string | null;
|
|
22
|
+
gitRemoteName: string | null;
|
|
23
|
+
envParentName: string | null;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Get all parent repo names from different sources
|
|
27
|
+
*/
|
|
28
|
+
export declare function checkParentRepoSetup(projectRoot: string): ParentRepoCheck;
|
|
29
|
+
/**
|
|
30
|
+
* Validate parent repo setup consistency
|
|
31
|
+
*/
|
|
32
|
+
export declare function validateParentRepoSetup(projectRoot: string): ValidationResult;
|
|
33
|
+
/**
|
|
34
|
+
* Print validation result to console
|
|
35
|
+
*/
|
|
36
|
+
export declare function printValidationResult(result: ValidationResult): void;
|
|
37
|
+
/**
|
|
38
|
+
* Validate and exit with error code if validation fails
|
|
39
|
+
* Use this in CLI commands that require valid parent repo setup
|
|
40
|
+
*/
|
|
41
|
+
export declare function validateOrExit(projectRoot: string): void;
|
|
42
|
+
//# sourceMappingURL=parent-repo-validator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parent-repo-validator.d.ts","sourceRoot":"","sources":["../../../../src/core/cicd/parent-repo-validator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAOH,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,eAAe;IAC9B,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9B;AAwED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,WAAW,EAAE,MAAM,GAAG,eAAe,CAMzE;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,WAAW,EAAE,MAAM,GAAG,gBAAgB,CAiF7E;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,gBAAgB,GAAG,IAAI,CA+CpE;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAYxD"}
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parent Repository Validation Utility
|
|
3
|
+
*
|
|
4
|
+
* Validates consistency of parent repo naming across:
|
|
5
|
+
* - .specweave/config.json (source of truth)
|
|
6
|
+
* - Git remote (origin)
|
|
7
|
+
* - .env file (if exists)
|
|
8
|
+
*
|
|
9
|
+
* Prevents the common mistake of creating duplicate parent repos
|
|
10
|
+
* when using multi-project mode with -shared flag.
|
|
11
|
+
*/
|
|
12
|
+
import * as fs from 'fs-extra';
|
|
13
|
+
import * as path from 'path';
|
|
14
|
+
import { execSync } from 'child_process';
|
|
15
|
+
import chalk from 'chalk';
|
|
16
|
+
/**
|
|
17
|
+
* Extract parent repo name from config.json
|
|
18
|
+
*/
|
|
19
|
+
function getConfigParentRepoName(projectRoot) {
|
|
20
|
+
const configPath = path.join(projectRoot, '.specweave', 'config.json');
|
|
21
|
+
if (!fs.existsSync(configPath)) {
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
try {
|
|
25
|
+
const config = fs.readJsonSync(configPath);
|
|
26
|
+
return config.multiProject?.parentRepoName || null;
|
|
27
|
+
}
|
|
28
|
+
catch (error) {
|
|
29
|
+
console.error(chalk.yellow('⚠️ Failed to parse config.json:'), error);
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Extract parent repo name from git remote origin
|
|
35
|
+
*/
|
|
36
|
+
function getGitRemoteRepoName(projectRoot) {
|
|
37
|
+
try {
|
|
38
|
+
const remoteUrl = execSync('git remote get-url origin', {
|
|
39
|
+
cwd: projectRoot,
|
|
40
|
+
encoding: 'utf-8',
|
|
41
|
+
stdio: ['pipe', 'pipe', 'ignore'] // Suppress stderr
|
|
42
|
+
}).trim();
|
|
43
|
+
// Extract repo name from URL
|
|
44
|
+
// Examples:
|
|
45
|
+
// - https://github.com/owner/repo.git → repo
|
|
46
|
+
// - git@github.com:owner/repo.git → repo
|
|
47
|
+
const match = remoteUrl.match(/\/([^\/]+?)(\.git)?$/);
|
|
48
|
+
return match ? match[1].replace('.git', '') : null;
|
|
49
|
+
}
|
|
50
|
+
catch (error) {
|
|
51
|
+
// Git remote doesn't exist or not a git repo
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Extract parent repo name from .env file
|
|
57
|
+
*/
|
|
58
|
+
function getEnvParentRepoName(projectRoot) {
|
|
59
|
+
const envPath = path.join(projectRoot, '.env');
|
|
60
|
+
if (!fs.existsSync(envPath)) {
|
|
61
|
+
return null;
|
|
62
|
+
}
|
|
63
|
+
try {
|
|
64
|
+
const envContent = fs.readFileSync(envPath, 'utf-8');
|
|
65
|
+
const match = envContent.match(/^PARENT_REPO_NAME=(.*)$/m);
|
|
66
|
+
if (!match) {
|
|
67
|
+
return null;
|
|
68
|
+
}
|
|
69
|
+
// Format: shared:repo-name or repo-name
|
|
70
|
+
const value = match[1].trim();
|
|
71
|
+
const parts = value.split(':');
|
|
72
|
+
return parts.length === 2 ? parts[1] : value;
|
|
73
|
+
}
|
|
74
|
+
catch (error) {
|
|
75
|
+
console.error(chalk.yellow('⚠️ Failed to read .env:'), error);
|
|
76
|
+
return null;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Get all parent repo names from different sources
|
|
81
|
+
*/
|
|
82
|
+
export function checkParentRepoSetup(projectRoot) {
|
|
83
|
+
return {
|
|
84
|
+
configParentName: getConfigParentRepoName(projectRoot),
|
|
85
|
+
gitRemoteName: getGitRemoteRepoName(projectRoot),
|
|
86
|
+
envParentName: getEnvParentRepoName(projectRoot)
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Validate parent repo setup consistency
|
|
91
|
+
*/
|
|
92
|
+
export function validateParentRepoSetup(projectRoot) {
|
|
93
|
+
const result = {
|
|
94
|
+
valid: true,
|
|
95
|
+
errors: [],
|
|
96
|
+
warnings: []
|
|
97
|
+
};
|
|
98
|
+
// Get all names
|
|
99
|
+
const check = checkParentRepoSetup(projectRoot);
|
|
100
|
+
result.configName = check.configParentName || undefined;
|
|
101
|
+
result.gitRemoteName = check.gitRemoteName || undefined;
|
|
102
|
+
result.envName = check.envParentName || undefined;
|
|
103
|
+
// Check 1: Config has parent repo name (if multi-project enabled)
|
|
104
|
+
const configPath = path.join(projectRoot, '.specweave', 'config.json');
|
|
105
|
+
if (fs.existsSync(configPath)) {
|
|
106
|
+
const config = fs.readJsonSync(configPath);
|
|
107
|
+
const multiProjectEnabled = config.multiProject?.enabled === true;
|
|
108
|
+
if (multiProjectEnabled && !check.configParentName) {
|
|
109
|
+
result.valid = false;
|
|
110
|
+
result.errors.push('❌ Multi-project enabled but parentRepoName not set in config.json');
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
// Check 2: Git remote matches config (if both exist)
|
|
114
|
+
if (check.configParentName && check.gitRemoteName) {
|
|
115
|
+
if (check.configParentName !== check.gitRemoteName) {
|
|
116
|
+
result.valid = false;
|
|
117
|
+
result.errors.push('❌ Git remote mismatch!', ` Config expects: ${check.configParentName}`, ` Git remote has: ${check.gitRemoteName}`, '', ' Fix with:', ` git remote set-url origin https://github.com/OWNER/${check.configParentName}.git`);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
// Check 3: .env matches config (if both exist)
|
|
121
|
+
if (check.configParentName && check.envParentName) {
|
|
122
|
+
if (check.configParentName !== check.envParentName) {
|
|
123
|
+
result.warnings.push('⚠️ .env mismatch (will be ignored):', ` Config: ${check.configParentName}`, ` .env: ${check.envParentName}`, '', ' Update .env to match config.json');
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
// Check 4: -shared suffix consistency
|
|
127
|
+
if (check.configParentName && check.configParentName.endsWith('-shared')) {
|
|
128
|
+
// Config has -shared, check git and env also have it
|
|
129
|
+
if (check.gitRemoteName && !check.gitRemoteName.endsWith('-shared')) {
|
|
130
|
+
result.valid = false;
|
|
131
|
+
result.errors.push('❌ Config has -shared suffix, but git remote doesn\'t', '', ` Config: ${check.configParentName} (has -shared)`, ` Git: ${check.gitRemoteName} (missing -shared)`, '');
|
|
132
|
+
}
|
|
133
|
+
if (check.envParentName && !check.envParentName.endsWith('-shared')) {
|
|
134
|
+
result.warnings.push('⚠️ Config has -shared suffix, but .env doesn\'t', '', ` Config: ${check.configParentName} (has -shared)`, ` .env: ${check.envParentName} (missing -shared)`, '');
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
return result;
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Print validation result to console
|
|
141
|
+
*/
|
|
142
|
+
export function printValidationResult(result) {
|
|
143
|
+
console.log('\n🔍 Validating Parent Repo Setup...\n');
|
|
144
|
+
// Show current setup
|
|
145
|
+
console.log('📋 Current Setup:\n');
|
|
146
|
+
console.log(` Config (parentRepoName): ${result.configName || chalk.gray('<not set>')}`);
|
|
147
|
+
console.log(` Git Remote (origin): ${result.gitRemoteName || chalk.gray('<not set>')}`);
|
|
148
|
+
console.log(` .env (PARENT_REPO_NAME): ${result.envName || chalk.gray('<not set>')}`);
|
|
149
|
+
console.log('');
|
|
150
|
+
// Show errors
|
|
151
|
+
if (result.errors.length > 0) {
|
|
152
|
+
result.errors.forEach(error => {
|
|
153
|
+
console.log(chalk.red(error));
|
|
154
|
+
});
|
|
155
|
+
console.log('');
|
|
156
|
+
}
|
|
157
|
+
// Show warnings
|
|
158
|
+
if (result.warnings.length > 0) {
|
|
159
|
+
result.warnings.forEach(warning => {
|
|
160
|
+
console.log(chalk.yellow(warning));
|
|
161
|
+
});
|
|
162
|
+
console.log('');
|
|
163
|
+
}
|
|
164
|
+
// Summary
|
|
165
|
+
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
|
|
166
|
+
if (result.valid && result.warnings.length === 0) {
|
|
167
|
+
console.log(chalk.green('✅ All checks passed!'));
|
|
168
|
+
console.log('\nYour parent repo setup is consistent across:');
|
|
169
|
+
console.log(' ✓ .specweave/config.json');
|
|
170
|
+
console.log(' ✓ git remote (origin)');
|
|
171
|
+
if (result.envName) {
|
|
172
|
+
console.log(' ✓ .env');
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
else {
|
|
176
|
+
if (!result.valid) {
|
|
177
|
+
console.log(chalk.red(`❌ Validation failed with ${result.errors.length} error(s)`));
|
|
178
|
+
}
|
|
179
|
+
if (result.warnings.length > 0) {
|
|
180
|
+
console.log(chalk.yellow(`⚠️ Found ${result.warnings.length} warning(s)`));
|
|
181
|
+
}
|
|
182
|
+
console.log('\nPlease fix the issues above before syncing to GitHub.');
|
|
183
|
+
}
|
|
184
|
+
console.log('');
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Validate and exit with error code if validation fails
|
|
188
|
+
* Use this in CLI commands that require valid parent repo setup
|
|
189
|
+
*/
|
|
190
|
+
export function validateOrExit(projectRoot) {
|
|
191
|
+
const result = validateParentRepoSetup(projectRoot);
|
|
192
|
+
printValidationResult(result);
|
|
193
|
+
if (!result.valid) {
|
|
194
|
+
process.exit(1);
|
|
195
|
+
}
|
|
196
|
+
// Show warnings but don't exit
|
|
197
|
+
if (result.warnings.length > 0) {
|
|
198
|
+
console.log(chalk.yellow('⚠️ Warnings detected but continuing...\n'));
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
//# sourceMappingURL=parent-repo-validator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parent-repo-validator.js","sourceRoot":"","sources":["../../../../src/core/cicd/parent-repo-validator.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CI/CD Monitor State Manager
|
|
3
|
+
*
|
|
4
|
+
* Manages persistent state for workflow monitoring, failure detection,
|
|
5
|
+
* and deduplication. Uses file-based storage with locking to prevent
|
|
6
|
+
* concurrent write corruption.
|
|
7
|
+
*/
|
|
8
|
+
import { CICDMonitorState, FailureRecord, IStateManager } from './types';
|
|
9
|
+
/**
|
|
10
|
+
* StateManager - Manages CI/CD monitor persistent state
|
|
11
|
+
*
|
|
12
|
+
* Features:
|
|
13
|
+
* - File-based JSON storage
|
|
14
|
+
* - File locking to prevent corruption
|
|
15
|
+
* - Automatic directory creation
|
|
16
|
+
* - State migration support
|
|
17
|
+
* - Deduplication tracking
|
|
18
|
+
*/
|
|
19
|
+
export declare class StateManager implements IStateManager {
|
|
20
|
+
private statePath;
|
|
21
|
+
private lockPath;
|
|
22
|
+
/**
|
|
23
|
+
* Create state manager
|
|
24
|
+
*
|
|
25
|
+
* @param rootDir - Project root directory (defaults to cwd)
|
|
26
|
+
*/
|
|
27
|
+
constructor(rootDir?: string);
|
|
28
|
+
/**
|
|
29
|
+
* Load state from disk
|
|
30
|
+
*
|
|
31
|
+
* @returns Current state (or default if file doesn't exist)
|
|
32
|
+
*/
|
|
33
|
+
loadState(): Promise<CICDMonitorState>;
|
|
34
|
+
/**
|
|
35
|
+
* Save state to disk with file locking
|
|
36
|
+
*
|
|
37
|
+
* @param state - State to save
|
|
38
|
+
*/
|
|
39
|
+
saveState(state: CICDMonitorState): Promise<void>;
|
|
40
|
+
/**
|
|
41
|
+
* Mark failure as processed (deduplication)
|
|
42
|
+
*
|
|
43
|
+
* @param runId - Workflow run ID
|
|
44
|
+
*/
|
|
45
|
+
markProcessed(runId: number): Promise<void>;
|
|
46
|
+
/**
|
|
47
|
+
* Get last poll timestamp
|
|
48
|
+
*
|
|
49
|
+
* @returns ISO 8601 timestamp or null
|
|
50
|
+
*/
|
|
51
|
+
getLastPoll(): Promise<string | null>;
|
|
52
|
+
/**
|
|
53
|
+
* Update last poll timestamp to now
|
|
54
|
+
*/
|
|
55
|
+
updateLastPoll(): Promise<void>;
|
|
56
|
+
/**
|
|
57
|
+
* Add failure record
|
|
58
|
+
*
|
|
59
|
+
* @param failure - Failure record to add
|
|
60
|
+
*/
|
|
61
|
+
addFailure(failure: FailureRecord): Promise<void>;
|
|
62
|
+
/**
|
|
63
|
+
* Get all unprocessed failures
|
|
64
|
+
*
|
|
65
|
+
* @returns Array of unprocessed failure records
|
|
66
|
+
*/
|
|
67
|
+
getUnprocessedFailures(): Promise<FailureRecord[]>;
|
|
68
|
+
/**
|
|
69
|
+
* Acquire file lock (with timeout)
|
|
70
|
+
*
|
|
71
|
+
* Prevents concurrent writes from corrupting state file.
|
|
72
|
+
*/
|
|
73
|
+
private acquireLock;
|
|
74
|
+
/**
|
|
75
|
+
* Release file lock
|
|
76
|
+
*/
|
|
77
|
+
private releaseLock;
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=state-manager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"state-manager.d.ts","sourceRoot":"","sources":["../../../../src/core/cicd/state-manager.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,OAAO,EACL,gBAAgB,EAEhB,aAAa,EACb,aAAa,EACd,MAAM,SAAS,CAAC;AAiBjB;;;;;;;;;GASG;AACH,qBAAa,YAAa,YAAW,aAAa;IAChD,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,QAAQ,CAAS;IAEzB;;;;OAIG;gBACS,OAAO,GAAE,MAAsB;IAK3C;;;;OAIG;IACG,SAAS,IAAI,OAAO,CAAC,gBAAgB,CAAC;IA6B5C;;;;OAIG;IACG,SAAS,CAAC,KAAK,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC;IAkBvD;;;;OAIG;IACG,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAUjD;;;;OAIG;IACG,WAAW,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAK3C;;OAEG;IACG,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC;IAMrC;;;;OAIG;IACG,UAAU,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IAgBvD;;;;OAIG;IACG,sBAAsB,IAAI,OAAO,CAAC,aAAa,EAAE,CAAC;IAQxD;;;;OAIG;YACW,WAAW;IAkCzB;;OAEG;YACW,WAAW;CAO1B"}
|