@uxf/scripts 11.14.0 → 11.23.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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@uxf/scripts",
|
|
3
|
-
"version": "11.
|
|
3
|
+
"version": "11.23.1",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"bin": {
|
|
@@ -26,7 +26,6 @@
|
|
|
26
26
|
"author": "",
|
|
27
27
|
"license": "ISC",
|
|
28
28
|
"dependencies": {
|
|
29
|
-
"@commitlint/parse": "19.0.3",
|
|
30
29
|
"axios": "1.6.7",
|
|
31
30
|
"cheerio": "1.0.0-rc.12",
|
|
32
31
|
"dayjs": "1.11.10",
|
package/src/GitLab.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
const { env } = require("process");
|
|
2
2
|
const { create } = require("axios");
|
|
3
3
|
const dayjs = require("dayjs");
|
|
4
|
-
const parse = import("@commitlint/parse");
|
|
5
4
|
|
|
6
5
|
const axios = create({
|
|
7
6
|
baseURL: `${env.CI_SERVER_URL}/api/v4`,
|
|
@@ -36,7 +35,6 @@ async function getAll(url, config) {
|
|
|
36
35
|
|
|
37
36
|
async function loadCommits(from) {
|
|
38
37
|
const commits = [];
|
|
39
|
-
console.log(`- start date: ${from}`);
|
|
40
38
|
|
|
41
39
|
let nextPage = "1";
|
|
42
40
|
do {
|
|
@@ -52,38 +50,7 @@ async function loadCommits(from) {
|
|
|
52
50
|
commits.push(...response.data);
|
|
53
51
|
} while (nextPage);
|
|
54
52
|
|
|
55
|
-
|
|
56
|
-
for (const commit of commits) {
|
|
57
|
-
if (commit.created_at === from) {
|
|
58
|
-
continue;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
const parsedTitle = await parse(commit.title, undefined, { issuePrefixes: ["#"] });
|
|
62
|
-
|
|
63
|
-
preparedCommits.push({
|
|
64
|
-
...commit,
|
|
65
|
-
parsedTitle: {
|
|
66
|
-
scope: parsedTitle.scope,
|
|
67
|
-
type: parsedTitle.type,
|
|
68
|
-
subject: (parsedTitle.subject || commit.title).replace(/(#[0-9]*)/g, "").trim(),
|
|
69
|
-
},
|
|
70
|
-
issueIds: parsedTitle.references.map((ref) => Number.parseInt(ref.issue)).filter((i) => !!i),
|
|
71
|
-
});
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
return preparedCommits;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
async function loadIssues(iids) {
|
|
78
|
-
if (iids.length === 0) {
|
|
79
|
-
return [];
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
const { data } = await axios.get(`/projects/${env.CI_PROJECT_ID}/issues`, {
|
|
83
|
-
params: { iids },
|
|
84
|
-
});
|
|
85
|
-
|
|
86
|
-
return data;
|
|
53
|
+
return commits.filter((commit) => commit.created_at !== from);
|
|
87
54
|
}
|
|
88
55
|
|
|
89
56
|
async function getLastTag() {
|
|
@@ -121,11 +88,14 @@ function getSingleMergeRequestChanges(projectId, mr_iid) {
|
|
|
121
88
|
return axios.get(`/projects/${projectId}/merge_requests/${mr_iid}/changes`).then((r) => r.data);
|
|
122
89
|
}
|
|
123
90
|
|
|
124
|
-
|
|
91
|
+
/**
|
|
92
|
+
* @param {boolean} includeWip
|
|
93
|
+
*/
|
|
94
|
+
function getAllMergeRequests(includeWip) {
|
|
125
95
|
return getAll("/merge_requests", {
|
|
126
96
|
params: {
|
|
127
97
|
approwed: "no",
|
|
128
|
-
wip: "no",
|
|
98
|
+
wip: includeWip ? undefined : "no",
|
|
129
99
|
sort: "asc",
|
|
130
100
|
scope: "all",
|
|
131
101
|
state: "opened",
|
|
@@ -140,7 +110,6 @@ function getAllProjects() {
|
|
|
140
110
|
|
|
141
111
|
module.exports = {
|
|
142
112
|
loadCommits,
|
|
143
|
-
loadIssues,
|
|
144
113
|
getLastTag,
|
|
145
114
|
createRelease,
|
|
146
115
|
getAllMergeRequests,
|
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
const { argv, env } = require("process");
|
|
2
2
|
|
|
3
|
+
const AVAILABLE_VARIANTS = ["CR", "STALE"];
|
|
4
|
+
|
|
3
5
|
module.exports = async () => {
|
|
4
6
|
const cli = require("yargs")
|
|
5
7
|
.command("$0", "UXF merge requests notifier", (yargs) => {
|
|
6
8
|
yargs.demandCommand(0, 0).usage(`Usage:
|
|
7
9
|
uxf-merge-requests-notifier [options]
|
|
8
|
-
|
|
10
|
+
|
|
9
11
|
Environment variables:
|
|
12
|
+
VARIANT - optional - CR (default), STALE
|
|
10
13
|
GITLAB_TOKEN - required
|
|
11
14
|
GOOGLE_WEBHOOK_URL - required
|
|
12
15
|
CI_SERVER_URL - required - setting by GitLab CI`);
|
|
@@ -32,7 +35,14 @@ Environment variables:
|
|
|
32
35
|
return 1;
|
|
33
36
|
}
|
|
34
37
|
|
|
35
|
-
|
|
38
|
+
const variant = env.VARIANT?.toUpperCase() ?? "CR";
|
|
39
|
+
|
|
40
|
+
if (!AVAILABLE_VARIANTS.includes(variant)) {
|
|
41
|
+
console.log(`Unknown "${variant}" variant. Available variants are ${AVAILABLE_VARIANTS.join(", ")}.`);
|
|
42
|
+
return 1;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
await require("./index")(variant);
|
|
36
46
|
} catch (e) {
|
|
37
47
|
console.error(e);
|
|
38
48
|
return 1;
|
|
@@ -10,41 +10,59 @@ function inflect(value, word1, word2, word3) {
|
|
|
10
10
|
return `${value} ${value === 1 ? word1 : value <= 4 ? word2 : word3}`;
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
function mapMergeRequests(mrs, projects) {
|
|
14
|
+
return mrs.map((mr) => ({
|
|
15
|
+
id: mr.id,
|
|
16
|
+
iid: mr.iid,
|
|
17
|
+
reviewers: mr.reviewers ?? [],
|
|
18
|
+
project: projects.find((project) => project.id === mr.project_id),
|
|
19
|
+
title: mr.title,
|
|
20
|
+
author: mr.author,
|
|
21
|
+
createdAt: mr.created_at,
|
|
22
|
+
updatedAt: mr.updated_at,
|
|
23
|
+
webUrl: mr.web_url,
|
|
24
|
+
state: mr.state.toUpperCase(),
|
|
25
|
+
targetBranch: mr.target_branch,
|
|
26
|
+
sourceBranch: mr.source_branch,
|
|
27
|
+
}));
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function getChatPostMessage(resultsCount, variant) {
|
|
31
|
+
switch (variant) {
|
|
32
|
+
case "CR":
|
|
33
|
+
return `🔥🔥🔥 ${inflect(resultsCount, "MR čekající na code review", "MR čekající na code review", "MR čekajících na code review",)}`;
|
|
34
|
+
case "STALE":
|
|
35
|
+
return `❗❗❗ ${inflect(resultsCount, "MR starší než měsíc", "MR starší než měsíc", "MR starších než měsíc")}`;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* @param variant
|
|
41
|
+
*/
|
|
42
|
+
module.exports = async function run(variant) {
|
|
14
43
|
const projects = await GitLab.getAllProjects();
|
|
15
|
-
const allMergeRequests = await GitLab.getAllMergeRequests();
|
|
44
|
+
const allMergeRequests = await GitLab.getAllMergeRequests(variant === "STALE");
|
|
16
45
|
|
|
17
|
-
|
|
18
|
-
.map((mr) => ({
|
|
19
|
-
id: mr.id,
|
|
20
|
-
iid: mr.iid,
|
|
21
|
-
reviewers: mr.reviewers ?? [],
|
|
22
|
-
project: projects.find((project) => project.id === mr.project_id),
|
|
23
|
-
title: mr.title,
|
|
24
|
-
author: mr.author,
|
|
25
|
-
createdAt: mr.created_at,
|
|
26
|
-
updatedAt: mr.updated_at,
|
|
27
|
-
webUrl: mr.web_url,
|
|
28
|
-
state: mr.state.toUpperCase(),
|
|
29
|
-
targetBranch: mr.target_branch,
|
|
30
|
-
sourceBranch: mr.source_branch,
|
|
31
|
-
}))
|
|
32
|
-
.filter((mr) => mr.reviewers.length === 0)
|
|
46
|
+
let result = mapMergeRequests(allMergeRequests, projects)
|
|
33
47
|
.filter((mr) => mr.sourceBranch !== "develop" || mr.targetBranch !== "master")
|
|
34
48
|
.filter((mr) => !mr.project.archived);
|
|
35
49
|
|
|
50
|
+
switch (variant) {
|
|
51
|
+
case "CR":
|
|
52
|
+
result = result.filter((mr) => mr.reviewers.length === 0);
|
|
53
|
+
break;
|
|
54
|
+
case "STALE":
|
|
55
|
+
result = result.filter(mr => dayjs().diff(mr.updatedAt, "days") > 30);
|
|
56
|
+
break;
|
|
57
|
+
}
|
|
58
|
+
|
|
36
59
|
if (result.length === 0) {
|
|
37
|
-
console.log("No merge requests
|
|
60
|
+
console.log("No merge requests.");
|
|
38
61
|
return;
|
|
39
62
|
}
|
|
40
63
|
|
|
41
64
|
await GoogleChat.chatPostMessage({
|
|
42
|
-
text:
|
|
43
|
-
result.length,
|
|
44
|
-
"MR čekající na code review",
|
|
45
|
-
"MR čekající na code review",
|
|
46
|
-
"MR čekajících na code review",
|
|
47
|
-
)}`,
|
|
65
|
+
text: getChatPostMessage(result.length, variant),
|
|
48
66
|
});
|
|
49
67
|
|
|
50
68
|
for (const mr of result) {
|
package/src/uxf-release/cli.js
CHANGED
|
@@ -2,16 +2,17 @@ const { argv, env } = require("process");
|
|
|
2
2
|
|
|
3
3
|
module.exports = async () => {
|
|
4
4
|
const cli = require("yargs")
|
|
5
|
-
.command("$0", "UXF release helper", yargs => {
|
|
5
|
+
.command("$0", "UXF release helper", (yargs) => {
|
|
6
6
|
yargs.demandCommand(0, 0).usage(`UXF release helper
|
|
7
7
|
Usage:
|
|
8
8
|
uxf-release [options]
|
|
9
9
|
|
|
10
10
|
Environment variables:
|
|
11
|
-
GITLAB_TOKEN
|
|
12
|
-
CI_SERVER_URL
|
|
13
|
-
CI_PROJECT_ID
|
|
14
|
-
SLACK_TOKEN
|
|
11
|
+
GITLAB_TOKEN - required
|
|
12
|
+
CI_SERVER_URL - required - setting by GitLab CI
|
|
13
|
+
CI_PROJECT_ID - required - setting by GitLab CI
|
|
14
|
+
SLACK_TOKEN - optional
|
|
15
|
+
GOOGLE_WEBHOOK_URL - optional`);
|
|
15
16
|
})
|
|
16
17
|
.option("m", {
|
|
17
18
|
alias: "message",
|
|
@@ -55,11 +56,6 @@ Environment variables:
|
|
|
55
56
|
env.CI_PROJECT_ID = projectId;
|
|
56
57
|
}
|
|
57
58
|
|
|
58
|
-
if (!slackChannel) {
|
|
59
|
-
console.log("Slack channel must be set. Use parameter -s or --slack-channel");
|
|
60
|
-
return 1;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
59
|
if (!env.CI_SERVER_URL) {
|
|
64
60
|
console.log("GitLab url must be set. Use environment variable CI_SERVER_URL.");
|
|
65
61
|
return 1;
|
package/src/uxf-release/index.js
CHANGED
|
@@ -2,98 +2,129 @@ const GitLab = require("../GitLab");
|
|
|
2
2
|
const Slack = require("../Slack");
|
|
3
3
|
const GoogleChat = require("../GoogleChat");
|
|
4
4
|
|
|
5
|
-
function
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
5
|
+
function parseCommitMessage(commitMessage) {
|
|
6
|
+
/* fix(bo): [KLK-123] commit message */
|
|
7
|
+
const result = /^(.*)\((.*)\): \[(.*)\] (.*)/.exec(commitMessage);
|
|
8
|
+
|
|
9
|
+
if (result !== null) {
|
|
10
|
+
return {
|
|
11
|
+
type: result[1],
|
|
12
|
+
issues: result[3].replace(" ", "").split(","),
|
|
13
|
+
message: result[4],
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/* fix: [KLK-123] commit message */
|
|
18
|
+
const result_1 = /^(.*): \[(.*)\] (.*)/.exec(commitMessage);
|
|
19
|
+
|
|
20
|
+
if (result_1 !== null) {
|
|
21
|
+
return {
|
|
22
|
+
type: result_1[1],
|
|
23
|
+
issues: result_1[3].replace(" ", "").split(","),
|
|
24
|
+
message: result_1[4],
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/* [KLK-123] commit message */
|
|
29
|
+
const result_2 = /^\[(.*)\] (.*)/.exec(commitMessage);
|
|
30
|
+
|
|
31
|
+
if (result_2 !== null) {
|
|
32
|
+
return {
|
|
33
|
+
type: null,
|
|
34
|
+
issues: result_2[1].replace(" ", "").split(","),
|
|
35
|
+
message: result_2[2],
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function generateSlackCommitMessage(commit) {
|
|
43
|
+
const { title, short_id, web_url, author_email } = commit;
|
|
44
|
+
|
|
45
|
+
const parsedCommit = parseCommitMessage(title);
|
|
46
|
+
|
|
47
|
+
return parsedCommit?.type
|
|
48
|
+
? `• _${parsedCommit.type.toUpperCase()}_ - ${parsedCommit.message} <${web_url}|${short_id}> (${author_email})`
|
|
49
|
+
: `• ${title} <${web_url}|${short_id}> (${author_email})`;
|
|
21
50
|
}
|
|
22
51
|
|
|
23
|
-
function
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
52
|
+
function generateSlackMessage(commits, messageTitle) {
|
|
53
|
+
return {
|
|
54
|
+
text: `${messageTitle}
|
|
55
|
+
|
|
56
|
+
${commits.map(generateSlackCommitMessage).join("\n")}
|
|
57
|
+
`,
|
|
58
|
+
};
|
|
27
59
|
}
|
|
28
60
|
|
|
29
|
-
function
|
|
30
|
-
|
|
61
|
+
function generateGoogleCommitMessage(commit) {
|
|
62
|
+
const { title, short_id, web_url, author_email } = commit;
|
|
63
|
+
const parsedCommit = parseCommitMessage(title);
|
|
64
|
+
|
|
65
|
+
const issues = parsedCommit?.issues.map((issue) => `<https://youtrack.uxf.dev/issue/${issue}|${issue}>`) ?? [];
|
|
31
66
|
|
|
32
|
-
issues.
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
.join("\n")}`;
|
|
36
|
-
});
|
|
67
|
+
const suffix = [`<${web_url}|${short_id}>`, author_email, issues.length > 0 ? issues.join(", ") : null]
|
|
68
|
+
.filter((i) => !!i)
|
|
69
|
+
.join(" | ");
|
|
37
70
|
|
|
38
|
-
if (
|
|
39
|
-
|
|
71
|
+
if (parsedCommit === null) {
|
|
72
|
+
return `* ${title} ${suffix}`;
|
|
40
73
|
}
|
|
41
74
|
|
|
42
|
-
|
|
43
|
-
}
|
|
75
|
+
if (parsedCommit.type !== null && parsedCommit.message !== null) {
|
|
76
|
+
return `* _${parsedCommit.type.toUpperCase()}_ ${parsedCommit.message} ${suffix}`;
|
|
77
|
+
}
|
|
44
78
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
issues.forEach(issue => {
|
|
48
|
-
texts.push(`*${issue.title}* <${issue.web_url}|#${issue.iid}>`);
|
|
49
|
-
issue.commits.forEach((commit) => texts.push(generateSlackCommitMessage(commit)));
|
|
50
|
-
});
|
|
51
|
-
if (commitsWithoutIssues.length > 0) {
|
|
52
|
-
texts.push(`*Commity bez issue*`);
|
|
53
|
-
commitsWithoutIssues.forEach((commit) => texts.push(generateSlackCommitMessage(commit)));
|
|
79
|
+
if (parsedCommit.message) {
|
|
80
|
+
return `* ${parsedCommit.message} ${suffix}`;
|
|
54
81
|
}
|
|
82
|
+
|
|
83
|
+
return `* ${title} ${suffix}`;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function generateGoogleMessage(commits, messageTitle) {
|
|
55
87
|
return {
|
|
56
|
-
text:
|
|
88
|
+
text: `${messageTitle}
|
|
89
|
+
|
|
90
|
+
${commits.map(generateGoogleCommitMessage).join("\n")}
|
|
91
|
+
`,
|
|
57
92
|
};
|
|
58
93
|
}
|
|
59
94
|
|
|
60
|
-
function
|
|
61
|
-
const { title,
|
|
95
|
+
function generateReleaseCommitMessage(commit) {
|
|
96
|
+
const { title, short_id, web_url, author_email } = commit;
|
|
62
97
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
} <${web_url}|${short_id}> (${author_email})`
|
|
67
|
-
: `• ${title} <${web_url}|${short_id}> (${author_email})`;
|
|
68
|
-
}
|
|
98
|
+
const parsedCommit = parseCommitMessage(title);
|
|
99
|
+
|
|
100
|
+
const issues = parsedCommit?.issues.map((issue) => `[${issue}](https://youtrack.uxf.dev/issue/${issue})`) ?? [];
|
|
69
101
|
|
|
70
|
-
|
|
71
|
-
|
|
102
|
+
const suffix = [`[${short_id}](${web_url})`, author_email, issues.length > 0 ? issues.join(", ") : null]
|
|
103
|
+
.filter((i) => !!i)
|
|
104
|
+
.join(" | ");
|
|
72
105
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
106
|
+
if (parsedCommit === null) {
|
|
107
|
+
return `- ${title} ${suffix}`;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
if (parsedCommit.type !== null && parsedCommit.message !== null) {
|
|
111
|
+
return `- **${parsedCommit.type.toUpperCase()}** ${parsedCommit.message} ${suffix}`;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
if (parsedCommit.message) {
|
|
115
|
+
return `- ${parsedCommit.message} ${suffix}`;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
return `- ${title} ${suffix}`;
|
|
76
119
|
}
|
|
77
120
|
|
|
78
121
|
module.exports = async (dryRun, channel, messageTitle) => {
|
|
79
122
|
const lastTag = await GitLab.getLastTag();
|
|
80
123
|
const commits = await GitLab.loadCommits(lastTag ? lastTag.commit.committed_date : null);
|
|
81
|
-
const issues = await GitLab.loadIssues(getIssueIdsFromCommits(commits));
|
|
82
|
-
|
|
83
|
-
addCommitsToIssues(commits, issues);
|
|
84
|
-
|
|
85
|
-
const commitsWithoutIssue = commits.filter(c => c.issueIds.length === 0);
|
|
86
124
|
|
|
87
|
-
await Slack.chatPostMessage(
|
|
88
|
-
channel,
|
|
89
|
-
{ text: generateSlackMessage(issues, commitsWithoutIssue, messageTitle) },
|
|
90
|
-
dryRun,
|
|
91
|
-
);
|
|
125
|
+
await Slack.chatPostMessage(channel, { text: generateSlackMessage(commits, messageTitle) }, dryRun);
|
|
92
126
|
|
|
93
|
-
await GoogleChat.chatPostMessage(
|
|
94
|
-
generateGoogleMessage(issues, commitsWithoutIssue, messageTitle),
|
|
95
|
-
dryRun,
|
|
96
|
-
);
|
|
127
|
+
await GoogleChat.chatPostMessage(generateGoogleMessage(commits, messageTitle), dryRun);
|
|
97
128
|
|
|
98
|
-
await GitLab.createRelease(commits.map(
|
|
129
|
+
await GitLab.createRelease(commits.map(generateReleaseCommitMessage).join("\n"), dryRun);
|
|
99
130
|
};
|