ado-sync 0.1.47 → 0.1.49
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/.next-steps.md +179 -0
- package/README.md +13 -0
- package/dist/ai/summarizer.js +6 -3
- package/dist/ai/summarizer.js.map +1 -1
- package/dist/azure/test-cases.js +28 -10
- package/dist/azure/test-cases.js.map +1 -1
- package/dist/azure/work-items.d.ts +28 -0
- package/dist/azure/work-items.js +96 -0
- package/dist/azure/work-items.js.map +1 -1
- package/dist/cli.js +362 -25
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts +0 -5
- package/dist/config.js +17 -3
- package/dist/config.js.map +1 -1
- package/dist/issues/ado-bugs.d.ts +23 -0
- package/dist/issues/ado-bugs.js +59 -0
- package/dist/issues/ado-bugs.js.map +1 -0
- package/dist/issues/create-issues.d.ts +32 -0
- package/dist/issues/create-issues.js +236 -0
- package/dist/issues/create-issues.js.map +1 -0
- package/dist/issues/github.d.ts +22 -0
- package/dist/issues/github.js +95 -0
- package/dist/issues/github.js.map +1 -0
- package/dist/mcp-server.d.ts +3 -0
- package/dist/mcp-server.js +154 -20
- package/dist/mcp-server.js.map +1 -1
- package/dist/parsers/gherkin.js +2 -1
- package/dist/parsers/gherkin.js.map +1 -1
- package/dist/sync/engine.d.ts +41 -0
- package/dist/sync/engine.js +176 -10
- package/dist/sync/engine.js.map +1 -1
- package/dist/sync/manifest.d.ts +69 -0
- package/dist/sync/manifest.js +197 -0
- package/dist/sync/manifest.js.map +1 -0
- package/dist/sync/publish-results.d.ts +8 -1
- package/dist/sync/publish-results.js +167 -5
- package/dist/sync/publish-results.js.map +1 -1
- package/dist/sync/writeback.js +41 -20
- package/dist/sync/writeback.js.map +1 -1
- package/dist/types.d.ts +53 -0
- package/docs/mcp-server.md +131 -29
- package/docs/publish-test-results.md +136 -2
- package/docs/vscode-extension.md +139 -0
- package/llms.txt +28 -3
- package/package.json +2 -2
- package/.cucumber/.ado-sync-state.json +0 -282
- package/.cucumber/ado-sync.yaml +0 -21
- package/.cucumber/features/cart.feature +0 -62
- package/.cucumber/features/checkout.feature +0 -100
- package/.cucumber/features/homepage.feature +0 -7
- package/.cucumber/features/inventory.feature +0 -59
- package/.cucumber/features/login.feature +0 -74
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Create GitHub Issues or ADO Bugs for failed test results.
|
|
4
|
+
*
|
|
5
|
+
* Guards applied in order before any issue is filed:
|
|
6
|
+
* 1. Failure-rate threshold — if >N% fail → one environment-failure issue
|
|
7
|
+
* 2. Error clustering — same error message → one cluster issue per group
|
|
8
|
+
* 3. Hard cap — stop after maxIssues; file one overflow summary
|
|
9
|
+
* 4. Dedup — skip if an open issue for the same TC already exists
|
|
10
|
+
*/
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.createIssuesFromResults = createIssuesFromResults;
|
|
13
|
+
const ado_bugs_1 = require("./ado-bugs");
|
|
14
|
+
const github_1 = require("./github");
|
|
15
|
+
// ─── Main entry point ─────────────────────────────────────────────────────────
|
|
16
|
+
async function createIssuesFromResults(results, config, issueConfig, runInfo, dryRun = false) {
|
|
17
|
+
const failed = results.filter((r) => r.outcome === 'Failed');
|
|
18
|
+
const totalFailed = failed.length;
|
|
19
|
+
const totalResults = runInfo.totalResults;
|
|
20
|
+
const threshold = issueConfig.threshold ?? 20;
|
|
21
|
+
const maxIssues = issueConfig.maxIssues ?? 50;
|
|
22
|
+
const clusterByError = issueConfig.clusterByError !== false;
|
|
23
|
+
const dedupEnabled = issueConfig.dedupByTestCase !== false;
|
|
24
|
+
const provider = issueConfig.provider ?? 'github';
|
|
25
|
+
const issued = [];
|
|
26
|
+
let suppressed = 0;
|
|
27
|
+
if (totalFailed === 0) {
|
|
28
|
+
return { mode: 'per-test', issued, totalFailed: 0, suppressed: 0 };
|
|
29
|
+
}
|
|
30
|
+
// ── Guard 1: Failure-rate threshold ─────────────────────────────────────────
|
|
31
|
+
const failureRate = totalResults > 0 ? (totalFailed / totalResults) * 100 : 100;
|
|
32
|
+
if (failureRate > threshold) {
|
|
33
|
+
const title = `[ENV FAILURE] ${totalFailed}/${totalResults} tests failed (${Math.round(failureRate)}%)`;
|
|
34
|
+
if (dryRun) {
|
|
35
|
+
return { mode: 'environment', issued: [{ action: 'created', title, reason: 'dry-run' }], totalFailed, suppressed: totalFailed - 1 };
|
|
36
|
+
}
|
|
37
|
+
const body = buildEnvFailureBody(failed, runInfo);
|
|
38
|
+
const url = await fileIssue(provider, config, issueConfig, title, body, ['test-failure', 'environment-failure']);
|
|
39
|
+
return { mode: 'environment', issued: [{ action: 'created', url, title }], totalFailed, suppressed: totalFailed - 1 };
|
|
40
|
+
}
|
|
41
|
+
// ── Guard 2: Error clustering ────────────────────────────────────────────────
|
|
42
|
+
const batches = clusterByError ? clusterByErrorSignature(failed) : failed.map((t) => [t]);
|
|
43
|
+
const mode = batches.some((b) => b.length > 1) ? 'cluster' : 'per-test';
|
|
44
|
+
for (const batch of batches) {
|
|
45
|
+
// ── Guard 3: Hard cap ──────────────────────────────────────────────────────
|
|
46
|
+
if (issued.filter((i) => i.action === 'created').length >= maxIssues) {
|
|
47
|
+
suppressed += batch.length;
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
const isCluster = batch.length > 1;
|
|
51
|
+
const first = batch[0];
|
|
52
|
+
const title = isCluster
|
|
53
|
+
? `[CLUSTER] ${errorSignature(first.errorMessage)} (${batch.length} tests)`
|
|
54
|
+
: `[FAILED] ${first.testName}`;
|
|
55
|
+
// ── Guard 4: Dedup ─────────────────────────────────────────────────────────
|
|
56
|
+
if (dedupEnabled && !isCluster && first.testCaseId !== undefined) {
|
|
57
|
+
const existing = await checkDuplicate(provider, config, issueConfig, first);
|
|
58
|
+
if (existing) {
|
|
59
|
+
issued.push({ action: 'skipped', title, reason: `open issue exists: ${existing}` });
|
|
60
|
+
continue;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
if (dryRun) {
|
|
64
|
+
issued.push({ action: 'created', title, reason: 'dry-run' });
|
|
65
|
+
continue;
|
|
66
|
+
}
|
|
67
|
+
const labels = isCluster ? [...(issueConfig.labels ?? ['test-failure']), 'error-cluster']
|
|
68
|
+
: buildLabels(issueConfig.labels, first.testCaseId);
|
|
69
|
+
const body = isCluster
|
|
70
|
+
? buildClusterBody(batch, runInfo)
|
|
71
|
+
: buildTestFailureBody(first, runInfo, config.orgUrl, config.project);
|
|
72
|
+
const url = await fileIssue(provider, config, issueConfig, title, body, labels, isCluster ? undefined : first);
|
|
73
|
+
issued.push({ action: 'created', url, title });
|
|
74
|
+
}
|
|
75
|
+
// ── Guard 3 overflow summary ─────────────────────────────────────────────────
|
|
76
|
+
if (suppressed > 0 && !dryRun) {
|
|
77
|
+
const title = `[OVERFLOW] ${suppressed} additional failures suppressed (cap: ${maxIssues})`;
|
|
78
|
+
const body = [
|
|
79
|
+
`**${issued.filter((i) => i.action === 'created').length}** issues were filed for this run.`,
|
|
80
|
+
`An additional **${suppressed}** failures were suppressed to stay within the \`maxIssues\` limit of ${maxIssues}.`,
|
|
81
|
+
'',
|
|
82
|
+
runInfo.runUrl ? `[View full test run](${runInfo.runUrl})` : '',
|
|
83
|
+
'',
|
|
84
|
+
'Consider investigating whether this is an environment-level failure.',
|
|
85
|
+
].join('\n');
|
|
86
|
+
const url = await fileIssue(provider, config, issueConfig, title, body, ['test-failure', 'overflow']);
|
|
87
|
+
issued.push({ action: 'created', url, title });
|
|
88
|
+
}
|
|
89
|
+
return { mode, issued, totalFailed, suppressed };
|
|
90
|
+
}
|
|
91
|
+
// ─── Clustering ───────────────────────────────────────────────────────────────
|
|
92
|
+
/** Returns a short human-readable fingerprint of an error message. */
|
|
93
|
+
function errorSignature(msg) {
|
|
94
|
+
if (!msg)
|
|
95
|
+
return 'unknown error';
|
|
96
|
+
// Take first non-empty line, strip timestamps/numbers, cap length
|
|
97
|
+
const first = msg.split('\n').map((l) => l.trim()).find((l) => l.length > 0) ?? msg;
|
|
98
|
+
return first.replace(/\d+/g, 'N').slice(0, 80);
|
|
99
|
+
}
|
|
100
|
+
/** Group failures by error signature. Clusters with >1 member go first. */
|
|
101
|
+
function clusterByErrorSignature(failed) {
|
|
102
|
+
const map = new Map();
|
|
103
|
+
for (const r of failed) {
|
|
104
|
+
const key = errorSignature(r.errorMessage);
|
|
105
|
+
if (!map.has(key))
|
|
106
|
+
map.set(key, []);
|
|
107
|
+
map.get(key).push(r);
|
|
108
|
+
}
|
|
109
|
+
// Largest clusters first so we use the cap budget on the most impactful groups
|
|
110
|
+
return [...map.values()].sort((a, b) => b.length - a.length);
|
|
111
|
+
}
|
|
112
|
+
// ─── Dedup ────────────────────────────────────────────────────────────────────
|
|
113
|
+
async function checkDuplicate(provider, config, issueConfig, result) {
|
|
114
|
+
const tcId = result.testCaseId;
|
|
115
|
+
if (provider === 'github') {
|
|
116
|
+
const token = resolveToken(issueConfig.token);
|
|
117
|
+
if (!token || !issueConfig.repo)
|
|
118
|
+
return null;
|
|
119
|
+
const existing = await (0, github_1.findOpenGitHubIssueByLabel)(issueConfig.repo, token, `tc:${tcId}`).catch(() => null);
|
|
120
|
+
return existing ? existing.html_url : null;
|
|
121
|
+
}
|
|
122
|
+
else {
|
|
123
|
+
const existingId = await (0, ado_bugs_1.findOpenAdoBug)(config, `[FAILED] ${result.testName}`).catch(() => null);
|
|
124
|
+
return existingId ? `${config.orgUrl}/${config.project}/_workitems/edit/${existingId}` : null;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
// ─── Issue filing ─────────────────────────────────────────────────────────────
|
|
128
|
+
async function fileIssue(provider, config, issueConfig, title, body, labels, result) {
|
|
129
|
+
if (provider === 'github') {
|
|
130
|
+
const token = resolveToken(issueConfig.token);
|
|
131
|
+
if (!token)
|
|
132
|
+
throw new Error('GitHub token is required (--github-token or createIssuesOnFailure.token)');
|
|
133
|
+
if (!issueConfig.repo)
|
|
134
|
+
throw new Error('GitHub repo is required (--github-repo or createIssuesOnFailure.repo)');
|
|
135
|
+
const issue = await (0, github_1.createGitHubIssue)({
|
|
136
|
+
repo: issueConfig.repo, token, title, body, labels,
|
|
137
|
+
assignees: issueConfig.assignees,
|
|
138
|
+
});
|
|
139
|
+
return issue.html_url;
|
|
140
|
+
}
|
|
141
|
+
else {
|
|
142
|
+
const bug = await (0, ado_bugs_1.createAdoBug)(config, {
|
|
143
|
+
title, body,
|
|
144
|
+
areaPath: issueConfig.areaPath,
|
|
145
|
+
assignTo: issueConfig.assignTo,
|
|
146
|
+
testCaseId: result?.testCaseId,
|
|
147
|
+
});
|
|
148
|
+
return bug.url;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
function buildLabels(base, tcId) {
|
|
152
|
+
const labels = [...(base ?? ['test-failure'])];
|
|
153
|
+
if (tcId !== undefined)
|
|
154
|
+
labels.push(`tc:${tcId}`);
|
|
155
|
+
return labels;
|
|
156
|
+
}
|
|
157
|
+
/** Resolve $ENV_VAR references in token strings. */
|
|
158
|
+
function resolveToken(token) {
|
|
159
|
+
if (!token)
|
|
160
|
+
return token;
|
|
161
|
+
if (token.startsWith('$'))
|
|
162
|
+
return process.env[token.slice(1)];
|
|
163
|
+
return token;
|
|
164
|
+
}
|
|
165
|
+
// ─── Issue body builders ──────────────────────────────────────────────────────
|
|
166
|
+
function buildTestFailureBody(result, runInfo, orgUrl, project) {
|
|
167
|
+
const tcLink = result.testCaseId
|
|
168
|
+
? `[#${result.testCaseId}](${orgUrl.replace(/\/$/, '')}/${project}/_testManagement?testCaseId=${result.testCaseId})`
|
|
169
|
+
: '—';
|
|
170
|
+
const runLink = runInfo.runUrl ? `[View run](${runInfo.runUrl})` : '—';
|
|
171
|
+
const buildLink = runInfo.buildId ? `#${runInfo.buildId}` : '—';
|
|
172
|
+
const lines = [
|
|
173
|
+
`## Test failure: ${result.testName}`,
|
|
174
|
+
'',
|
|
175
|
+
'| Field | Value |',
|
|
176
|
+
'|---|---|',
|
|
177
|
+
`| ADO Test Case | ${tcLink} |`,
|
|
178
|
+
`| Build | ${buildLink} |`,
|
|
179
|
+
`| Run | ${runLink} |`,
|
|
180
|
+
'',
|
|
181
|
+
];
|
|
182
|
+
if (result.errorMessage) {
|
|
183
|
+
lines.push('### Error', '```', result.errorMessage.trim(), '```', '');
|
|
184
|
+
}
|
|
185
|
+
if (result.stackTrace) {
|
|
186
|
+
lines.push('### Stack trace', '```', result.stackTrace.trim(), '```', '');
|
|
187
|
+
}
|
|
188
|
+
lines.push('---', '_Filed automatically by [ado-sync](https://github.com/PavanMudigonda/ado-sync)_');
|
|
189
|
+
return lines.join('\n');
|
|
190
|
+
}
|
|
191
|
+
function buildClusterBody(batch, runInfo) {
|
|
192
|
+
const runLink = runInfo.runUrl ? `[View run](${runInfo.runUrl})` : '—';
|
|
193
|
+
const sample = batch[0];
|
|
194
|
+
const names = batch.slice(0, 20).map((r) => `- ${r.testName}`).join('\n');
|
|
195
|
+
const overflow = batch.length > 20 ? `\n_… and ${batch.length - 20} more_` : '';
|
|
196
|
+
const lines = [
|
|
197
|
+
`## Error cluster: ${errorSignature(sample.errorMessage)}`,
|
|
198
|
+
'',
|
|
199
|
+
`**${batch.length} tests failed with the same error.** Run: ${runLink}`,
|
|
200
|
+
'',
|
|
201
|
+
'### Affected tests',
|
|
202
|
+
names + overflow,
|
|
203
|
+
'',
|
|
204
|
+
];
|
|
205
|
+
if (sample.errorMessage) {
|
|
206
|
+
lines.push('### Error', '```', sample.errorMessage.trim(), '```', '');
|
|
207
|
+
}
|
|
208
|
+
if (sample.stackTrace) {
|
|
209
|
+
lines.push('### Stack trace (first failure)', '```', sample.stackTrace.trim(), '```', '');
|
|
210
|
+
}
|
|
211
|
+
lines.push('---', '_Filed automatically by [ado-sync](https://github.com/PavanMudigonda/ado-sync)_');
|
|
212
|
+
return lines.join('\n');
|
|
213
|
+
}
|
|
214
|
+
function buildEnvFailureBody(failed, runInfo) {
|
|
215
|
+
const runLink = runInfo.runUrl ? `[View run](${runInfo.runUrl})` : '—';
|
|
216
|
+
const sample = failed[0];
|
|
217
|
+
const names = failed.slice(0, 10).map((r) => `- ${r.testName}`).join('\n');
|
|
218
|
+
const overflow = failed.length > 10 ? `\n_… and ${failed.length - 10} more_` : '';
|
|
219
|
+
const lines = [
|
|
220
|
+
`## Environment failure: ${failed.length} tests failed`,
|
|
221
|
+
'',
|
|
222
|
+
`More than the configured threshold of tests failed in a single run. This likely indicates an **infrastructure or environment issue** rather than individual test failures.`,
|
|
223
|
+
'',
|
|
224
|
+
`**Run:** ${runLink}`,
|
|
225
|
+
'',
|
|
226
|
+
'### Sample failures',
|
|
227
|
+
names + overflow,
|
|
228
|
+
'',
|
|
229
|
+
];
|
|
230
|
+
if (sample?.errorMessage) {
|
|
231
|
+
lines.push('### Sample error', '```', sample.errorMessage.trim(), '```', '');
|
|
232
|
+
}
|
|
233
|
+
lines.push('---', '_Filed automatically by [ado-sync](https://github.com/PavanMudigonda/ado-sync)_');
|
|
234
|
+
return lines.join('\n');
|
|
235
|
+
}
|
|
236
|
+
//# sourceMappingURL=create-issues.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create-issues.js","sourceRoot":"","sources":["../../src/issues/create-issues.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GitHub Issues API client — creates and searches issues using Node's built-in
|
|
3
|
+
* https module (no extra dependencies required).
|
|
4
|
+
*/
|
|
5
|
+
export interface GitHubIssueOptions {
|
|
6
|
+
repo: string;
|
|
7
|
+
token: string;
|
|
8
|
+
title: string;
|
|
9
|
+
body: string;
|
|
10
|
+
labels?: string[];
|
|
11
|
+
assignees?: string[];
|
|
12
|
+
}
|
|
13
|
+
export interface GitHubIssue {
|
|
14
|
+
number: number;
|
|
15
|
+
html_url: string;
|
|
16
|
+
}
|
|
17
|
+
export declare function createGitHubIssue(opts: GitHubIssueOptions): Promise<GitHubIssue>;
|
|
18
|
+
/**
|
|
19
|
+
* Returns the first open issue matching the given label, or null if none exists.
|
|
20
|
+
* Used for dedup: each per-test issue is labelled "tc:12345" so we can find it again.
|
|
21
|
+
*/
|
|
22
|
+
export declare function findOpenGitHubIssueByLabel(repo: string, token: string, tcLabel: string): Promise<GitHubIssue | null>;
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* GitHub Issues API client — creates and searches issues using Node's built-in
|
|
4
|
+
* https module (no extra dependencies required).
|
|
5
|
+
*/
|
|
6
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
7
|
+
if (k2 === undefined) k2 = k;
|
|
8
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
9
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
10
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
11
|
+
}
|
|
12
|
+
Object.defineProperty(o, k2, desc);
|
|
13
|
+
}) : (function(o, m, k, k2) {
|
|
14
|
+
if (k2 === undefined) k2 = k;
|
|
15
|
+
o[k2] = m[k];
|
|
16
|
+
}));
|
|
17
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
18
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
19
|
+
}) : function(o, v) {
|
|
20
|
+
o["default"] = v;
|
|
21
|
+
});
|
|
22
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
23
|
+
var ownKeys = function(o) {
|
|
24
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
25
|
+
var ar = [];
|
|
26
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
27
|
+
return ar;
|
|
28
|
+
};
|
|
29
|
+
return ownKeys(o);
|
|
30
|
+
};
|
|
31
|
+
return function (mod) {
|
|
32
|
+
if (mod && mod.__esModule) return mod;
|
|
33
|
+
var result = {};
|
|
34
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
35
|
+
__setModuleDefault(result, mod);
|
|
36
|
+
return result;
|
|
37
|
+
};
|
|
38
|
+
})();
|
|
39
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
40
|
+
exports.createGitHubIssue = createGitHubIssue;
|
|
41
|
+
exports.findOpenGitHubIssueByLabel = findOpenGitHubIssueByLabel;
|
|
42
|
+
const https = __importStar(require("https"));
|
|
43
|
+
async function createGitHubIssue(opts) {
|
|
44
|
+
const payload = JSON.stringify({
|
|
45
|
+
title: opts.title,
|
|
46
|
+
body: opts.body,
|
|
47
|
+
labels: opts.labels ?? [],
|
|
48
|
+
assignees: opts.assignees ?? [],
|
|
49
|
+
});
|
|
50
|
+
return ghRequest('POST', `/repos/${opts.repo}/issues`, opts.token, payload);
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Returns the first open issue matching the given label, or null if none exists.
|
|
54
|
+
* Used for dedup: each per-test issue is labelled "tc:12345" so we can find it again.
|
|
55
|
+
*/
|
|
56
|
+
async function findOpenGitHubIssueByLabel(repo, token, tcLabel) {
|
|
57
|
+
const q = encodeURIComponent(`repo:${repo} label:"${tcLabel}" state:open`);
|
|
58
|
+
const result = await ghRequest('GET', `/search/issues?q=${q}&per_page=1`, token, null);
|
|
59
|
+
return result.items?.[0] ?? null;
|
|
60
|
+
}
|
|
61
|
+
function ghRequest(method, apiPath, token, body) {
|
|
62
|
+
return new Promise((resolve, reject) => {
|
|
63
|
+
const headers = {
|
|
64
|
+
'Authorization': `Bearer ${token}`,
|
|
65
|
+
'Accept': 'application/vnd.github+json',
|
|
66
|
+
'X-GitHub-Api-Version': '2022-11-28',
|
|
67
|
+
'User-Agent': 'ado-sync',
|
|
68
|
+
'Content-Type': 'application/json',
|
|
69
|
+
};
|
|
70
|
+
if (body)
|
|
71
|
+
headers['Content-Length'] = Buffer.byteLength(body);
|
|
72
|
+
const req = https.request({ hostname: 'api.github.com', path: apiPath, method, headers }, (res) => {
|
|
73
|
+
const chunks = [];
|
|
74
|
+
res.on('data', (c) => chunks.push(c));
|
|
75
|
+
res.on('end', () => {
|
|
76
|
+
const text = Buffer.concat(chunks).toString();
|
|
77
|
+
if (res.statusCode && res.statusCode >= 400) {
|
|
78
|
+
reject(new Error(`GitHub API ${res.statusCode} ${method} ${apiPath}: ${text}`));
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
try {
|
|
82
|
+
resolve(JSON.parse(text));
|
|
83
|
+
}
|
|
84
|
+
catch {
|
|
85
|
+
reject(new Error(`GitHub API non-JSON response: ${text.slice(0, 200)}`));
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
});
|
|
89
|
+
req.on('error', reject);
|
|
90
|
+
if (body)
|
|
91
|
+
req.write(body);
|
|
92
|
+
req.end();
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
//# sourceMappingURL=github.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"github.js","sourceRoot":"","sources":["../../src/issues/github.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkBH,8CAQC;AAMD,gEAIC;AAlCD,6CAA+B;AAgBxB,KAAK,UAAU,iBAAiB,CAAC,IAAwB;IAC9D,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC;QAC7B,KAAK,EAAE,IAAI,CAAC,KAAK;QACjB,IAAI,EAAG,IAAI,CAAC,IAAI;QAChB,MAAM,EAAK,IAAI,CAAC,MAAM,IAAO,EAAE;QAC/B,SAAS,EAAE,IAAI,CAAC,SAAS,IAAI,EAAE;KAChC,CAAC,CAAC;IACH,OAAO,SAAS,CAAc,MAAM,EAAE,UAAU,IAAI,CAAC,IAAI,SAAS,EAAE,IAAI,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;AAC3F,CAAC;AAED;;;GAGG;AACI,KAAK,UAAU,0BAA0B,CAAC,IAAY,EAAE,KAAa,EAAE,OAAe;IAC3F,MAAM,CAAC,GAAG,kBAAkB,CAAC,QAAQ,IAAI,WAAW,OAAO,cAAc,CAAC,CAAC;IAC3E,MAAM,MAAM,GAAG,MAAM,SAAS,CAA2B,KAAK,EAAE,oBAAoB,CAAC,aAAa,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC;IACjH,OAAO,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC;AACnC,CAAC;AAED,SAAS,SAAS,CAAU,MAAc,EAAE,OAAe,EAAE,KAAa,EAAE,IAAmB;IAC7F,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,MAAM,OAAO,GAAoC;YAC/C,eAAe,EAAG,UAAU,KAAK,EAAE;YACnC,QAAQ,EAAU,6BAA6B;YAC/C,sBAAsB,EAAE,YAAY;YACpC,YAAY,EAAM,UAAU;YAC5B,cAAc,EAAI,kBAAkB;SACrC,CAAC;QACF,IAAI,IAAI;YAAE,OAAO,CAAC,gBAAgB,CAAC,GAAG,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;QAE9D,MAAM,GAAG,GAAG,KAAK,CAAC,OAAO,CAAC,EAAE,QAAQ,EAAE,gBAAgB,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,CAAC,GAAG,EAAE,EAAE;YAChG,MAAM,MAAM,GAAa,EAAE,CAAC;YAC5B,GAAG,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,CAAS,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;YAC9C,GAAG,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE;gBACjB,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,QAAQ,EAAE,CAAC;gBAC9C,IAAI,GAAG,CAAC,UAAU,IAAI,GAAG,CAAC,UAAU,IAAI,GAAG,EAAE,CAAC;oBAC5C,MAAM,CAAC,IAAI,KAAK,CAAC,cAAc,GAAG,CAAC,UAAU,IAAI,MAAM,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC,CAAC,CAAC;oBAChF,OAAO;gBACT,CAAC;gBACD,IAAI,CAAC;oBAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;gBAAC,CAAC;gBAClC,MAAM,CAAC;oBAAC,MAAM,CAAC,IAAI,KAAK,CAAC,iCAAiC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;gBAAC,CAAC;YACrF,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QACH,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QACxB,IAAI,IAAI;YAAE,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC1B,GAAG,CAAC,GAAG,EAAE,CAAC;IACZ,CAAC,CAAC,CAAC;AACL,CAAC"}
|
package/dist/mcp-server.d.ts
CHANGED
|
@@ -17,6 +17,9 @@
|
|
|
17
17
|
* generate_specs — generate local spec files from ADO User Stories
|
|
18
18
|
* get_work_items — fetch ADO User Stories by ID, WIQL query, or area path
|
|
19
19
|
* publish_test_results — publish test results to Azure DevOps
|
|
20
|
+
* create_issue — file a GitHub Issue or ADO Bug for a test failure
|
|
21
|
+
* get_story_context — planner-agent feed: AC items, suggested tags, linked TCs
|
|
22
|
+
* generate_manifest — write .ai-workflow-manifest-{id}.json for a story
|
|
20
23
|
*
|
|
21
24
|
* Usage (register in .claude/settings.json or .vscode/mcp.json):
|
|
22
25
|
*
|