ai-sdlc 0.3.1-alpha.0-alpha.6 → 0.3.1-alpha.0-alpha.8
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 +54 -0
- package/dist/cli/commands/import-issue.d.ts +7 -0
- package/dist/cli/commands/import-issue.d.ts.map +1 -0
- package/dist/cli/commands/import-issue.js +125 -0
- package/dist/cli/commands/import-issue.js.map +1 -0
- package/dist/cli/commands/link-issue.d.ts +11 -0
- package/dist/cli/commands/link-issue.d.ts.map +1 -0
- package/dist/cli/commands/link-issue.js +156 -0
- package/dist/cli/commands/link-issue.js.map +1 -0
- package/dist/cli/commands.d.ts +3 -0
- package/dist/cli/commands.d.ts.map +1 -1
- package/dist/cli/commands.js +4 -0
- package/dist/cli/commands.js.map +1 -1
- package/dist/core/config.d.ts +5 -1
- package/dist/core/config.d.ts.map +1 -1
- package/dist/core/config.js +73 -0
- package/dist/core/config.js.map +1 -1
- package/dist/index.js +11 -1
- package/dist/index.js.map +1 -1
- package/dist/services/gh-cli.d.ts +122 -0
- package/dist/services/gh-cli.d.ts.map +1 -0
- package/dist/services/gh-cli.js +249 -0
- package/dist/services/gh-cli.js.map +1 -0
- package/dist/services/ticket-provider/github-provider.d.ts +84 -0
- package/dist/services/ticket-provider/github-provider.d.ts.map +1 -0
- package/dist/services/ticket-provider/github-provider.js +194 -0
- package/dist/services/ticket-provider/github-provider.js.map +1 -0
- package/dist/services/ticket-provider/index.d.ts +22 -0
- package/dist/services/ticket-provider/index.d.ts.map +1 -0
- package/dist/services/ticket-provider/index.js +38 -0
- package/dist/services/ticket-provider/index.js.map +1 -0
- package/dist/services/ticket-provider/null-provider.d.ts +59 -0
- package/dist/services/ticket-provider/null-provider.d.ts.map +1 -0
- package/dist/services/ticket-provider/null-provider.js +73 -0
- package/dist/services/ticket-provider/null-provider.js.map +1 -0
- package/dist/services/ticket-provider/types.d.ts +115 -0
- package/dist/services/ticket-provider/types.d.ts.map +1 -0
- package/dist/services/ticket-provider/types.js +2 -0
- package/dist/services/ticket-provider/types.js.map +1 -0
- package/dist/types/index.d.ts +27 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
import { spawnSync } from 'child_process';
|
|
2
|
+
/**
|
|
3
|
+
* Custom error for when gh CLI is not installed.
|
|
4
|
+
*/
|
|
5
|
+
export class GhNotInstalledError extends Error {
|
|
6
|
+
constructor() {
|
|
7
|
+
super('GitHub CLI (gh) is not installed.\nInstall it from: https://cli.github.com/');
|
|
8
|
+
this.name = 'GhNotInstalledError';
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Custom error for when gh CLI is not authenticated.
|
|
13
|
+
*/
|
|
14
|
+
export class GhNotAuthenticatedError extends Error {
|
|
15
|
+
constructor() {
|
|
16
|
+
super('Not authenticated to GitHub.\nRun: gh auth login');
|
|
17
|
+
this.name = 'GhNotAuthenticatedError';
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Custom error for when a GitHub Issue is not found.
|
|
22
|
+
*/
|
|
23
|
+
export class GhIssueNotFoundError extends Error {
|
|
24
|
+
constructor(owner, repo, number) {
|
|
25
|
+
super(`Issue #${number} not found in ${owner}/${repo}`);
|
|
26
|
+
this.name = 'GhIssueNotFoundError';
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Custom error for when access to a repository is denied.
|
|
31
|
+
*/
|
|
32
|
+
export class GhNoAccessError extends Error {
|
|
33
|
+
constructor(owner, repo) {
|
|
34
|
+
super(`Cannot access ${owner}/${repo}. Check your permissions.`);
|
|
35
|
+
this.name = 'GhNoAccessError';
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Parse a GitHub issue URL into its components.
|
|
40
|
+
*
|
|
41
|
+
* Supports various formats:
|
|
42
|
+
* - https://github.com/owner/repo/issues/123
|
|
43
|
+
* - https://github.com/owner/repo/issues/123#issuecomment-456
|
|
44
|
+
* - github.com/owner/repo/issues/123
|
|
45
|
+
* - owner/repo#123
|
|
46
|
+
*
|
|
47
|
+
* @param url GitHub issue URL in various formats
|
|
48
|
+
* @returns Parsed components or null if invalid
|
|
49
|
+
*/
|
|
50
|
+
export function parseGitHubIssueUrl(url) {
|
|
51
|
+
// Remove protocol and www
|
|
52
|
+
const normalized = url
|
|
53
|
+
.replace(/^https?:\/\//i, '')
|
|
54
|
+
.replace(/^www\./i, '');
|
|
55
|
+
// Match: github.com/owner/repo/issues/123
|
|
56
|
+
const fullMatch = normalized.match(/^github\.com\/([^\/]+)\/([^\/]+)\/issues\/(\d+)/i);
|
|
57
|
+
if (fullMatch) {
|
|
58
|
+
return {
|
|
59
|
+
owner: fullMatch[1],
|
|
60
|
+
repo: fullMatch[2],
|
|
61
|
+
number: parseInt(fullMatch[3], 10),
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
// Match: owner/repo#123
|
|
65
|
+
const shortMatch = url.match(/^([^\/]+)\/([^#]+)#(\d+)$/);
|
|
66
|
+
if (shortMatch) {
|
|
67
|
+
return {
|
|
68
|
+
owner: shortMatch[1],
|
|
69
|
+
repo: shortMatch[2],
|
|
70
|
+
number: parseInt(shortMatch[3], 10),
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
return null;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Check if the gh CLI is installed and authenticated.
|
|
77
|
+
*
|
|
78
|
+
* @returns true if gh is available and authenticated, false otherwise
|
|
79
|
+
*/
|
|
80
|
+
export async function isGhAvailable() {
|
|
81
|
+
// Check if gh is installed
|
|
82
|
+
const versionResult = spawnSync('gh', ['--version'], {
|
|
83
|
+
encoding: 'utf-8',
|
|
84
|
+
shell: false,
|
|
85
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
86
|
+
});
|
|
87
|
+
if (versionResult.status !== 0 || versionResult.error) {
|
|
88
|
+
return false;
|
|
89
|
+
}
|
|
90
|
+
// Check if gh is authenticated
|
|
91
|
+
const authResult = spawnSync('gh', ['auth', 'status'], {
|
|
92
|
+
encoding: 'utf-8',
|
|
93
|
+
shell: false,
|
|
94
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
95
|
+
});
|
|
96
|
+
// gh auth status returns 0 when authenticated
|
|
97
|
+
return authResult.status === 0;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Check if gh CLI is authenticated specifically.
|
|
101
|
+
* Assumes gh is already installed.
|
|
102
|
+
*
|
|
103
|
+
* @returns true if authenticated, false otherwise
|
|
104
|
+
*/
|
|
105
|
+
export async function isGhAuthenticated() {
|
|
106
|
+
const authResult = spawnSync('gh', ['auth', 'status'], {
|
|
107
|
+
encoding: 'utf-8',
|
|
108
|
+
shell: false,
|
|
109
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
110
|
+
});
|
|
111
|
+
return authResult.status === 0;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Fetch a single GitHub Issue by number.
|
|
115
|
+
*
|
|
116
|
+
* @param owner Repository owner
|
|
117
|
+
* @param repo Repository name
|
|
118
|
+
* @param number Issue number
|
|
119
|
+
* @returns GitHub Issue details
|
|
120
|
+
* @throws {GhNotInstalledError} If gh CLI is not installed
|
|
121
|
+
* @throws {GhNotAuthenticatedError} If gh CLI is not authenticated
|
|
122
|
+
* @throws {GhIssueNotFoundError} If issue is not found
|
|
123
|
+
* @throws {GhNoAccessError} If access to repo is denied
|
|
124
|
+
*/
|
|
125
|
+
export async function ghIssueView(owner, repo, number) {
|
|
126
|
+
const result = spawnSync('gh', [
|
|
127
|
+
'issue',
|
|
128
|
+
'view',
|
|
129
|
+
number.toString(),
|
|
130
|
+
'-R',
|
|
131
|
+
`${owner}/${repo}`,
|
|
132
|
+
'--json',
|
|
133
|
+
'number,title,body,state,labels,assignees,projectItems',
|
|
134
|
+
], {
|
|
135
|
+
encoding: 'utf-8',
|
|
136
|
+
shell: false,
|
|
137
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
138
|
+
timeout: 30000, // 30 second timeout
|
|
139
|
+
maxBuffer: 10 * 1024 * 1024, // 10MB for large issue bodies
|
|
140
|
+
});
|
|
141
|
+
// Handle errors
|
|
142
|
+
if (result.error) {
|
|
143
|
+
// @ts-expect-error - error.code is not in the type definition but exists at runtime
|
|
144
|
+
if (result.error.code === 'ENOENT') {
|
|
145
|
+
throw new GhNotInstalledError();
|
|
146
|
+
}
|
|
147
|
+
throw new Error(`Failed to execute gh command: ${result.error.message}`);
|
|
148
|
+
}
|
|
149
|
+
if (result.status !== 0) {
|
|
150
|
+
const stderr = result.stderr || '';
|
|
151
|
+
const stderrLower = stderr.toLowerCase();
|
|
152
|
+
// Check for authentication errors
|
|
153
|
+
if (stderrLower.includes('not logged in') ||
|
|
154
|
+
stderrLower.includes('authentication') ||
|
|
155
|
+
stderrLower.includes('gh auth login')) {
|
|
156
|
+
throw new GhNotAuthenticatedError();
|
|
157
|
+
}
|
|
158
|
+
// Check for not found errors
|
|
159
|
+
if (stderrLower.includes('not found') || stderrLower.includes('could not resolve')) {
|
|
160
|
+
throw new GhIssueNotFoundError(owner, repo, number);
|
|
161
|
+
}
|
|
162
|
+
// Check for permission errors
|
|
163
|
+
if (stderrLower.includes('permission') || stderrLower.includes('403')) {
|
|
164
|
+
throw new GhNoAccessError(owner, repo);
|
|
165
|
+
}
|
|
166
|
+
// Generic error
|
|
167
|
+
throw new Error(`gh issue view failed: ${stderr}`);
|
|
168
|
+
}
|
|
169
|
+
// Parse JSON output
|
|
170
|
+
try {
|
|
171
|
+
return JSON.parse(result.stdout);
|
|
172
|
+
}
|
|
173
|
+
catch (error) {
|
|
174
|
+
throw new Error(`Failed to parse gh CLI output: ${error instanceof Error ? error.message : String(error)}`);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* List GitHub Issues in a repository.
|
|
179
|
+
*
|
|
180
|
+
* @param owner Repository owner
|
|
181
|
+
* @param repo Repository name
|
|
182
|
+
* @param filter Optional filter criteria
|
|
183
|
+
* @returns Array of GitHub Issues
|
|
184
|
+
* @throws {GhNotInstalledError} If gh CLI is not installed
|
|
185
|
+
* @throws {GhNotAuthenticatedError} If gh CLI is not authenticated
|
|
186
|
+
* @throws {GhNoAccessError} If access to repo is denied
|
|
187
|
+
*/
|
|
188
|
+
export async function ghIssueList(owner, repo, filter) {
|
|
189
|
+
const args = [
|
|
190
|
+
'issue',
|
|
191
|
+
'list',
|
|
192
|
+
'-R',
|
|
193
|
+
`${owner}/${repo}`,
|
|
194
|
+
'--json',
|
|
195
|
+
'number,title,body,state,labels,assignees',
|
|
196
|
+
];
|
|
197
|
+
// Add filter options
|
|
198
|
+
if (filter?.state && filter.state !== 'all') {
|
|
199
|
+
args.push('--state', filter.state);
|
|
200
|
+
}
|
|
201
|
+
if (filter?.labels && filter.labels.length > 0) {
|
|
202
|
+
args.push('--label', filter.labels.join(','));
|
|
203
|
+
}
|
|
204
|
+
if (filter?.assignee) {
|
|
205
|
+
args.push('--assignee', filter.assignee);
|
|
206
|
+
}
|
|
207
|
+
if (filter?.limit) {
|
|
208
|
+
args.push('--limit', filter.limit.toString());
|
|
209
|
+
}
|
|
210
|
+
const result = spawnSync('gh', args, {
|
|
211
|
+
encoding: 'utf-8',
|
|
212
|
+
shell: false,
|
|
213
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
214
|
+
timeout: 30000, // 30 second timeout
|
|
215
|
+
maxBuffer: 10 * 1024 * 1024, // 10MB for large responses
|
|
216
|
+
});
|
|
217
|
+
// Handle errors
|
|
218
|
+
if (result.error) {
|
|
219
|
+
// @ts-expect-error - error.code is not in the type definition but exists at runtime
|
|
220
|
+
if (result.error.code === 'ENOENT') {
|
|
221
|
+
throw new GhNotInstalledError();
|
|
222
|
+
}
|
|
223
|
+
throw new Error(`Failed to execute gh command: ${result.error.message}`);
|
|
224
|
+
}
|
|
225
|
+
if (result.status !== 0) {
|
|
226
|
+
const stderr = result.stderr || '';
|
|
227
|
+
const stderrLower = stderr.toLowerCase();
|
|
228
|
+
// Check for authentication errors
|
|
229
|
+
if (stderrLower.includes('not logged in') ||
|
|
230
|
+
stderrLower.includes('authentication') ||
|
|
231
|
+
stderrLower.includes('gh auth login')) {
|
|
232
|
+
throw new GhNotAuthenticatedError();
|
|
233
|
+
}
|
|
234
|
+
// Check for permission errors
|
|
235
|
+
if (stderrLower.includes('permission') || stderrLower.includes('403')) {
|
|
236
|
+
throw new GhNoAccessError(owner, repo);
|
|
237
|
+
}
|
|
238
|
+
// Generic error
|
|
239
|
+
throw new Error(`gh issue list failed: ${stderr}`);
|
|
240
|
+
}
|
|
241
|
+
// Parse JSON output
|
|
242
|
+
try {
|
|
243
|
+
return JSON.parse(result.stdout);
|
|
244
|
+
}
|
|
245
|
+
catch (error) {
|
|
246
|
+
throw new Error(`Failed to parse gh CLI output: ${error instanceof Error ? error.message : String(error)}`);
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
//# sourceMappingURL=gh-cli.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gh-cli.js","sourceRoot":"","sources":["../../src/services/gh-cli.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { StoryStatus } from '../../types/index.js';
|
|
2
|
+
import { Ticket, TicketFilter, NewTicket, TicketProvider } from './types.js';
|
|
3
|
+
/**
|
|
4
|
+
* GitHub-specific configuration for the ticket provider.
|
|
5
|
+
*/
|
|
6
|
+
export interface GitHubConfig {
|
|
7
|
+
/** Repository in format 'owner/repo' */
|
|
8
|
+
repo?: string;
|
|
9
|
+
/** GitHub Projects v2 project number for priority sync */
|
|
10
|
+
projectNumber?: number;
|
|
11
|
+
/** Map story statuses to GitHub labels */
|
|
12
|
+
statusLabels?: Record<string, string>;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Ticket provider implementation for GitHub Issues.
|
|
16
|
+
*
|
|
17
|
+
* Integrates with GitHub Issues via the gh CLI. Supports:
|
|
18
|
+
* - Listing issues with filters
|
|
19
|
+
* - Fetching individual issues
|
|
20
|
+
* - Status mapping between GitHub and ai-sdlc
|
|
21
|
+
*
|
|
22
|
+
* Write operations (create, updateStatus, addComment, linkPR) will be
|
|
23
|
+
* implemented in story S-0075.
|
|
24
|
+
*/
|
|
25
|
+
export declare class GitHubTicketProvider implements TicketProvider {
|
|
26
|
+
private config?;
|
|
27
|
+
readonly name = "github";
|
|
28
|
+
constructor(config?: GitHubConfig | undefined);
|
|
29
|
+
/**
|
|
30
|
+
* Get owner and repo from config.
|
|
31
|
+
* @throws Error if repo is not configured
|
|
32
|
+
*/
|
|
33
|
+
private getOwnerRepo;
|
|
34
|
+
/**
|
|
35
|
+
* Map GitHub Issue to Ticket.
|
|
36
|
+
*/
|
|
37
|
+
private mapIssueToTicket;
|
|
38
|
+
/**
|
|
39
|
+
* List tickets matching the given filter criteria.
|
|
40
|
+
*/
|
|
41
|
+
list(filter?: TicketFilter): Promise<Ticket[]>;
|
|
42
|
+
/**
|
|
43
|
+
* Get a single ticket by its ID.
|
|
44
|
+
*/
|
|
45
|
+
get(id: string): Promise<Ticket>;
|
|
46
|
+
/**
|
|
47
|
+
* Create a new ticket.
|
|
48
|
+
* @throws Error - Not yet implemented (S-0075)
|
|
49
|
+
*/
|
|
50
|
+
create(_ticket: NewTicket): Promise<Ticket>;
|
|
51
|
+
/**
|
|
52
|
+
* Update the status of a ticket.
|
|
53
|
+
* No-op: Write operations will be implemented in S-0075.
|
|
54
|
+
*/
|
|
55
|
+
updateStatus(_id: string, _status: string): Promise<void>;
|
|
56
|
+
/**
|
|
57
|
+
* Add a comment to a ticket.
|
|
58
|
+
* No-op: Write operations will be implemented in S-0075.
|
|
59
|
+
*/
|
|
60
|
+
addComment(_id: string, _body: string): Promise<void>;
|
|
61
|
+
/**
|
|
62
|
+
* Link a pull request to a ticket.
|
|
63
|
+
* No-op: Write operations will be implemented in S-0075.
|
|
64
|
+
*/
|
|
65
|
+
linkPR(_id: string, _prUrl: string): Promise<void>;
|
|
66
|
+
/**
|
|
67
|
+
* Map internal story status to external GitHub status.
|
|
68
|
+
*
|
|
69
|
+
* Uses label-based mapping if configured, otherwise uses state:
|
|
70
|
+
* - backlog, ready, in_progress, blocked → 'open'
|
|
71
|
+
* - done → 'closed'
|
|
72
|
+
*/
|
|
73
|
+
mapStatusToExternal(status: StoryStatus): string;
|
|
74
|
+
/**
|
|
75
|
+
* Map external GitHub status to internal story status.
|
|
76
|
+
*
|
|
77
|
+
* If status labels are configured, tries to match label to status.
|
|
78
|
+
* Otherwise uses issue state:
|
|
79
|
+
* - open → ready
|
|
80
|
+
* - closed → done
|
|
81
|
+
*/
|
|
82
|
+
mapStatusFromExternal(externalStatus: string): StoryStatus;
|
|
83
|
+
}
|
|
84
|
+
//# sourceMappingURL=github-provider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"github-provider.d.ts","sourceRoot":"","sources":["../../../src/services/ticket-provider/github-provider.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACnD,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAQ7E;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,wCAAwC;IACxC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,0DAA0D;IAC1D,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,0CAA0C;IAC1C,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACvC;AAED;;;;;;;;;;GAUG;AACH,qBAAa,oBAAqB,YAAW,cAAc;IAG7C,OAAO,CAAC,MAAM,CAAC;IAF3B,QAAQ,CAAC,IAAI,YAAY;gBAEL,MAAM,CAAC,EAAE,YAAY,YAAA;IAEzC;;;OAGG;IACH,OAAO,CAAC,YAAY;IAapB;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAsCxB;;OAEG;IACG,IAAI,CAAC,MAAM,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAsCpD;;OAEG;IACG,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAYtC;;;OAGG;IACG,MAAM,CAAC,OAAO,EAAE,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC;IAIjD;;;OAGG;IACG,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAI/D;;;OAGG;IACG,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAI3D;;;OAGG;IACG,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIxD;;;;;;OAMG;IACH,mBAAmB,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM;IAmBhD;;;;;;;OAOG;IACH,qBAAqB,CAAC,cAAc,EAAE,MAAM,GAAG,WAAW;CAoB3D"}
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
import { ghIssueView, ghIssueList, } from '../gh-cli.js';
|
|
2
|
+
/**
|
|
3
|
+
* Ticket provider implementation for GitHub Issues.
|
|
4
|
+
*
|
|
5
|
+
* Integrates with GitHub Issues via the gh CLI. Supports:
|
|
6
|
+
* - Listing issues with filters
|
|
7
|
+
* - Fetching individual issues
|
|
8
|
+
* - Status mapping between GitHub and ai-sdlc
|
|
9
|
+
*
|
|
10
|
+
* Write operations (create, updateStatus, addComment, linkPR) will be
|
|
11
|
+
* implemented in story S-0075.
|
|
12
|
+
*/
|
|
13
|
+
export class GitHubTicketProvider {
|
|
14
|
+
config;
|
|
15
|
+
name = 'github';
|
|
16
|
+
constructor(config) {
|
|
17
|
+
this.config = config;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Get owner and repo from config.
|
|
21
|
+
* @throws Error if repo is not configured
|
|
22
|
+
*/
|
|
23
|
+
getOwnerRepo() {
|
|
24
|
+
if (!this.config?.repo) {
|
|
25
|
+
throw new Error('GitHub repository not configured. Set ticketing.github.repo in config.');
|
|
26
|
+
}
|
|
27
|
+
const [owner, repo] = this.config.repo.split('/');
|
|
28
|
+
if (!owner || !repo) {
|
|
29
|
+
throw new Error(`Invalid GitHub repository format: "${this.config.repo}". Expected "owner/repo".`);
|
|
30
|
+
}
|
|
31
|
+
return { owner, repo };
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Map GitHub Issue to Ticket.
|
|
35
|
+
*/
|
|
36
|
+
mapIssueToTicket(issue) {
|
|
37
|
+
const { owner, repo } = this.getOwnerRepo();
|
|
38
|
+
const url = `https://github.com/${owner}/${repo}/issues/${issue.number}`;
|
|
39
|
+
const labels = issue.labels.map((l) => l.name);
|
|
40
|
+
const assignee = issue.assignees[0]?.login;
|
|
41
|
+
// Extract priority from project if available
|
|
42
|
+
let priority = 3; // Default priority
|
|
43
|
+
if (issue.projectItems && issue.projectItems.length > 0) {
|
|
44
|
+
for (const item of issue.projectItems) {
|
|
45
|
+
// Look for priority field in project
|
|
46
|
+
if (item.fieldValueByName) {
|
|
47
|
+
const priorityField = item.fieldValueByName.find((f) => f.field.name.toLowerCase() === 'priority');
|
|
48
|
+
if (priorityField) {
|
|
49
|
+
// Try to parse priority as number
|
|
50
|
+
const priorityValue = parseInt(priorityField.name, 10);
|
|
51
|
+
if (!isNaN(priorityValue)) {
|
|
52
|
+
priority = priorityValue;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
return {
|
|
59
|
+
id: issue.number.toString(),
|
|
60
|
+
url,
|
|
61
|
+
title: issue.title,
|
|
62
|
+
description: issue.body || '',
|
|
63
|
+
status: issue.state,
|
|
64
|
+
priority,
|
|
65
|
+
labels,
|
|
66
|
+
assignee,
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* List tickets matching the given filter criteria.
|
|
71
|
+
*/
|
|
72
|
+
async list(filter) {
|
|
73
|
+
const { owner, repo } = this.getOwnerRepo();
|
|
74
|
+
// Convert TicketFilter to IssueFilter
|
|
75
|
+
const issueFilter = {};
|
|
76
|
+
if (filter?.status && filter.status.length > 0) {
|
|
77
|
+
// Map internal statuses to GitHub state
|
|
78
|
+
const hasOpen = filter.status.some((s) => ['backlog', 'ready', 'in-progress', 'blocked'].includes(s));
|
|
79
|
+
const hasClosed = filter.status.includes('done');
|
|
80
|
+
if (hasOpen && hasClosed) {
|
|
81
|
+
issueFilter.state = 'all';
|
|
82
|
+
}
|
|
83
|
+
else if (hasOpen) {
|
|
84
|
+
issueFilter.state = 'open';
|
|
85
|
+
}
|
|
86
|
+
else if (hasClosed) {
|
|
87
|
+
issueFilter.state = 'closed';
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
if (filter?.labels) {
|
|
91
|
+
issueFilter.labels = filter.labels;
|
|
92
|
+
}
|
|
93
|
+
if (filter?.assignee) {
|
|
94
|
+
issueFilter.assignee = filter.assignee;
|
|
95
|
+
}
|
|
96
|
+
if (filter?.limit) {
|
|
97
|
+
issueFilter.limit = filter.limit;
|
|
98
|
+
}
|
|
99
|
+
const issues = await ghIssueList(owner, repo, issueFilter);
|
|
100
|
+
return issues.map((issue) => this.mapIssueToTicket(issue));
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Get a single ticket by its ID.
|
|
104
|
+
*/
|
|
105
|
+
async get(id) {
|
|
106
|
+
const { owner, repo } = this.getOwnerRepo();
|
|
107
|
+
const issueNumber = parseInt(id, 10);
|
|
108
|
+
if (isNaN(issueNumber)) {
|
|
109
|
+
throw new Error(`Invalid GitHub issue number: "${id}"`);
|
|
110
|
+
}
|
|
111
|
+
const issue = await ghIssueView(owner, repo, issueNumber);
|
|
112
|
+
return this.mapIssueToTicket(issue);
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Create a new ticket.
|
|
116
|
+
* @throws Error - Not yet implemented (S-0075)
|
|
117
|
+
*/
|
|
118
|
+
async create(_ticket) {
|
|
119
|
+
throw new Error('GitHub ticket creation not yet implemented (S-0075)');
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Update the status of a ticket.
|
|
123
|
+
* No-op: Write operations will be implemented in S-0075.
|
|
124
|
+
*/
|
|
125
|
+
async updateStatus(_id, _status) {
|
|
126
|
+
// No-op: Write operations not yet implemented
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Add a comment to a ticket.
|
|
130
|
+
* No-op: Write operations will be implemented in S-0075.
|
|
131
|
+
*/
|
|
132
|
+
async addComment(_id, _body) {
|
|
133
|
+
// No-op: Write operations not yet implemented
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Link a pull request to a ticket.
|
|
137
|
+
* No-op: Write operations will be implemented in S-0075.
|
|
138
|
+
*/
|
|
139
|
+
async linkPR(_id, _prUrl) {
|
|
140
|
+
// No-op: Write operations not yet implemented
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Map internal story status to external GitHub status.
|
|
144
|
+
*
|
|
145
|
+
* Uses label-based mapping if configured, otherwise uses state:
|
|
146
|
+
* - backlog, ready, in_progress, blocked → 'open'
|
|
147
|
+
* - done → 'closed'
|
|
148
|
+
*/
|
|
149
|
+
mapStatusToExternal(status) {
|
|
150
|
+
// Check for custom label mapping
|
|
151
|
+
if (this.config?.statusLabels && this.config.statusLabels[status]) {
|
|
152
|
+
return this.config.statusLabels[status];
|
|
153
|
+
}
|
|
154
|
+
// Default mapping to GitHub issue state
|
|
155
|
+
switch (status) {
|
|
156
|
+
case 'done':
|
|
157
|
+
return 'closed';
|
|
158
|
+
case 'backlog':
|
|
159
|
+
case 'ready':
|
|
160
|
+
case 'in-progress':
|
|
161
|
+
case 'blocked':
|
|
162
|
+
default:
|
|
163
|
+
return 'open';
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Map external GitHub status to internal story status.
|
|
168
|
+
*
|
|
169
|
+
* If status labels are configured, tries to match label to status.
|
|
170
|
+
* Otherwise uses issue state:
|
|
171
|
+
* - open → ready
|
|
172
|
+
* - closed → done
|
|
173
|
+
*/
|
|
174
|
+
mapStatusFromExternal(externalStatus) {
|
|
175
|
+
// Check for custom label mapping (reverse lookup)
|
|
176
|
+
if (this.config?.statusLabels) {
|
|
177
|
+
for (const [status, label] of Object.entries(this.config.statusLabels)) {
|
|
178
|
+
if (label === externalStatus) {
|
|
179
|
+
return status;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
// Default mapping from GitHub issue state
|
|
184
|
+
const statusLower = externalStatus.toLowerCase();
|
|
185
|
+
switch (statusLower) {
|
|
186
|
+
case 'closed':
|
|
187
|
+
return 'done';
|
|
188
|
+
case 'open':
|
|
189
|
+
default:
|
|
190
|
+
return 'ready';
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
//# sourceMappingURL=github-provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"github-provider.js","sourceRoot":"","sources":["../../../src/services/ticket-provider/github-provider.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { Config } from '../../types/index.js';
|
|
2
|
+
import { TicketProvider } from './types.js';
|
|
3
|
+
export * from './types.js';
|
|
4
|
+
export { NullTicketProvider } from './null-provider.js';
|
|
5
|
+
export { GitHubTicketProvider } from './github-provider.js';
|
|
6
|
+
/**
|
|
7
|
+
* Create a ticket provider based on configuration.
|
|
8
|
+
*
|
|
9
|
+
* Factory function that instantiates the appropriate TicketProvider
|
|
10
|
+
* implementation based on the `ticketing.provider` configuration value.
|
|
11
|
+
*
|
|
12
|
+
* Defaults to NullTicketProvider when:
|
|
13
|
+
* - No ticketing configuration exists
|
|
14
|
+
* - ticketing.provider is 'none'
|
|
15
|
+
* - ticketing.provider is an unknown value
|
|
16
|
+
*
|
|
17
|
+
* @param config Application configuration
|
|
18
|
+
* @returns Configured ticket provider instance
|
|
19
|
+
* @throws Error if requesting an unimplemented provider (github, jira)
|
|
20
|
+
*/
|
|
21
|
+
export declare function createTicketProvider(config: Config): TicketProvider;
|
|
22
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/services/ticket-provider/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAG9C,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAG5C,cAAc,YAAY,CAAC;AAC3B,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAE5D;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,MAAM,GAAG,cAAc,CAmBnE"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { NullTicketProvider } from './null-provider.js';
|
|
2
|
+
import { GitHubTicketProvider } from './github-provider.js';
|
|
3
|
+
// Re-export types
|
|
4
|
+
export * from './types.js';
|
|
5
|
+
export { NullTicketProvider } from './null-provider.js';
|
|
6
|
+
export { GitHubTicketProvider } from './github-provider.js';
|
|
7
|
+
/**
|
|
8
|
+
* Create a ticket provider based on configuration.
|
|
9
|
+
*
|
|
10
|
+
* Factory function that instantiates the appropriate TicketProvider
|
|
11
|
+
* implementation based on the `ticketing.provider` configuration value.
|
|
12
|
+
*
|
|
13
|
+
* Defaults to NullTicketProvider when:
|
|
14
|
+
* - No ticketing configuration exists
|
|
15
|
+
* - ticketing.provider is 'none'
|
|
16
|
+
* - ticketing.provider is an unknown value
|
|
17
|
+
*
|
|
18
|
+
* @param config Application configuration
|
|
19
|
+
* @returns Configured ticket provider instance
|
|
20
|
+
* @throws Error if requesting an unimplemented provider (github, jira)
|
|
21
|
+
*/
|
|
22
|
+
export function createTicketProvider(config) {
|
|
23
|
+
const provider = config.ticketing?.provider ?? 'none';
|
|
24
|
+
switch (provider) {
|
|
25
|
+
case 'none':
|
|
26
|
+
return new NullTicketProvider();
|
|
27
|
+
case 'github':
|
|
28
|
+
return new GitHubTicketProvider(config.ticketing?.github);
|
|
29
|
+
case 'jira':
|
|
30
|
+
// Placeholder for future Jira provider implementation
|
|
31
|
+
throw new Error('Jira provider not yet implemented');
|
|
32
|
+
default:
|
|
33
|
+
// Unknown provider - fall back to safe default
|
|
34
|
+
console.warn(`Unknown ticket provider "${provider}", falling back to 'none'`);
|
|
35
|
+
return new NullTicketProvider();
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/services/ticket-provider/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAG5D,kBAAkB;AAClB,cAAc,YAAY,CAAC;AAC3B,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAE5D;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,oBAAoB,CAAC,MAAc;IACjD,MAAM,QAAQ,GAAG,MAAM,CAAC,SAAS,EAAE,QAAQ,IAAI,MAAM,CAAC;IAEtD,QAAQ,QAAQ,EAAE,CAAC;QACjB,KAAK,MAAM;YACT,OAAO,IAAI,kBAAkB,EAAE,CAAC;QAElC,KAAK,QAAQ;YACX,OAAO,IAAI,oBAAoB,CAAC,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;QAE5D,KAAK,MAAM;YACT,sDAAsD;YACtD,MAAM,IAAI,KAAK,CAAC,mCAAmC,CAAC,CAAC;QAEvD;YACE,+CAA+C;YAC/C,OAAO,CAAC,IAAI,CAAC,4BAA4B,QAAQ,2BAA2B,CAAC,CAAC;YAC9E,OAAO,IAAI,kBAAkB,EAAE,CAAC;IACpC,CAAC;AACH,CAAC"}
|