Skip to content

Commit 6d59d75

Browse files
committed
Merge branch 'feature-releaser' into 'main'
Added releaser script See merge request isard/isardvdi!325
2 parents d653bab + 9212532 commit 6d59d75

File tree

5 files changed

+403
-0
lines changed

5 files changed

+403
-0
lines changed

.gitlab-ci.yml

+49
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
stages:
2+
- build
3+
- changelog
4+
- force-changelog-retry
5+
16
docker-build:
27
image: docker:latest
38
stage: build
@@ -24,3 +29,47 @@ docker-build:
2429
artifacts:
2530
paths:
2631
- docker-compose*.yml
32+
33+
.changelog:
34+
image: registry.gitlab.com/gitlab-org/release-cli
35+
stage: changelog
36+
before_script:
37+
- apk add --no-cache nodejs npm git
38+
- cd releaser && npm i --save && cd -
39+
40+
changelog:
41+
extends: .changelog
42+
rules:
43+
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
44+
script:
45+
- ./releaser/index.js CHANGELOG.md
46+
47+
changelog-release:
48+
extends: .changelog
49+
rules:
50+
- if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
51+
script:
52+
- url_host=`git remote get-url origin | sed -e "s/https:\/\/gitlab-ci-token:.*@//g"`
53+
- git remote set-url origin "https://${GITLAB_LOGIN}:${GITLAB_TOKEN}@${url_host}"
54+
- ./releaser/index.js CHANGELOG.md --release
55+
56+
force-changelog-retry:
57+
image: alpine
58+
stage: force-changelog-retry
59+
rules:
60+
- if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
61+
when: always
62+
allow_failure: true
63+
- when: never
64+
before_script:
65+
- apk add --no-cache jq curl
66+
script:
67+
- export gitlab_base_url="https://gitlab.com/api/v4/projects"
68+
- |
69+
export opened_merge_requests=`curl -H "Authorization: Bearer ${GITLAB_TOKEN}" "${gitlab_base_url}/${PROJECT_ID}/merge_requests?state=opened"`
70+
- |
71+
for iid in $(echo "${opened_merge_requests}" | jq '.[] | .iid'); do
72+
latest_pipeline=`curl -H "Authorization: Bearer ${GITLAB_TOKEN}" "${gitlab_base_url}/${PROJECT_ID}/merge_requests/${iid}/pipelines" | jq '.[0] | .id'`
73+
latest_changelog_job=`curl -H "Authorization: Bearer ${GITLAB_TOKEN}" "${gitlab_base_url}/${PROJECT_ID}/pipelines/${latest_pipeline}" | jq '.[] | select(.name == "changelog") | .id' `
74+
curl -x POST -H "Authorization: Bearer ${GITLAB_TOKEN}" "$gitlab_base_url/${PROJECT_ID}/jobs/${latest_changelog_job}/retry"
75+
done

CHANGELOG.md

+6
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,12 @@
22

33
All notable changes to this project will be documented in this file.
44

5+
## [3.1.0] - 2021-09-01
6+
7+
### Added
8+
9+
- Added the releaser script. Now tags and GitLab releases are done automatically
10+
511
## [3.0.2] - 2021-08-27
612

713
### Fixed

releaser/index.js

+129
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
#!/usr/bin/env node
2+
3+
const fs = require("fs");
4+
const marked = require("marked");
5+
const git = require("isomorphic-git");
6+
const execSync = require("child_process").execSync;
7+
const quote = require("shell-quote").quote;
8+
const https = require("https");
9+
const semver = require("semver");
10+
11+
if (process.argv.length < 3) {
12+
console.error("Please, pass the CHANGELOG.md path as argument");
13+
process.exit(1);
14+
}
15+
16+
let release = false;
17+
if (process.argv.length === 4 && process.argv[3] === "--release") {
18+
release = true;
19+
}
20+
21+
const changelogPath = process.argv[2];
22+
23+
(async () => {
24+
try {
25+
const changelog = fs.readFileSync(changelogPath, "utf8");
26+
27+
const content = marked.lexer(changelog);
28+
29+
let latestVersion = false;
30+
let version;
31+
let versionTitle;
32+
let versionChangelog = "";
33+
for (let i = 0; i < content.length; i++) {
34+
const item = content[i];
35+
36+
// Every item in the CHANGELOG with depth 2 is a release
37+
if (item.type === "heading" && item.depth === 2) {
38+
if (latestVersion) {
39+
break;
40+
}
41+
42+
latestVersion = true;
43+
44+
// Get the version number
45+
version = item.text.match(/\[(.*)\]/).pop();
46+
versionTitle = item.text;
47+
}
48+
49+
if (latestVersion) {
50+
versionChangelog += item.raw;
51+
}
52+
}
53+
54+
const tagName = "v" + version;
55+
56+
const getReleases = new Promise((resolve, reject) => {
57+
https.get(
58+
`https://gitlab.com/api/v4/projects/${process.env.CI_PROJECT_ID}/releases`,
59+
(rsp) => {
60+
let data = [];
61+
62+
rsp.on("data", (fragment) => {
63+
data.push(fragment);
64+
});
65+
66+
rsp.on("end", () => {
67+
const body = Buffer.concat(data).toString();
68+
69+
if (rsp.statusCode !== 200) {
70+
reject(`HTTP Code ${rsp.statusCode}: ${body}`);
71+
}
72+
73+
resolve(body);
74+
});
75+
76+
rsp.on("error", (err) => {
77+
reject(err);
78+
});
79+
}
80+
);
81+
});
82+
83+
const releases = JSON.parse(await getReleases);
84+
if (releases.length > 0) {
85+
if (semver.lte(tagName, releases[0].tag_name)) {
86+
console.error(
87+
"CHANGELOG not updated or outdated! Write an entry to the CHANGELOG >:(!"
88+
);
89+
process.exit(1);
90+
}
91+
}
92+
93+
if (release) {
94+
await git.annotatedTag({
95+
fs,
96+
dir: ".",
97+
ref: tagName,
98+
message: versionChangelog,
99+
tagger: {
100+
name: process.env.GITLAB_USER_NAME,
101+
email: process.env.GITLAB_USER_EMAIL,
102+
},
103+
});
104+
105+
await git.push({
106+
fs,
107+
http: require("isomorphic-git/http/node"),
108+
dir: ".",
109+
ref: tagName,
110+
});
111+
112+
execSync(
113+
quote([
114+
"release-cli",
115+
"create",
116+
"--tag-name",
117+
tagName,
118+
"--name",
119+
versionTitle,
120+
"--description",
121+
versionChangelog,
122+
])
123+
);
124+
}
125+
} catch (err) {
126+
console.log(err);
127+
process.exit(1);
128+
}
129+
})();

0 commit comments

Comments
 (0)