@waron97/prbot 2.0.0 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/settings.local.json +9 -3
- package/.prettierrc.mjs +11 -0
- package/README.md +30 -30
- package/eslint.config.mjs +16 -0
- package/index.js +327 -344
- package/package.json +33 -32
- package/src/commands/autopr.js +238 -259
- package/src/commands/changelog.js +154 -150
- package/src/commands/commit.js +146 -0
- package/src/commands/init.js +137 -134
- package/src/commands/pr.js +101 -106
- package/src/commands/ver.js +54 -64
- package/src/config.js +4 -4
- package/src/index.js +83 -78
- package/src/lib/addons.js +4 -4
- package/src/lib/git.js +6 -6
package/package.json
CHANGED
|
@@ -1,34 +1,35 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
"
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
2
|
+
"name": "@waron97/prbot",
|
|
3
|
+
"version": "2.2.0",
|
|
4
|
+
"description": "",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
8
|
+
},
|
|
9
|
+
"bin": {
|
|
10
|
+
"prbot": "src/index.js"
|
|
11
|
+
},
|
|
12
|
+
"dependencies": {
|
|
13
|
+
"@inquirer/search": "^2.0.1",
|
|
14
|
+
"commander": "^14.0.2",
|
|
15
|
+
"dotenv": "^17.2.3",
|
|
16
|
+
"eslint-plugin-es5": "^1.5.0",
|
|
17
|
+
"inquirer": "^13.4.2",
|
|
18
|
+
"inquirer-search-list": "^1.2.6",
|
|
19
|
+
"node-fetch": "^3.3.2",
|
|
20
|
+
"omelette": "^0.4.17",
|
|
21
|
+
"prettier": "^3.5.3"
|
|
22
|
+
},
|
|
23
|
+
"devDependencies": {
|
|
24
|
+
"@eslint/js": "^9.21.0",
|
|
25
|
+
"@types/node": "^25.0.10",
|
|
26
|
+
"@typescript-eslint/parser": "^8.26.0",
|
|
27
|
+
"eslint": "^9.21.0",
|
|
28
|
+
"typescript": "^5.8.2",
|
|
29
|
+
"typescript-eslint": "^8.26.0"
|
|
30
|
+
},
|
|
31
|
+
"keywords": [],
|
|
32
|
+
"author": "",
|
|
33
|
+
"license": "ISC",
|
|
34
|
+
"type": "module"
|
|
34
35
|
}
|
package/src/commands/autopr.js
CHANGED
|
@@ -1,309 +1,288 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
import inquirer from
|
|
5
|
-
import
|
|
6
|
-
import { resolveAddonsPath } from
|
|
7
|
-
import { execGit } from
|
|
1
|
+
import { readFileSync } from 'fs';
|
|
2
|
+
import fs from 'fs/promises';
|
|
3
|
+
import search from '@inquirer/search';
|
|
4
|
+
import inquirer from 'inquirer';
|
|
5
|
+
import fetch from 'node-fetch';
|
|
6
|
+
import { resolveAddonsPath } from '../lib/addons.js';
|
|
7
|
+
import { execGit } from '../lib/git.js';
|
|
8
8
|
import {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
} from
|
|
9
|
+
appendPrToLine,
|
|
10
|
+
buildRefString,
|
|
11
|
+
detectIndentation,
|
|
12
|
+
extractSections,
|
|
13
|
+
findDuplicateLine,
|
|
14
|
+
findSectionEndLine,
|
|
15
|
+
} from './changelog.js';
|
|
16
16
|
|
|
17
17
|
function devopsHeaders() {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
18
|
+
const token = Buffer.from(`:${process.env.DEVOPS_TOKEN}`).toString('base64');
|
|
19
|
+
return {
|
|
20
|
+
Authorization: `Basic ${token}`,
|
|
21
|
+
'Content-Type': 'application/json',
|
|
22
|
+
};
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
async function fetchTask(taskId) {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
26
|
+
const url = `${process.env.TRIDENT_URL}/jsonrpc`;
|
|
27
|
+
const body = {
|
|
28
|
+
jsonrpc: '2.0',
|
|
29
|
+
method: 'call',
|
|
30
|
+
id: 1,
|
|
31
|
+
params: {
|
|
32
|
+
service: 'object',
|
|
33
|
+
method: 'execute_kw',
|
|
34
|
+
args: [
|
|
35
|
+
process.env.TRIDENT_DB,
|
|
36
|
+
parseInt(process.env.TRIDENT_UID, 10),
|
|
37
|
+
process.env.TRIDENT_TOKEN,
|
|
38
|
+
'project.task',
|
|
39
|
+
'read',
|
|
40
|
+
[[parseInt(taskId, 10)]],
|
|
41
|
+
{
|
|
42
|
+
fields: [
|
|
43
|
+
'name',
|
|
44
|
+
'x_subpackage_id',
|
|
45
|
+
'x_workflow',
|
|
46
|
+
'x_cluster_id',
|
|
47
|
+
'x_release_checklist',
|
|
48
|
+
],
|
|
49
|
+
},
|
|
50
|
+
],
|
|
48
51
|
},
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
throw new Error(`Trident error: ${JSON.stringify(data.error)}`);
|
|
60
|
-
if (!data.result || !data.result[0])
|
|
61
|
-
throw new Error(`Task ${taskId} not found`);
|
|
62
|
-
return data.result[0];
|
|
52
|
+
};
|
|
53
|
+
const res = await fetch(url, {
|
|
54
|
+
method: 'POST',
|
|
55
|
+
headers: { 'Content-Type': 'application/json' },
|
|
56
|
+
body: JSON.stringify(body),
|
|
57
|
+
});
|
|
58
|
+
const data = await res.json();
|
|
59
|
+
if (data.error) throw new Error(`Trident error: ${JSON.stringify(data.error)}`);
|
|
60
|
+
if (!data.result || !data.result[0]) throw new Error(`Task ${taskId} not found`);
|
|
61
|
+
return data.result[0];
|
|
63
62
|
}
|
|
64
63
|
|
|
65
64
|
function buildPrDescription(taskIds, jiras) {
|
|
66
|
-
|
|
67
|
-
(
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
lines.
|
|
71
|
-
}
|
|
72
|
-
return lines.join("\n");
|
|
65
|
+
const lines = taskIds.map((id) => `${process.env.TRIDENT_URL}/odoo/my-tasks/${id}`);
|
|
66
|
+
for (const jira of jiras ?? []) {
|
|
67
|
+
lines.push(`https://sorgenia.atlassian.net/browse/${jira}`);
|
|
68
|
+
}
|
|
69
|
+
return lines.join('\n');
|
|
73
70
|
}
|
|
74
71
|
|
|
75
72
|
async function createDevopsPR(branch, title, description) {
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
})
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
const prUrl = `https://dev.azure.com/${DEVOPS_ORG}/${DEVOPS_PROJECT}/_git/${DEVOPS_REPO}/pullrequest/${data.pullRequestId}`;
|
|
94
|
-
return { id: data.pullRequestId, url: prUrl };
|
|
73
|
+
const { DEVOPS_ORG, DEVOPS_PROJECT, DEVOPS_REPO, AUTOPR_TARGET_BRANCH } = process.env;
|
|
74
|
+
const apiUrl = `https://dev.azure.com/${DEVOPS_ORG}/${DEVOPS_PROJECT}/_apis/git/repositories/${DEVOPS_REPO}/pullrequests?api-version=7.0`;
|
|
75
|
+
const res = await fetch(apiUrl, {
|
|
76
|
+
method: 'POST',
|
|
77
|
+
headers: devopsHeaders(),
|
|
78
|
+
body: JSON.stringify({
|
|
79
|
+
title,
|
|
80
|
+
description,
|
|
81
|
+
isDraft: true,
|
|
82
|
+
sourceRefName: `refs/heads/${branch}`,
|
|
83
|
+
targetRefName: `refs/heads/${AUTOPR_TARGET_BRANCH}`,
|
|
84
|
+
}),
|
|
85
|
+
});
|
|
86
|
+
const data = await res.json();
|
|
87
|
+
if (!res.ok) throw new Error(`DevOps PR creation failed: ${JSON.stringify(data)}`);
|
|
88
|
+
const prUrl = `https://dev.azure.com/${DEVOPS_ORG}/${DEVOPS_PROJECT}/_git/${DEVOPS_REPO}/pullrequest/${data.pullRequestId}`;
|
|
89
|
+
return { id: data.pullRequestId, url: prUrl };
|
|
95
90
|
}
|
|
96
91
|
|
|
97
92
|
async function appendChecklistPrLink(taskId, currentChecklist, prUrl, prNumber) {
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
throw new Error(`Trident write error: ${JSON.stringify(data.error)}`);
|
|
93
|
+
const link = `<a href="${prUrl}">${prUrl}</a><br/>`;
|
|
94
|
+
const updated = currentChecklist ? `${currentChecklist}\n${link}` : link;
|
|
95
|
+
const url = `${process.env.TRIDENT_URL}/jsonrpc`;
|
|
96
|
+
const res = await fetch(url, {
|
|
97
|
+
method: 'POST',
|
|
98
|
+
headers: { 'Content-Type': 'application/json' },
|
|
99
|
+
body: JSON.stringify({
|
|
100
|
+
jsonrpc: '2.0',
|
|
101
|
+
method: 'call',
|
|
102
|
+
id: 2,
|
|
103
|
+
params: {
|
|
104
|
+
service: 'object',
|
|
105
|
+
method: 'execute_kw',
|
|
106
|
+
args: [
|
|
107
|
+
process.env.TRIDENT_DB,
|
|
108
|
+
parseInt(process.env.TRIDENT_UID, 10),
|
|
109
|
+
process.env.TRIDENT_TOKEN,
|
|
110
|
+
'project.task',
|
|
111
|
+
'write',
|
|
112
|
+
[[parseInt(taskId, 10)], { x_release_checklist: updated }],
|
|
113
|
+
],
|
|
114
|
+
},
|
|
115
|
+
}),
|
|
116
|
+
});
|
|
117
|
+
const data = await res.json();
|
|
118
|
+
if (data.error) throw new Error(`Trident write error: ${JSON.stringify(data.error)}`);
|
|
125
119
|
}
|
|
126
120
|
|
|
127
121
|
function scoreSections(sections, candidates) {
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
122
|
+
const results = [];
|
|
123
|
+
for (const section of sections) {
|
|
124
|
+
const heading = section.heading.replace(/^### /, '').toLowerCase().trim();
|
|
125
|
+
let score = 0;
|
|
126
|
+
for (const candidate of candidates) {
|
|
127
|
+
const lc = candidate.toLowerCase().trim();
|
|
128
|
+
if (heading === lc) {
|
|
129
|
+
score += 100;
|
|
130
|
+
continue;
|
|
131
|
+
}
|
|
132
|
+
if (heading.includes(lc) || lc.includes(heading)) {
|
|
133
|
+
score += 50;
|
|
134
|
+
continue;
|
|
135
|
+
}
|
|
136
|
+
// Match by first pipe-segment (e.g. "CROSS_31.1 - ML")
|
|
137
|
+
const candidatePrefix = lc.split('|')[0].trim();
|
|
138
|
+
const headingPrefix = heading.split('|')[0].trim();
|
|
139
|
+
if (
|
|
140
|
+
headingPrefix.includes(candidatePrefix) ||
|
|
141
|
+
candidatePrefix.includes(headingPrefix)
|
|
142
|
+
) {
|
|
143
|
+
score += 20;
|
|
144
|
+
continue;
|
|
145
|
+
}
|
|
146
|
+
// Token fallback
|
|
147
|
+
const tokens = lc.split(/[\s|_\-.]+/).filter((t) => t.length > 2);
|
|
148
|
+
for (const token of tokens) {
|
|
149
|
+
if (heading.includes(token)) score++;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
if (score > 0) results.push({ ...section, score });
|
|
159
153
|
}
|
|
160
|
-
|
|
161
|
-
}
|
|
162
|
-
return results.sort((a, b) => b.score - a.score).slice(0, 3);
|
|
154
|
+
return results.sort((a, b) => b.score - a.score).slice(0, 3);
|
|
163
155
|
}
|
|
164
156
|
|
|
165
157
|
async function selectSection(sections, candidates) {
|
|
166
|
-
|
|
158
|
+
const scored = candidates.length > 0 ? scoreSections(sections, candidates) : [];
|
|
167
159
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
160
|
+
if (candidates.length > 0) {
|
|
161
|
+
console.log(`\nTask fields: ${candidates.join(' | ')}`);
|
|
162
|
+
if (scored.length === 0) console.log('No matching sections found.');
|
|
163
|
+
}
|
|
172
164
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
165
|
+
const scoredHeadings = new Set(scored.map((s) => s.heading));
|
|
166
|
+
const topChoices = scored.map((s) => ({
|
|
167
|
+
name: `${s.heading.replace(/^### /, '')} ✓`,
|
|
168
|
+
value: s.heading,
|
|
169
|
+
}));
|
|
170
|
+
const restChoices = sections
|
|
171
|
+
.filter((s) => !scoredHeadings.has(s.heading))
|
|
172
|
+
.map((s) => ({ name: s.heading.replace(/^### /, ''), value: s.heading }));
|
|
173
|
+
const allChoices = [...topChoices, ...restChoices];
|
|
182
174
|
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
});
|
|
192
|
-
return sections.find((s) => s.heading === selected);
|
|
175
|
+
const selected = await search({
|
|
176
|
+
message: 'Select changelog section:',
|
|
177
|
+
source: async (input) => {
|
|
178
|
+
if (!input) return allChoices;
|
|
179
|
+
return allChoices.filter((c) => c.value.toLowerCase().includes(input.toLowerCase()));
|
|
180
|
+
},
|
|
181
|
+
});
|
|
182
|
+
return sections.find((s) => s.heading === selected);
|
|
193
183
|
}
|
|
194
184
|
|
|
195
185
|
async function autopr(options) {
|
|
196
|
-
|
|
197
|
-
|
|
186
|
+
const ADDONS_PATH = resolveAddonsPath(process.env.ADDONS_PATH);
|
|
187
|
+
const changelogPath = `${ADDONS_PATH}/CHANGELOG.md`;
|
|
198
188
|
|
|
199
|
-
|
|
200
|
-
|
|
189
|
+
const ids = options.trident ?? [];
|
|
190
|
+
const hasTridents = ids.length > 0;
|
|
201
191
|
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
: [];
|
|
205
|
-
tasks.forEach((t) => console.log(`Task: ${t.name}`));
|
|
192
|
+
const tasks = hasTridents ? await Promise.all(ids.map((id) => fetchTask(id))) : [];
|
|
193
|
+
tasks.forEach((t) => console.log(`Task: ${t.name}`));
|
|
206
194
|
|
|
207
|
-
|
|
195
|
+
const content = readFileSync(changelogPath, 'utf-8');
|
|
208
196
|
|
|
209
|
-
|
|
210
|
-
? findDuplicateLine(content, ids, [])
|
|
211
|
-
: null;
|
|
197
|
+
const duplicate = hasTridents ? findDuplicateLine(content, ids, []) : null;
|
|
212
198
|
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
199
|
+
let appendMode = false;
|
|
200
|
+
if (duplicate) {
|
|
201
|
+
console.log(`\nExisting entry (line ${duplicate.lineNumber + 1}):\n ${duplicate.line}`);
|
|
202
|
+
const { confirm } = await inquirer.prompt([
|
|
203
|
+
{
|
|
204
|
+
type: 'confirm',
|
|
205
|
+
name: 'confirm',
|
|
206
|
+
message: 'Append PR ref to existing entry?',
|
|
207
|
+
default: true,
|
|
208
|
+
},
|
|
209
|
+
]);
|
|
210
|
+
appendMode = confirm;
|
|
211
|
+
}
|
|
226
212
|
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
: options.jira?.[0]
|
|
232
|
-
? `autopr_${options.jira[0]}`
|
|
233
|
-
: null);
|
|
234
|
-
if (!branch)
|
|
235
|
-
throw new Error(
|
|
236
|
-
"No branch name: provide --branch, a task ID, or --jira",
|
|
237
|
-
);
|
|
213
|
+
const branch =
|
|
214
|
+
options.branch ??
|
|
215
|
+
(ids[0] ? `autopr_${ids[0]}` : options.jira?.[0] ? `autopr_${options.jira[0]}` : null);
|
|
216
|
+
if (!branch) throw new Error('No branch name: provide --branch, a task ID, or --jira');
|
|
238
217
|
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
218
|
+
let message = null;
|
|
219
|
+
if (!appendMode) {
|
|
220
|
+
message = options.message;
|
|
221
|
+
if (!message) {
|
|
222
|
+
const answer = await inquirer.prompt([
|
|
223
|
+
{ type: 'input', name: 'message', message: 'Changelog entry message:' },
|
|
224
|
+
]);
|
|
225
|
+
message = answer.message;
|
|
226
|
+
}
|
|
247
227
|
}
|
|
248
|
-
}
|
|
249
228
|
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
229
|
+
await execGit(['checkout', '-b', branch], ADDONS_PATH);
|
|
230
|
+
console.log(`Branch created: ${branch}`);
|
|
231
|
+
await execGit(['push', '-u', 'origin', branch], ADDONS_PATH);
|
|
253
232
|
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
233
|
+
const prTitle = options.name ?? tasks[0]?.name ?? branch;
|
|
234
|
+
const prDescription = buildPrDescription(ids, options.jira ?? []);
|
|
235
|
+
const { id: prNumber, url: prUrl } = await createDevopsPR(branch, prTitle, prDescription);
|
|
236
|
+
console.log(`PR opened: #${prNumber} — ${prUrl}`);
|
|
258
237
|
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
238
|
+
if (hasTridents) {
|
|
239
|
+
for (let i = 0; i < ids.length; i++) {
|
|
240
|
+
await appendChecklistPrLink(ids[i], tasks[i].x_release_checklist, prUrl, prNumber);
|
|
241
|
+
}
|
|
242
|
+
console.log('Checklist updated');
|
|
262
243
|
}
|
|
263
|
-
console.log("Checklist updated");
|
|
264
|
-
}
|
|
265
244
|
|
|
266
|
-
|
|
245
|
+
const lines = content.split('\n');
|
|
267
246
|
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
247
|
+
if (appendMode) {
|
|
248
|
+
lines[duplicate.lineNumber] = appendPrToLine(lines[duplicate.lineNumber], prNumber);
|
|
249
|
+
} else {
|
|
250
|
+
const sections = extractSections(content);
|
|
251
|
+
const candidates = [];
|
|
252
|
+
if (hasTridents) {
|
|
253
|
+
const anchor = tasks.find(
|
|
254
|
+
(t) =>
|
|
255
|
+
(Array.isArray(t.x_subpackage_id) && t.x_subpackage_id[1]) ||
|
|
256
|
+
(Array.isArray(t.x_workflow) && t.x_workflow[1]) ||
|
|
257
|
+
(Array.isArray(t.x_cluster_id) && t.x_cluster_id[1])
|
|
258
|
+
);
|
|
259
|
+
if (anchor) {
|
|
260
|
+
if (Array.isArray(anchor.x_subpackage_id) && anchor.x_subpackage_id[1])
|
|
261
|
+
candidates.push(anchor.x_subpackage_id[1]);
|
|
262
|
+
if (Array.isArray(anchor.x_workflow) && anchor.x_workflow[1])
|
|
263
|
+
candidates.push(anchor.x_workflow[1]);
|
|
264
|
+
if (Array.isArray(anchor.x_cluster_id) && anchor.x_cluster_id[1])
|
|
265
|
+
candidates.push(anchor.x_cluster_id[1]);
|
|
266
|
+
}
|
|
267
|
+
}
|
|
286
268
|
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
269
|
+
const selectedSection = await selectSection(sections, candidates);
|
|
270
|
+
const endLine = findSectionEndLine(lines, selectedSection.startLine);
|
|
271
|
+
const indent = detectIndentation(lines, selectedSection.startLine, endLine);
|
|
290
272
|
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
273
|
+
const jiras = options.jira ?? [];
|
|
274
|
+
const refString = buildRefString(ids, jiras, prNumber);
|
|
275
|
+
const newEntry = `${indent}- ${message}${refString ? ' ' + refString : ''}`;
|
|
276
|
+
lines.splice(endLine + 1, 0, newEntry);
|
|
277
|
+
}
|
|
296
278
|
|
|
297
|
-
|
|
298
|
-
|
|
279
|
+
await fs.writeFile(changelogPath, lines.join('\n'));
|
|
280
|
+
console.log('Changelog entry written');
|
|
299
281
|
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
);
|
|
305
|
-
await execGit(["push"], ADDONS_PATH);
|
|
306
|
-
console.log("Changelog committed and pushed");
|
|
282
|
+
await execGit(['add', 'CHANGELOG.md'], ADDONS_PATH);
|
|
283
|
+
await execGit(['commit', '-m', '[DOC][CHANGELOG] Changelog'], ADDONS_PATH);
|
|
284
|
+
await execGit(['push'], ADDONS_PATH);
|
|
285
|
+
console.log('Changelog committed and pushed');
|
|
307
286
|
}
|
|
308
287
|
|
|
309
288
|
export { autopr };
|