chief-clancy 0.6.0 → 0.7.1
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 +3 -2
- package/dist/bundle/clancy-afk.js +6 -2
- package/dist/bundle/clancy-once.js +49 -48
- package/dist/installer/hook-installer/hook-installer.d.ts +2 -0
- package/dist/installer/hook-installer/hook-installer.d.ts.map +1 -1
- package/dist/installer/hook-installer/hook-installer.js +36 -1
- package/dist/installer/hook-installer/hook-installer.js.map +1 -1
- package/dist/installer/install.js +8 -0
- package/dist/installer/install.js.map +1 -1
- package/hooks/clancy-branch-guard.js +129 -0
- package/hooks/clancy-context-monitor.js +134 -46
- package/hooks/clancy-post-compact.js +53 -0
- package/hooks/package.json +3 -0
- package/package.json +7 -3
- package/src/agents/verification-gate.md +128 -0
- package/src/roles/setup/workflows/init.md +45 -0
- package/src/roles/setup/workflows/scaffold.md +30 -0
- package/src/roles/setup/workflows/settings.md +56 -0
- package/src/templates/.env.example.github +19 -1
- package/src/templates/.env.example.jira +25 -1
- package/src/templates/.env.example.linear +19 -1
- package/dist/schemas/bitbucket-pr.d.ts +0 -137
- package/dist/schemas/bitbucket-pr.d.ts.map +0 -1
- package/dist/schemas/bitbucket-pr.js +0 -75
- package/dist/schemas/bitbucket-pr.js.map +0 -1
- package/dist/schemas/env.d.ts +0 -150
- package/dist/schemas/env.d.ts.map +0 -1
- package/dist/schemas/env.js +0 -63
- package/dist/schemas/env.js.map +0 -1
- package/dist/schemas/github-issues.d.ts +0 -105
- package/dist/schemas/github-issues.d.ts.map +0 -1
- package/dist/schemas/github-issues.js +0 -54
- package/dist/schemas/github-issues.js.map +0 -1
- package/dist/schemas/gitlab-mr.d.ts +0 -73
- package/dist/schemas/gitlab-mr.d.ts.map +0 -1
- package/dist/schemas/gitlab-mr.js +0 -33
- package/dist/schemas/gitlab-mr.js.map +0 -1
- package/dist/schemas/jira.d.ts +0 -59
- package/dist/schemas/jira.d.ts.map +0 -1
- package/dist/schemas/jira.js +0 -56
- package/dist/schemas/jira.js.map +0 -1
- package/dist/schemas/linear.d.ts +0 -108
- package/dist/schemas/linear.d.ts.map +0 -1
- package/dist/schemas/linear.js +0 -84
- package/dist/schemas/linear.js.map +0 -1
- package/dist/scripts/afk/afk.d.ts +0 -21
- package/dist/scripts/afk/afk.d.ts.map +0 -1
- package/dist/scripts/afk/afk.js +0 -118
- package/dist/scripts/afk/afk.js.map +0 -1
- package/dist/scripts/board/github/github.d.ts +0 -104
- package/dist/scripts/board/github/github.d.ts.map +0 -1
- package/dist/scripts/board/github/github.js +0 -291
- package/dist/scripts/board/github/github.js.map +0 -1
- package/dist/scripts/board/jira/jira.d.ts +0 -139
- package/dist/scripts/board/jira/jira.d.ts.map +0 -1
- package/dist/scripts/board/jira/jira.js +0 -378
- package/dist/scripts/board/jira/jira.js.map +0 -1
- package/dist/scripts/board/linear/linear.d.ts +0 -129
- package/dist/scripts/board/linear/linear.d.ts.map +0 -1
- package/dist/scripts/board/linear/linear.js +0 -393
- package/dist/scripts/board/linear/linear.js.map +0 -1
- package/dist/scripts/once/board-ops/board-ops.d.ts +0 -26
- package/dist/scripts/once/board-ops/board-ops.d.ts.map +0 -1
- package/dist/scripts/once/board-ops/board-ops.js +0 -113
- package/dist/scripts/once/board-ops/board-ops.js.map +0 -1
- package/dist/scripts/once/deliver/deliver.d.ts +0 -37
- package/dist/scripts/once/deliver/deliver.d.ts.map +0 -1
- package/dist/scripts/once/deliver/deliver.js +0 -236
- package/dist/scripts/once/deliver/deliver.js.map +0 -1
- package/dist/scripts/once/fetch-ticket/fetch-ticket.d.ts +0 -22
- package/dist/scripts/once/fetch-ticket/fetch-ticket.d.ts.map +0 -1
- package/dist/scripts/once/fetch-ticket/fetch-ticket.js +0 -123
- package/dist/scripts/once/fetch-ticket/fetch-ticket.js.map +0 -1
- package/dist/scripts/once/git-token/git-token.d.ts +0 -13
- package/dist/scripts/once/git-token/git-token.d.ts.map +0 -1
- package/dist/scripts/once/git-token/git-token.js +0 -30
- package/dist/scripts/once/git-token/git-token.js.map +0 -1
- package/dist/scripts/once/once.d.ts +0 -12
- package/dist/scripts/once/once.d.ts.map +0 -1
- package/dist/scripts/once/once.js +0 -356
- package/dist/scripts/once/once.js.map +0 -1
- package/dist/scripts/once/pr-creation/pr-creation.d.ts +0 -11
- package/dist/scripts/once/pr-creation/pr-creation.d.ts.map +0 -1
- package/dist/scripts/once/pr-creation/pr-creation.js +0 -50
- package/dist/scripts/once/pr-creation/pr-creation.js.map +0 -1
- package/dist/scripts/once/rework/rework.d.ts +0 -32
- package/dist/scripts/once/rework/rework.d.ts.map +0 -1
- package/dist/scripts/once/rework/rework.js +0 -208
- package/dist/scripts/once/rework/rework.js.map +0 -1
- package/dist/scripts/once/types/types.d.ts +0 -13
- package/dist/scripts/once/types/types.d.ts.map +0 -1
- package/dist/scripts/once/types/types.js +0 -2
- package/dist/scripts/once/types/types.js.map +0 -1
- package/dist/scripts/shared/branch/branch.d.ts +0 -50
- package/dist/scripts/shared/branch/branch.d.ts.map +0 -1
- package/dist/scripts/shared/branch/branch.js +0 -61
- package/dist/scripts/shared/branch/branch.js.map +0 -1
- package/dist/scripts/shared/claude-cli/claude-cli.d.ts +0 -31
- package/dist/scripts/shared/claude-cli/claude-cli.d.ts.map +0 -1
- package/dist/scripts/shared/claude-cli/claude-cli.js +0 -60
- package/dist/scripts/shared/claude-cli/claude-cli.js.map +0 -1
- package/dist/scripts/shared/env-schema/env-schema.d.ts +0 -27
- package/dist/scripts/shared/env-schema/env-schema.d.ts.map +0 -1
- package/dist/scripts/shared/env-schema/env-schema.js +0 -47
- package/dist/scripts/shared/env-schema/env-schema.js.map +0 -1
- package/dist/scripts/shared/feasibility/feasibility.d.ts +0 -30
- package/dist/scripts/shared/feasibility/feasibility.d.ts.map +0 -1
- package/dist/scripts/shared/feasibility/feasibility.js +0 -68
- package/dist/scripts/shared/feasibility/feasibility.js.map +0 -1
- package/dist/scripts/shared/format/format.d.ts +0 -11
- package/dist/scripts/shared/format/format.d.ts.map +0 -1
- package/dist/scripts/shared/format/format.js +0 -18
- package/dist/scripts/shared/format/format.js.map +0 -1
- package/dist/scripts/shared/git-ops/git-ops.d.ts +0 -90
- package/dist/scripts/shared/git-ops/git-ops.d.ts.map +0 -1
- package/dist/scripts/shared/git-ops/git-ops.js +0 -190
- package/dist/scripts/shared/git-ops/git-ops.js.map +0 -1
- package/dist/scripts/shared/http/http.d.ts +0 -54
- package/dist/scripts/shared/http/http.d.ts.map +0 -1
- package/dist/scripts/shared/http/http.js +0 -76
- package/dist/scripts/shared/http/http.js.map +0 -1
- package/dist/scripts/shared/notify/notify.d.ts +0 -46
- package/dist/scripts/shared/notify/notify.d.ts.map +0 -1
- package/dist/scripts/shared/notify/notify.js +0 -88
- package/dist/scripts/shared/notify/notify.js.map +0 -1
- package/dist/scripts/shared/preflight/preflight.d.ts +0 -40
- package/dist/scripts/shared/preflight/preflight.d.ts.map +0 -1
- package/dist/scripts/shared/preflight/preflight.js +0 -96
- package/dist/scripts/shared/preflight/preflight.js.map +0 -1
- package/dist/scripts/shared/progress/progress.d.ts +0 -75
- package/dist/scripts/shared/progress/progress.d.ts.map +0 -1
- package/dist/scripts/shared/progress/progress.js +0 -210
- package/dist/scripts/shared/progress/progress.js.map +0 -1
- package/dist/scripts/shared/prompt/prompt.d.ts +0 -58
- package/dist/scripts/shared/prompt/prompt.d.ts.map +0 -1
- package/dist/scripts/shared/prompt/prompt.js +0 -123
- package/dist/scripts/shared/prompt/prompt.js.map +0 -1
- package/dist/scripts/shared/pull-request/bitbucket/bitbucket.d.ts +0 -82
- package/dist/scripts/shared/pull-request/bitbucket/bitbucket.d.ts.map +0 -1
- package/dist/scripts/shared/pull-request/bitbucket/bitbucket.js +0 -301
- package/dist/scripts/shared/pull-request/bitbucket/bitbucket.js.map +0 -1
- package/dist/scripts/shared/pull-request/github/github.d.ts +0 -72
- package/dist/scripts/shared/pull-request/github/github.d.ts.map +0 -1
- package/dist/scripts/shared/pull-request/github/github.js +0 -226
- package/dist/scripts/shared/pull-request/github/github.js.map +0 -1
- package/dist/scripts/shared/pull-request/gitlab/gitlab.d.ts +0 -74
- package/dist/scripts/shared/pull-request/gitlab/gitlab.d.ts.map +0 -1
- package/dist/scripts/shared/pull-request/gitlab/gitlab.js +0 -220
- package/dist/scripts/shared/pull-request/gitlab/gitlab.js.map +0 -1
- package/dist/scripts/shared/pull-request/post-pr/post-pr.d.ts +0 -31
- package/dist/scripts/shared/pull-request/post-pr/post-pr.d.ts.map +0 -1
- package/dist/scripts/shared/pull-request/post-pr/post-pr.js +0 -61
- package/dist/scripts/shared/pull-request/post-pr/post-pr.js.map +0 -1
- package/dist/scripts/shared/pull-request/pr-body/pr-body.d.ts +0 -40
- package/dist/scripts/shared/pull-request/pr-body/pr-body.d.ts.map +0 -1
- package/dist/scripts/shared/pull-request/pr-body/pr-body.js +0 -84
- package/dist/scripts/shared/pull-request/pr-body/pr-body.js.map +0 -1
- package/dist/scripts/shared/pull-request/rework-comment/rework-comment.d.ts +0 -23
- package/dist/scripts/shared/pull-request/rework-comment/rework-comment.d.ts.map +0 -1
- package/dist/scripts/shared/pull-request/rework-comment/rework-comment.js +0 -30
- package/dist/scripts/shared/pull-request/rework-comment/rework-comment.js.map +0 -1
- package/dist/scripts/shared/remote/remote.d.ts +0 -41
- package/dist/scripts/shared/remote/remote.d.ts.map +0 -1
- package/dist/scripts/shared/remote/remote.js +0 -227
- package/dist/scripts/shared/remote/remote.js.map +0 -1
- package/dist/types/board.d.ts +0 -13
- package/dist/types/board.d.ts.map +0 -1
- package/dist/types/board.js +0 -5
- package/dist/types/board.js.map +0 -1
- package/dist/types/index.d.ts +0 -4
- package/dist/types/index.d.ts.map +0 -1
- package/dist/types/index.js +0 -2
- package/dist/types/index.js.map +0 -1
- package/dist/types/remote.d.ts +0 -55
- package/dist/types/remote.d.ts.map +0 -1
- package/dist/types/remote.js +0 -5
- package/dist/types/remote.js.map +0 -1
- package/dist/utils/parse-json/parse-json.d.ts +0 -20
- package/dist/utils/parse-json/parse-json.d.ts.map +0 -1
- package/dist/utils/parse-json/parse-json.js +0 -27
- package/dist/utils/parse-json/parse-json.js.map +0 -1
|
@@ -1,378 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Clancy Jira board script.
|
|
3
|
-
*
|
|
4
|
-
* Fetches a ticket from Jira Cloud, creates branches, invokes Claude,
|
|
5
|
-
* pushes feature branches, creates PRs, and transitions status.
|
|
6
|
-
*
|
|
7
|
-
* Uses the new POST `/rest/api/3/search/jql` endpoint (old GET `/search`
|
|
8
|
-
* was removed by Atlassian in August 2025).
|
|
9
|
-
*/
|
|
10
|
-
import { jiraIssueLinksResponseSchema, jiraSearchResponseSchema, jiraTransitionsResponseSchema, } from '../../../schemas/jira.js';
|
|
11
|
-
import { jiraHeaders, pingEndpoint } from '../../../scripts/shared/http/http.js';
|
|
12
|
-
const SAFE_VALUE_PATTERN = /^[a-zA-Z0-9 _\-'.]+$/;
|
|
13
|
-
const ISSUE_KEY_PATTERN = /^[A-Z][A-Z0-9]+-\d+$/;
|
|
14
|
-
/**
|
|
15
|
-
* Build Jira Basic auth header value.
|
|
16
|
-
*
|
|
17
|
-
* @param user - The Jira username (email).
|
|
18
|
-
* @param token - The Jira API token.
|
|
19
|
-
* @returns The Base64-encoded `user:token` string for Basic auth.
|
|
20
|
-
*/
|
|
21
|
-
export function buildAuthHeader(user, token) {
|
|
22
|
-
return Buffer.from(`${user}:${token}`).toString('base64');
|
|
23
|
-
}
|
|
24
|
-
/**
|
|
25
|
-
* Validate that a user-controlled value is safe for JQL injection.
|
|
26
|
-
*
|
|
27
|
-
* @param value - The value to validate.
|
|
28
|
-
* @returns `true` if the value matches the safe pattern.
|
|
29
|
-
*/
|
|
30
|
-
export function isSafeJqlValue(value) {
|
|
31
|
-
return SAFE_VALUE_PATTERN.test(value);
|
|
32
|
-
}
|
|
33
|
-
/**
|
|
34
|
-
* Ping the Jira API to verify connectivity and credentials.
|
|
35
|
-
*
|
|
36
|
-
* @param baseUrl - The Jira Cloud base URL.
|
|
37
|
-
* @param projectKey - The Jira project key.
|
|
38
|
-
* @param auth - The Base64-encoded Basic auth string.
|
|
39
|
-
* @returns An object with `ok` and optional `error` message.
|
|
40
|
-
*
|
|
41
|
-
* @example
|
|
42
|
-
* ```ts
|
|
43
|
-
* const result = await pingJira('https://example.atlassian.net', 'PROJ', authHeader);
|
|
44
|
-
* if (!result.ok) console.error(result.error);
|
|
45
|
-
* ```
|
|
46
|
-
*/
|
|
47
|
-
export async function pingJira(baseUrl, projectKey, auth) {
|
|
48
|
-
return pingEndpoint(`${baseUrl}/rest/api/3/project/${projectKey}`, jiraHeaders(auth), {
|
|
49
|
-
401: '✗ Jira auth failed — check credentials',
|
|
50
|
-
403: '✗ Jira permission denied for this project',
|
|
51
|
-
404: `✗ Jira project "${projectKey}" not found`,
|
|
52
|
-
}, '✗ Could not reach Jira — check network');
|
|
53
|
-
}
|
|
54
|
-
/**
|
|
55
|
-
* Build the JQL query for fetching the next ticket.
|
|
56
|
-
*
|
|
57
|
-
* @param projectKey - The Jira project key.
|
|
58
|
-
* @param status - The JQL status to filter by (default: `"To Do"`).
|
|
59
|
-
* @param sprint - If set, adds an open sprint filter.
|
|
60
|
-
* @param label - If set, adds a label filter.
|
|
61
|
-
* @returns The JQL query string.
|
|
62
|
-
*/
|
|
63
|
-
export function buildJql(projectKey, status, sprint, label, excludeHitl) {
|
|
64
|
-
const parts = [`project="${projectKey}"`];
|
|
65
|
-
if (sprint)
|
|
66
|
-
parts.push('sprint in openSprints()');
|
|
67
|
-
if (label)
|
|
68
|
-
parts.push(`labels = "${label}"`);
|
|
69
|
-
if (excludeHitl)
|
|
70
|
-
parts.push('labels != "clancy:hitl"');
|
|
71
|
-
parts.push(`assignee=currentUser()`);
|
|
72
|
-
parts.push(`status="${status}"`);
|
|
73
|
-
return parts.join(' AND ') + ' ORDER BY priority ASC';
|
|
74
|
-
}
|
|
75
|
-
/**
|
|
76
|
-
* Extract all text strings from a Jira ADF (Atlassian Document Format) description.
|
|
77
|
-
*
|
|
78
|
-
* Recursively walks the ADF tree and collects all string values.
|
|
79
|
-
*
|
|
80
|
-
* @param adf - The ADF description object (or `undefined`).
|
|
81
|
-
* @returns A single string with all text content joined by spaces.
|
|
82
|
-
*/
|
|
83
|
-
export function extractAdfText(adf) {
|
|
84
|
-
if (!adf || typeof adf !== 'object')
|
|
85
|
-
return '';
|
|
86
|
-
const strings = [];
|
|
87
|
-
function walk(node) {
|
|
88
|
-
if (typeof node === 'string') {
|
|
89
|
-
strings.push(node);
|
|
90
|
-
return;
|
|
91
|
-
}
|
|
92
|
-
if (Array.isArray(node)) {
|
|
93
|
-
for (const item of node)
|
|
94
|
-
walk(item);
|
|
95
|
-
return;
|
|
96
|
-
}
|
|
97
|
-
if (node && typeof node === 'object') {
|
|
98
|
-
for (const value of Object.values(node)) {
|
|
99
|
-
walk(value);
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
walk(adf);
|
|
104
|
-
return strings.join(' ');
|
|
105
|
-
}
|
|
106
|
-
/**
|
|
107
|
-
* Fetch the next available ticket from Jira.
|
|
108
|
-
*
|
|
109
|
-
* @param baseUrl - The Jira Cloud base URL.
|
|
110
|
-
* @param auth - The Base64-encoded Basic auth string.
|
|
111
|
-
* @param projectKey - The Jira project key.
|
|
112
|
-
* @param status - The JQL status to filter by.
|
|
113
|
-
* @param sprint - Optional sprint filter.
|
|
114
|
-
* @param label - Optional label filter.
|
|
115
|
-
* @returns The fetched ticket, or `undefined` if no tickets are available.
|
|
116
|
-
*/
|
|
117
|
-
export async function fetchTicket(baseUrl, auth, projectKey, status, sprint, label) {
|
|
118
|
-
const results = await fetchTickets(baseUrl, auth, projectKey, status, sprint, label, false, 1);
|
|
119
|
-
return results[0];
|
|
120
|
-
}
|
|
121
|
-
/**
|
|
122
|
-
* Fetch multiple candidate tickets from Jira.
|
|
123
|
-
*
|
|
124
|
-
* @param baseUrl - The Jira Cloud base URL.
|
|
125
|
-
* @param auth - The Base64-encoded Basic auth string.
|
|
126
|
-
* @param projectKey - The Jira project key.
|
|
127
|
-
* @param status - The JQL status to filter by.
|
|
128
|
-
* @param sprint - Optional sprint filter.
|
|
129
|
-
* @param label - Optional label filter.
|
|
130
|
-
* @param excludeHitl - If `true`, excludes tickets with the `clancy:hitl` label.
|
|
131
|
-
* @param limit - Maximum number of results to return (default: 5).
|
|
132
|
-
* @returns Array of fetched tickets (may be empty).
|
|
133
|
-
*/
|
|
134
|
-
export async function fetchTickets(baseUrl, auth, projectKey, status, sprint, label, excludeHitl, limit = 5) {
|
|
135
|
-
const jql = buildJql(projectKey, status, sprint, label, excludeHitl);
|
|
136
|
-
let response;
|
|
137
|
-
try {
|
|
138
|
-
response = await fetch(`${baseUrl}/rest/api/3/search/jql`, {
|
|
139
|
-
method: 'POST',
|
|
140
|
-
headers: {
|
|
141
|
-
...jiraHeaders(auth),
|
|
142
|
-
'Content-Type': 'application/json',
|
|
143
|
-
},
|
|
144
|
-
body: JSON.stringify({
|
|
145
|
-
jql,
|
|
146
|
-
maxResults: limit,
|
|
147
|
-
fields: [
|
|
148
|
-
'summary',
|
|
149
|
-
'description',
|
|
150
|
-
'issuelinks',
|
|
151
|
-
'parent',
|
|
152
|
-
'customfield_10014',
|
|
153
|
-
],
|
|
154
|
-
}),
|
|
155
|
-
});
|
|
156
|
-
}
|
|
157
|
-
catch (err) {
|
|
158
|
-
console.warn(`⚠ Jira API request failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
159
|
-
return [];
|
|
160
|
-
}
|
|
161
|
-
if (!response.ok) {
|
|
162
|
-
console.warn(`⚠ Jira API returned HTTP ${response.status}`);
|
|
163
|
-
return [];
|
|
164
|
-
}
|
|
165
|
-
let json;
|
|
166
|
-
try {
|
|
167
|
-
json = await response.json();
|
|
168
|
-
}
|
|
169
|
-
catch {
|
|
170
|
-
console.warn('⚠ Jira API returned invalid JSON');
|
|
171
|
-
return [];
|
|
172
|
-
}
|
|
173
|
-
const parsed = jiraSearchResponseSchema.safeParse(json);
|
|
174
|
-
if (!parsed.success) {
|
|
175
|
-
console.warn(`⚠ Unexpected Jira response shape: ${parsed.error.message}`);
|
|
176
|
-
return [];
|
|
177
|
-
}
|
|
178
|
-
return parsed.data.issues.map((issue) => {
|
|
179
|
-
const fields = issue.fields;
|
|
180
|
-
// Extract blockers
|
|
181
|
-
const blockers = (fields.issuelinks ?? [])
|
|
182
|
-
.filter((link) => link.type?.name === 'Blocks' && link.inwardIssue?.key)
|
|
183
|
-
.map((link) => link.inwardIssue?.key)
|
|
184
|
-
.filter((key) => Boolean(key));
|
|
185
|
-
// Extract epic (next-gen parent OR classic customfield)
|
|
186
|
-
const epicKey = fields.parent?.key ?? fields.customfield_10014 ?? undefined;
|
|
187
|
-
return {
|
|
188
|
-
key: issue.key,
|
|
189
|
-
title: fields.summary,
|
|
190
|
-
description: extractAdfText(fields.description),
|
|
191
|
-
provider: 'jira',
|
|
192
|
-
epicKey,
|
|
193
|
-
blockers,
|
|
194
|
-
};
|
|
195
|
-
});
|
|
196
|
-
}
|
|
197
|
-
/**
|
|
198
|
-
* Check whether a Jira issue is blocked by unresolved blockers.
|
|
199
|
-
*
|
|
200
|
-
* Fetches the issue's links and checks for inward "Blocks" relationships
|
|
201
|
-
* where the blocking issue's statusCategory is not "done".
|
|
202
|
-
*
|
|
203
|
-
* @param baseUrl - The Jira Cloud base URL.
|
|
204
|
-
* @param auth - The Base64-encoded Basic auth string.
|
|
205
|
-
* @param key - The Jira issue key (e.g., `'PROJ-123'`).
|
|
206
|
-
* @returns `true` if any blocker is unresolved, `false` otherwise.
|
|
207
|
-
*/
|
|
208
|
-
export async function fetchBlockerStatus(baseUrl, auth, key) {
|
|
209
|
-
if (!ISSUE_KEY_PATTERN.test(key))
|
|
210
|
-
return false;
|
|
211
|
-
try {
|
|
212
|
-
const response = await fetch(`${baseUrl}/rest/api/3/issue/${key}?fields=issuelinks`, { headers: jiraHeaders(auth) });
|
|
213
|
-
if (!response.ok)
|
|
214
|
-
return false;
|
|
215
|
-
const json = await response.json();
|
|
216
|
-
const parsed = jiraIssueLinksResponseSchema.safeParse(json);
|
|
217
|
-
if (!parsed.success)
|
|
218
|
-
return false;
|
|
219
|
-
const links = parsed.data.fields?.issuelinks ?? [];
|
|
220
|
-
// Check for inward "Blocks" links with unresolved status
|
|
221
|
-
return links.some((link) => {
|
|
222
|
-
if (link.type?.name !== 'Blocks')
|
|
223
|
-
return false;
|
|
224
|
-
if (!link.inwardIssue?.key)
|
|
225
|
-
return false;
|
|
226
|
-
const categoryKey = link.inwardIssue.fields?.status?.statusCategory?.key;
|
|
227
|
-
// If status info is missing, assume not blocked
|
|
228
|
-
if (!categoryKey)
|
|
229
|
-
return false;
|
|
230
|
-
return categoryKey !== 'done';
|
|
231
|
-
});
|
|
232
|
-
}
|
|
233
|
-
catch {
|
|
234
|
-
return false;
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
/**
|
|
238
|
-
* Fetch the children status of a Jira epic (dual-mode).
|
|
239
|
-
*
|
|
240
|
-
* Tries the `Epic: {key}` text convention first (children with "Epic: PROJ-100"
|
|
241
|
-
* in their description). If no results, falls back to the native `parent = {key}`
|
|
242
|
-
* JQL query for backward compatibility with pre-v0.6.0 children.
|
|
243
|
-
*
|
|
244
|
-
* @param baseUrl - The Jira Cloud base URL.
|
|
245
|
-
* @param auth - The Base64-encoded Basic auth string.
|
|
246
|
-
* @param parentKey - The parent issue key (e.g., `'PROJ-100'`).
|
|
247
|
-
* @returns The children status, or `undefined` on failure.
|
|
248
|
-
*/
|
|
249
|
-
export async function fetchChildrenStatus(baseUrl, auth, parentKey) {
|
|
250
|
-
if (!ISSUE_KEY_PATTERN.test(parentKey))
|
|
251
|
-
return undefined;
|
|
252
|
-
try {
|
|
253
|
-
// Mode 1: Try Epic: text convention (scoped to project to avoid cross-project matches)
|
|
254
|
-
const projectPrefix = parentKey.split('-')[0];
|
|
255
|
-
const epicTextResult = await fetchChildrenByJql(baseUrl, auth, `project = "${projectPrefix}" AND description ~ "Epic: ${parentKey}"`);
|
|
256
|
-
if (epicTextResult && epicTextResult.total > 0)
|
|
257
|
-
return epicTextResult;
|
|
258
|
-
// Mode 2: Fall back to native parent API
|
|
259
|
-
return await fetchChildrenByJql(baseUrl, auth, `parent = ${parentKey}`);
|
|
260
|
-
}
|
|
261
|
-
catch {
|
|
262
|
-
return undefined;
|
|
263
|
-
}
|
|
264
|
-
}
|
|
265
|
-
/**
|
|
266
|
-
* Fetch children status using a JQL query (total and incomplete counts).
|
|
267
|
-
*
|
|
268
|
-
* @param baseUrl - The Jira Cloud base URL.
|
|
269
|
-
* @param auth - The Base64-encoded Basic auth string.
|
|
270
|
-
* @param jql - The JQL query to find children.
|
|
271
|
-
* @returns The children status, or `undefined` on failure.
|
|
272
|
-
*/
|
|
273
|
-
async function fetchChildrenByJql(baseUrl, auth, jql) {
|
|
274
|
-
// Fetch total count
|
|
275
|
-
const totalResponse = await fetch(`${baseUrl}/rest/api/3/search/jql`, {
|
|
276
|
-
method: 'POST',
|
|
277
|
-
headers: {
|
|
278
|
-
...jiraHeaders(auth),
|
|
279
|
-
'Content-Type': 'application/json',
|
|
280
|
-
},
|
|
281
|
-
body: JSON.stringify({ jql, maxResults: 0 }),
|
|
282
|
-
});
|
|
283
|
-
if (!totalResponse.ok)
|
|
284
|
-
return undefined;
|
|
285
|
-
const totalJson = (await totalResponse.json());
|
|
286
|
-
const total = totalJson.total ?? 0;
|
|
287
|
-
if (total === 0)
|
|
288
|
-
return { total: 0, incomplete: 0 };
|
|
289
|
-
// Fetch incomplete count
|
|
290
|
-
const incompleteResponse = await fetch(`${baseUrl}/rest/api/3/search/jql`, {
|
|
291
|
-
method: 'POST',
|
|
292
|
-
headers: {
|
|
293
|
-
...jiraHeaders(auth),
|
|
294
|
-
'Content-Type': 'application/json',
|
|
295
|
-
},
|
|
296
|
-
body: JSON.stringify({
|
|
297
|
-
jql: `${jql} AND statusCategory != "done"`,
|
|
298
|
-
maxResults: 0,
|
|
299
|
-
}),
|
|
300
|
-
});
|
|
301
|
-
if (!incompleteResponse.ok)
|
|
302
|
-
return undefined;
|
|
303
|
-
const incompleteJson = (await incompleteResponse.json());
|
|
304
|
-
const incomplete = incompleteJson.total ?? 0;
|
|
305
|
-
return { total, incomplete };
|
|
306
|
-
}
|
|
307
|
-
/**
|
|
308
|
-
* Look up a Jira transition ID by status name.
|
|
309
|
-
*
|
|
310
|
-
* @param baseUrl - The Jira Cloud base URL.
|
|
311
|
-
* @param auth - The Base64-encoded Basic auth string.
|
|
312
|
-
* @param issueKey - The Jira issue key (e.g., `'PROJ-123'`).
|
|
313
|
-
* @param statusName - The target status name (e.g., `'In Progress'`).
|
|
314
|
-
* @returns The transition ID, or `undefined` if not found.
|
|
315
|
-
*/
|
|
316
|
-
export async function lookupTransitionId(baseUrl, auth, issueKey, statusName) {
|
|
317
|
-
if (!ISSUE_KEY_PATTERN.test(issueKey))
|
|
318
|
-
return undefined;
|
|
319
|
-
let response;
|
|
320
|
-
try {
|
|
321
|
-
response = await fetch(`${baseUrl}/rest/api/3/issue/${issueKey}/transitions`, { headers: jiraHeaders(auth) });
|
|
322
|
-
}
|
|
323
|
-
catch (err) {
|
|
324
|
-
console.warn(`⚠ Jira transitions request failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
325
|
-
return undefined;
|
|
326
|
-
}
|
|
327
|
-
if (!response.ok)
|
|
328
|
-
return undefined;
|
|
329
|
-
let json;
|
|
330
|
-
try {
|
|
331
|
-
json = await response.json();
|
|
332
|
-
}
|
|
333
|
-
catch {
|
|
334
|
-
console.warn('⚠ Jira transitions returned invalid JSON');
|
|
335
|
-
return undefined;
|
|
336
|
-
}
|
|
337
|
-
const parsed = jiraTransitionsResponseSchema.safeParse(json);
|
|
338
|
-
if (!parsed.success) {
|
|
339
|
-
console.warn(`⚠ Unexpected Jira transitions response: ${parsed.error.message}`);
|
|
340
|
-
return undefined;
|
|
341
|
-
}
|
|
342
|
-
const transition = parsed.data.transitions.find((t) => t.name === statusName);
|
|
343
|
-
return transition?.id;
|
|
344
|
-
}
|
|
345
|
-
/**
|
|
346
|
-
* Transition a Jira issue to a new status.
|
|
347
|
-
*
|
|
348
|
-
* Fetches available transitions and executes the one matching the target status name.
|
|
349
|
-
* Best-effort — never throws on failure.
|
|
350
|
-
*
|
|
351
|
-
* @param baseUrl - The Jira Cloud base URL.
|
|
352
|
-
* @param auth - The Base64-encoded Basic auth string.
|
|
353
|
-
* @param issueKey - The Jira issue key (e.g., `'PROJ-123'`).
|
|
354
|
-
* @param statusName - The target status name (e.g., `'In Progress'`).
|
|
355
|
-
* @returns `true` if the transition succeeded.
|
|
356
|
-
*/
|
|
357
|
-
export async function transitionIssue(baseUrl, auth, issueKey, statusName) {
|
|
358
|
-
try {
|
|
359
|
-
const transitionId = await lookupTransitionId(baseUrl, auth, issueKey, statusName);
|
|
360
|
-
if (!transitionId) {
|
|
361
|
-
console.warn(`⚠ Jira transition "${statusName}" not found for ${issueKey}`);
|
|
362
|
-
return false;
|
|
363
|
-
}
|
|
364
|
-
const response = await fetch(`${baseUrl}/rest/api/3/issue/${issueKey}/transitions`, {
|
|
365
|
-
method: 'POST',
|
|
366
|
-
headers: {
|
|
367
|
-
...jiraHeaders(auth),
|
|
368
|
-
'Content-Type': 'application/json',
|
|
369
|
-
},
|
|
370
|
-
body: JSON.stringify({ transition: { id: transitionId } }),
|
|
371
|
-
});
|
|
372
|
-
return response.ok;
|
|
373
|
-
}
|
|
374
|
-
catch {
|
|
375
|
-
return false;
|
|
376
|
-
}
|
|
377
|
-
}
|
|
378
|
-
//# sourceMappingURL=jira.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"jira.js","sourceRoot":"","sources":["../../../../src/scripts/board/jira/jira.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,129 +0,0 @@
|
|
|
1
|
-
import type { Ticket } from '../../../types/index.js';
|
|
2
|
-
type LinearEnv = {
|
|
3
|
-
LINEAR_API_KEY: string;
|
|
4
|
-
LINEAR_TEAM_ID: string;
|
|
5
|
-
CLANCY_LABEL?: string;
|
|
6
|
-
CLANCY_BASE_BRANCH?: string;
|
|
7
|
-
CLANCY_STATUS_IN_PROGRESS?: string;
|
|
8
|
-
CLANCY_STATUS_DONE?: string;
|
|
9
|
-
CLANCY_MODEL?: string;
|
|
10
|
-
CLANCY_NOTIFY_WEBHOOK?: string;
|
|
11
|
-
};
|
|
12
|
-
/**
|
|
13
|
-
* Validate that a team ID is safe for use in GraphQL variables.
|
|
14
|
-
*
|
|
15
|
-
* @param teamId - The Linear team ID to validate.
|
|
16
|
-
* @returns `true` if the ID matches the safe pattern.
|
|
17
|
-
*/
|
|
18
|
-
export declare function isValidTeamId(teamId: string): boolean;
|
|
19
|
-
/**
|
|
20
|
-
* Make a GraphQL request to the Linear API.
|
|
21
|
-
*
|
|
22
|
-
* Personal API keys are passed directly (no "Bearer" prefix).
|
|
23
|
-
*
|
|
24
|
-
* @param apiKey - The Linear personal API key.
|
|
25
|
-
* @param query - The GraphQL query string.
|
|
26
|
-
* @param variables - The GraphQL variables object.
|
|
27
|
-
* @returns The raw JSON response, or `undefined` on failure.
|
|
28
|
-
*/
|
|
29
|
-
export declare function linearGraphql(apiKey: string, query: string, variables?: Record<string, unknown>): Promise<unknown>;
|
|
30
|
-
/**
|
|
31
|
-
* Ping the Linear API to verify connectivity and credentials.
|
|
32
|
-
*
|
|
33
|
-
* @param apiKey - The Linear personal API key.
|
|
34
|
-
* @returns An object with `ok` and optional `error` message.
|
|
35
|
-
*/
|
|
36
|
-
export declare function pingLinear(apiKey: string): Promise<{
|
|
37
|
-
ok: boolean;
|
|
38
|
-
error?: string;
|
|
39
|
-
}>;
|
|
40
|
-
/**
|
|
41
|
-
* Fetch the next available issue from Linear.
|
|
42
|
-
*
|
|
43
|
-
* Filters by `state.type: "unstarted"` (enum, works regardless of team
|
|
44
|
-
* column naming) and optionally by label.
|
|
45
|
-
*
|
|
46
|
-
* @param env - The Linear environment variables.
|
|
47
|
-
* @returns The fetched ticket with optional parent info, or `undefined` if none available.
|
|
48
|
-
*/
|
|
49
|
-
export declare function fetchIssue(env: LinearEnv): Promise<(Ticket & {
|
|
50
|
-
issueId: string;
|
|
51
|
-
parentIdentifier?: string;
|
|
52
|
-
}) | undefined>;
|
|
53
|
-
/** Linear ticket with issue ID and optional parent info. */
|
|
54
|
-
export type LinearTicket = Ticket & {
|
|
55
|
-
issueId: string;
|
|
56
|
-
parentIdentifier?: string;
|
|
57
|
-
};
|
|
58
|
-
/**
|
|
59
|
-
* Fetch multiple candidate issues from Linear.
|
|
60
|
-
*
|
|
61
|
-
* @param env - The Linear environment variables.
|
|
62
|
-
* @param excludeHitl - If `true`, excludes issues with the `clancy:hitl` label.
|
|
63
|
-
* @param limit - Maximum number of results to return (default: 5).
|
|
64
|
-
* @returns Array of fetched tickets (may be empty).
|
|
65
|
-
*/
|
|
66
|
-
export declare function fetchIssues(env: LinearEnv, excludeHitl?: boolean, limit?: number): Promise<LinearTicket[]>;
|
|
67
|
-
/**
|
|
68
|
-
* Check whether a Linear issue is blocked by unresolved blockers.
|
|
69
|
-
*
|
|
70
|
-
* Queries the issue's relations for `blockedBy` type relationships and checks
|
|
71
|
-
* if any blocking issues have an unresolved state (not "completed" or "canceled").
|
|
72
|
-
*
|
|
73
|
-
* @param apiKey - The Linear personal API key.
|
|
74
|
-
* @param issueId - The Linear issue UUID.
|
|
75
|
-
* @returns `true` if any blocker is unresolved, `false` otherwise.
|
|
76
|
-
*/
|
|
77
|
-
export declare function fetchBlockerStatus(apiKey: string, issueId: string): Promise<boolean>;
|
|
78
|
-
/** Result of checking children status for a parent issue. */
|
|
79
|
-
export type ChildrenStatus = {
|
|
80
|
-
total: number;
|
|
81
|
-
incomplete: number;
|
|
82
|
-
};
|
|
83
|
-
/**
|
|
84
|
-
* Fetch the children status of a Linear parent issue (dual-mode).
|
|
85
|
-
*
|
|
86
|
-
* Tries the `Epic: {identifier}` text convention first (searches for issues
|
|
87
|
-
* with "Epic: {parentIdentifier}" in their description). If no results, falls
|
|
88
|
-
* back to the native `children` API for backward compatibility.
|
|
89
|
-
*
|
|
90
|
-
* @param apiKey - The Linear personal API key.
|
|
91
|
-
* @param parentId - The Linear parent issue UUID.
|
|
92
|
-
* @param parentIdentifier - The Linear parent identifier (e.g., `'ENG-42'`).
|
|
93
|
-
* Required for Epic: text convention search. Falls back to native API only if not provided.
|
|
94
|
-
* @returns The children status, or `undefined` on failure.
|
|
95
|
-
*/
|
|
96
|
-
export declare function fetchChildrenStatus(apiKey: string, parentId: string, parentIdentifier?: string): Promise<ChildrenStatus | undefined>;
|
|
97
|
-
/**
|
|
98
|
-
* Look up a Linear workflow state ID by name and team.
|
|
99
|
-
*
|
|
100
|
-
* @param apiKey - The Linear personal API key.
|
|
101
|
-
* @param teamId - The Linear team ID.
|
|
102
|
-
* @param stateName - The workflow state name (e.g., `'In Progress'`).
|
|
103
|
-
* @returns The state ID, or `undefined` if not found.
|
|
104
|
-
*/
|
|
105
|
-
export declare function lookupWorkflowStateId(apiKey: string, teamId: string, stateName: string): Promise<string | undefined>;
|
|
106
|
-
/**
|
|
107
|
-
* Execute a state transition on a Linear issue.
|
|
108
|
-
*
|
|
109
|
-
* @param apiKey - The Linear personal API key.
|
|
110
|
-
* @param issueId - The Linear issue internal ID.
|
|
111
|
-
* @param stateId - The target workflow state ID.
|
|
112
|
-
* @returns `true` if the mutation succeeded.
|
|
113
|
-
*/
|
|
114
|
-
export declare function executeStateTransition(apiKey: string, issueId: string, stateId: string): Promise<boolean>;
|
|
115
|
-
/**
|
|
116
|
-
* Transition a Linear issue to a new workflow state.
|
|
117
|
-
*
|
|
118
|
-
* Looks up the workflow state ID by name, then executes the `issueUpdate` mutation.
|
|
119
|
-
* Best-effort — never throws on failure.
|
|
120
|
-
*
|
|
121
|
-
* @param apiKey - The Linear personal API key.
|
|
122
|
-
* @param teamId - The Linear team ID.
|
|
123
|
-
* @param issueId - The Linear issue internal ID.
|
|
124
|
-
* @param stateName - The target workflow state name (e.g., `'In Progress'`).
|
|
125
|
-
* @returns `true` if the transition succeeded.
|
|
126
|
-
*/
|
|
127
|
-
export declare function transitionIssue(apiKey: string, teamId: string, issueId: string, stateName: string): Promise<boolean>;
|
|
128
|
-
export {};
|
|
129
|
-
//# sourceMappingURL=linear.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"linear.d.ts","sourceRoot":"","sources":["../../../../src/scripts/board/linear/linear.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAK/C,KAAK,SAAS,GAAG;IACf,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,yBAAyB,CAAC,EAAE,MAAM,CAAC;IACnC,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,qBAAqB,CAAC,EAAE,MAAM,CAAC;CAChC,CAAC;AAEF;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAErD;AAED;;;;;;;;;GASG;AACH,wBAAsB,aAAa,CACjC,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,EACb,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAClC,OAAO,CAAC,OAAO,CAAC,CA8BlB;AAED;;;;;GAKG;AACH,wBAAsB,UAAU,CAC9B,MAAM,EAAE,MAAM,GACb,OAAO,CAAC;IAAE,EAAE,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAsC1C;AAED;;;;;;;;GAQG;AACH,wBAAsB,UAAU,CAAC,GAAG,EAAE,SAAS,GAAG,OAAO,CACrD,CAAC,MAAM,GAAG;IACR,OAAO,EAAE,MAAM,CAAC;IAChB,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B,CAAC,GACF,SAAS,CACZ,CAGA;AAED,4DAA4D;AAC5D,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG;IAClC,OAAO,EAAE,MAAM,CAAC;IAChB,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B,CAAC;AAEF;;;;;;;GAOG;AACH,wBAAsB,WAAW,CAC/B,GAAG,EAAE,SAAS,EACd,WAAW,CAAC,EAAE,OAAO,EACrB,KAAK,SAAI,GACR,OAAO,CAAC,YAAY,EAAE,CAAC,CA8EzB;AAED;;;;;;;;;GASG;AACH,wBAAsB,kBAAkB,CACtC,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,OAAO,CAAC,CA8BlB;AAED,6DAA6D;AAC7D,MAAM,MAAM,cAAc,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAAC;AAEnE;;;;;;;;;;;;GAYG;AACH,wBAAsB,mBAAmB,CACvC,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,gBAAgB,CAAC,EAAE,MAAM,GACxB,OAAO,CAAC,cAAc,GAAG,SAAS,CAAC,CAiBrC;AAuFD;;;;;;;GAOG;AACH,wBAAsB,qBAAqB,CACzC,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAuB7B;AAED;;;;;;;GAOG;AACH,wBAAsB,sBAAsB,CAC1C,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,OAAO,CAAC,CAoBlB;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,eAAe,CACnC,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,OAAO,CAAC,CAelB"}
|