@waron97/prbot 2.1.0 → 2.3.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 -263
- package/src/commands/changelog.js +154 -150
- package/src/commands/commit.js +146 -0
- package/src/commands/export.js +7 -0
- package/src/commands/exportPb.js +156 -0
- package/src/commands/init.js +144 -136
- package/src/commands/pr.js +81 -107
- package/src/commands/ver.js +54 -64
- package/src/config.js +4 -4
- package/src/index.js +112 -78
- package/src/lib/addons.js +4 -4
- package/src/lib/auth.js +25 -0
- 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.3.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,313 +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
|
-
|
|
48
|
-
|
|
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
|
+
],
|
|
49
51
|
},
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
throw new Error(`Trident error: ${JSON.stringify(data.error)}`);
|
|
61
|
-
if (!data.result || !data.result[0])
|
|
62
|
-
throw new Error(`Task ${taskId} not found`);
|
|
63
|
-
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];
|
|
64
62
|
}
|
|
65
63
|
|
|
66
64
|
function buildPrDescription(taskIds, jiras) {
|
|
67
|
-
|
|
68
|
-
(
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
lines.
|
|
72
|
-
}
|
|
73
|
-
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');
|
|
74
70
|
}
|
|
75
71
|
|
|
76
72
|
async function createDevopsPR(branch, title, description) {
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
})
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
const prUrl = `https://dev.azure.com/${DEVOPS_ORG}/${DEVOPS_PROJECT}/_git/${DEVOPS_REPO}/pullrequest/${data.pullRequestId}`;
|
|
95
|
-
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 };
|
|
96
90
|
}
|
|
97
91
|
|
|
98
92
|
async function appendChecklistPrLink(taskId, currentChecklist, prUrl, prNumber) {
|
|
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
|
-
|
|
125
|
-
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)}`);
|
|
126
119
|
}
|
|
127
120
|
|
|
128
121
|
function scoreSections(sections, candidates) {
|
|
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
|
-
|
|
159
|
-
|
|
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 });
|
|
160
153
|
}
|
|
161
|
-
|
|
162
|
-
}
|
|
163
|
-
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);
|
|
164
155
|
}
|
|
165
156
|
|
|
166
157
|
async function selectSection(sections, candidates) {
|
|
167
|
-
|
|
158
|
+
const scored = candidates.length > 0 ? scoreSections(sections, candidates) : [];
|
|
168
159
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
160
|
+
if (candidates.length > 0) {
|
|
161
|
+
console.log(`\nTask fields: ${candidates.join(' | ')}`);
|
|
162
|
+
if (scored.length === 0) console.log('No matching sections found.');
|
|
163
|
+
}
|
|
173
164
|
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
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];
|
|
183
174
|
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
});
|
|
193
|
-
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);
|
|
194
183
|
}
|
|
195
184
|
|
|
196
185
|
async function autopr(options) {
|
|
197
|
-
|
|
198
|
-
|
|
186
|
+
const ADDONS_PATH = resolveAddonsPath(process.env.ADDONS_PATH);
|
|
187
|
+
const changelogPath = `${ADDONS_PATH}/CHANGELOG.md`;
|
|
199
188
|
|
|
200
|
-
|
|
201
|
-
|
|
189
|
+
const ids = options.trident ?? [];
|
|
190
|
+
const hasTridents = ids.length > 0;
|
|
202
191
|
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
: [];
|
|
206
|
-
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}`));
|
|
207
194
|
|
|
208
|
-
|
|
195
|
+
const content = readFileSync(changelogPath, 'utf-8');
|
|
209
196
|
|
|
210
|
-
|
|
211
|
-
? findDuplicateLine(content, ids, [])
|
|
212
|
-
: null;
|
|
197
|
+
const duplicate = hasTridents ? findDuplicateLine(content, ids, []) : null;
|
|
213
198
|
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
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
|
+
}
|
|
227
212
|
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
: options.jira?.[0]
|
|
233
|
-
? `autopr_${options.jira[0]}`
|
|
234
|
-
: null);
|
|
235
|
-
if (!branch)
|
|
236
|
-
throw new Error(
|
|
237
|
-
"No branch name: provide --branch, a task ID, or --jira",
|
|
238
|
-
);
|
|
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');
|
|
239
217
|
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
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
|
+
}
|
|
248
227
|
}
|
|
249
|
-
}
|
|
250
228
|
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
229
|
+
await execGit(['checkout', '-b', branch], ADDONS_PATH);
|
|
230
|
+
console.log(`Branch created: ${branch}`);
|
|
231
|
+
await execGit(['push', '-u', 'origin', branch], ADDONS_PATH);
|
|
254
232
|
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
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}`);
|
|
259
237
|
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
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');
|
|
263
243
|
}
|
|
264
|
-
console.log("Checklist updated");
|
|
265
|
-
}
|
|
266
244
|
|
|
267
|
-
|
|
245
|
+
const lines = content.split('\n');
|
|
268
246
|
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
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
|
+
}
|
|
290
268
|
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
269
|
+
const selectedSection = await selectSection(sections, candidates);
|
|
270
|
+
const endLine = findSectionEndLine(lines, selectedSection.startLine);
|
|
271
|
+
const indent = detectIndentation(lines, selectedSection.startLine, endLine);
|
|
294
272
|
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
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
|
+
}
|
|
300
278
|
|
|
301
|
-
|
|
302
|
-
|
|
279
|
+
await fs.writeFile(changelogPath, lines.join('\n'));
|
|
280
|
+
console.log('Changelog entry written');
|
|
303
281
|
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
);
|
|
309
|
-
await execGit(["push"], ADDONS_PATH);
|
|
310
|
-
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');
|
|
311
286
|
}
|
|
312
287
|
|
|
313
288
|
export { autopr };
|