@omnitoolkit/releasebot 7.3.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 +57 -0
- package/bin/releasebot +6 -0
- package/package.json +37 -0
- package/src/cli.js +242 -0
- package/src/constants.js +48 -0
- package/src/index.js +64 -0
package/README.md
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# releasebot
|
|
2
|
+
|
|
3
|
+
This program analyzes a git repository and, if necessary, performs a release according to the specifications of [conventional commits](https://www.conventionalcommits.org/en/v1.0.0/) and [semantic versioning](https://semver.org/spec/v2.0.0.html).
|
|
4
|
+
|
|
5
|
+
It uses [semantic-release](https://github.com/semantic-release/semantic-release) (see [documentation](https://semantic-release.gitbook.io/semantic-release)) inside a Docker image with a custom-made module (see [index.js](src/index.js)). There, several plugins along with their configuration are defined and loaded on execution:
|
|
6
|
+
|
|
7
|
+
- [@semantic-release/commit-analyzer](https://github.com/semantic-release/commit-analyzer) reads each git commit added since the last release, determines if a new release is due, the type of release and the new version number. It analyzes the syntax according to the conventionalcommits preset in [parser.js](https://github.com/conventional-changelog/conventional-changelog/blob/conventional-changelog-conventionalcommits-v9.0.0/packages/conventional-changelog-conventionalcommits/src/parser.js) and checks for custom rules combined from the [default rules list](https://github.com/semantic-release/commit-analyzer/blob/v13.0.1/lib/default-release-rules.js) and the [@commitlint/config-conventional type list](https://github.com/conventional-changelog/commitlint/blob/v19.8.1/%40commitlint/config-conventional/README.md#type-enum). A commit should look like this:
|
|
8
|
+
```
|
|
9
|
+
<type>(<scope>)!: <short summary>
|
|
10
|
+
│ │ │ │
|
|
11
|
+
│ │ │ └─> Summary in present tense. Not capitalized. No period at the end.
|
|
12
|
+
│ │ │
|
|
13
|
+
│ │ └─> Indicator for breaking change. Optional.
|
|
14
|
+
│ │
|
|
15
|
+
│ └─> Commit scope. Can be any string. Optional.
|
|
16
|
+
│
|
|
17
|
+
└─> Commit type: build|chore|ci|docs|feat|fix|perf|refactor|revert|style|test
|
|
18
|
+
No release: x
|
|
19
|
+
Patch release: x x x x x x x x x
|
|
20
|
+
Minor release: x
|
|
21
|
+
Major release: (any type when used with '!' indicator)
|
|
22
|
+
```
|
|
23
|
+
(chart from [angular](https://github.com/angular/angular/blob/19.0.0/CONTRIBUTING.md#commit-message-header), changed)
|
|
24
|
+
- [@semantic-release/release-notes-generator](https://github.com/semantic-release/release-notes-generator) generates new release notes from the collected information according to the conventionalcommits preset in [writer.js](https://github.com/conventional-changelog/conventional-changelog/blob/conventional-changelog-conventionalcommits-v9.0.0/packages/conventional-changelog-conventionalcommits/src/writer.js) and the default commit types in [constants.js](https://github.com/conventional-changelog/conventional-changelog/blob/conventional-changelog-conventionalcommits-v9.0.0/packages/conventional-changelog-conventionalcommits/src/constants.js), which are changed to the combined custom rules from above.
|
|
25
|
+
- [@semantic-release/changelog](https://github.com/semantic-release/changelog) updates the changelog file `CHANGELOG.md` with the generated release notes.
|
|
26
|
+
- [@semantic-release/exec](https://github.com/semantic-release/exec) updates the file `VERSION` with the new version number (only if `VERSION` exists) and executes the command `./version.sh X.Y.Z` (only if `version.sh` exists). Both are optional, the latter can be used to set the new version number in other files in the repository.
|
|
27
|
+
- [@semantic-release/git](https://github.com/semantic-release/git) adds a new git commit with the above file changes, places a new git tag (new version number with prefixed `v`) and pushes the changes to the git remote.
|
|
28
|
+
- [@semantic-release/gitlab](https://github.com/semantic-release/gitlab) creates a GitLab release via API with the generated release notes.
|
|
29
|
+
|
|
30
|
+
## Requirements
|
|
31
|
+
|
|
32
|
+
- Git repository hosted on GitLab SaaS or self-managed
|
|
33
|
+
- GitLab CI/CD enabled and variable `GITLAB_TOKEN` set (can either be a personal, project or group access token with the scopes `api` and `write_repository`)
|
|
34
|
+
- Willingness of all contributors to follow the commit syntax above
|
|
35
|
+
|
|
36
|
+
## Usage
|
|
37
|
+
|
|
38
|
+
- In your `.gitlab-ci.yml`, define the stages explicitly and add a `release` stage at the end of the list. This ensures that the release runs only on a (to this point) successful pipeline.
|
|
39
|
+
```yaml
|
|
40
|
+
stages:
|
|
41
|
+
- build
|
|
42
|
+
- test
|
|
43
|
+
- deploy
|
|
44
|
+
- release
|
|
45
|
+
```
|
|
46
|
+
- Then add the following job and replace `main` with the desired version from the [releases](https://gitlab.com/omnitoolkit/omnitoolkit/-/releases) page:
|
|
47
|
+
```yaml
|
|
48
|
+
release_version:
|
|
49
|
+
image: registry.gitlab.com/omnitoolkit/omnitoolkit/releasebot:main
|
|
50
|
+
stage: release
|
|
51
|
+
rules:
|
|
52
|
+
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
|
|
53
|
+
script:
|
|
54
|
+
- releasebot --branches ${CI_DEFAULT_BRANCH}
|
|
55
|
+
```
|
|
56
|
+
- If `CI_DEFAULT_BRANCH` is not your release branch, replace it with the correct one.
|
|
57
|
+
- If you don't want to release on every push to the release branch, add `when: manual` to the job. You can now start the job on demand from the UI.
|
package/bin/releasebot
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
{
|
|
2
|
+
"bin": {
|
|
3
|
+
"releasebot": "./bin/releasebot"
|
|
4
|
+
},
|
|
5
|
+
"dependencies": {
|
|
6
|
+
"@semantic-release/changelog": "6.0.3",
|
|
7
|
+
"@semantic-release/commit-analyzer": "13.0.1",
|
|
8
|
+
"@semantic-release/exec": "7.1.0",
|
|
9
|
+
"@semantic-release/git": "10.0.1",
|
|
10
|
+
"@semantic-release/gitlab": "13.3.2",
|
|
11
|
+
"@semantic-release/release-notes-generator": "14.1.0",
|
|
12
|
+
"conventional-changelog-conventionalcommits": "9.3.1",
|
|
13
|
+
"semantic-release": "25.0.3"
|
|
14
|
+
},
|
|
15
|
+
"description": "Opinionated GitLab semantic-release CLI.",
|
|
16
|
+
"files": [
|
|
17
|
+
"bin/releasebot",
|
|
18
|
+
"src/cli.js",
|
|
19
|
+
"src/constants.js",
|
|
20
|
+
"src/index.js"
|
|
21
|
+
],
|
|
22
|
+
"homepage": "https://gitlab.com/omnitoolkit/omnitoolkit/-/tree/main/apps/releasebot#readme",
|
|
23
|
+
"license": "Apache-2.0",
|
|
24
|
+
"name": "@omnitoolkit/releasebot",
|
|
25
|
+
"publishConfig": {
|
|
26
|
+
"access": "public"
|
|
27
|
+
},
|
|
28
|
+
"repository": {
|
|
29
|
+
"directory": "apps/releasebot",
|
|
30
|
+
"type": "git",
|
|
31
|
+
"url": "git+https://gitlab.com/omnitoolkit/omnitoolkit.git"
|
|
32
|
+
},
|
|
33
|
+
"scripts": {
|
|
34
|
+
"test": "node --test"
|
|
35
|
+
},
|
|
36
|
+
"version": "7.3.1"
|
|
37
|
+
}
|
package/src/cli.js
ADDED
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
"use strict";
|
|
4
|
+
|
|
5
|
+
const fs = require("node:fs/promises");
|
|
6
|
+
const path = require("node:path");
|
|
7
|
+
const { execFile: execFileCallback, spawn: spawnCallback } = require("node:child_process");
|
|
8
|
+
const { promisify } = require("node:util");
|
|
9
|
+
|
|
10
|
+
const defaultExecFile = promisify(execFileCallback);
|
|
11
|
+
const defaultConfigPath = path.join(__dirname, "index.js");
|
|
12
|
+
|
|
13
|
+
function inferGitLabUrl({ env, remoteUrl }) {
|
|
14
|
+
if (env.CI_SERVER_URL) {
|
|
15
|
+
return env.CI_SERVER_URL;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const sshMatch = remoteUrl.match(/^[^@]+@([^:]+):/);
|
|
19
|
+
|
|
20
|
+
if (sshMatch) {
|
|
21
|
+
return `https://${sshMatch[1]}`;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
return new URL(remoteUrl).origin;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
async function gitOutput(execFile, args) {
|
|
28
|
+
const result = await execFile("git", args, { encoding: "utf8" });
|
|
29
|
+
return result.stdout.trim();
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
async function readGitMetadata(execFile) {
|
|
33
|
+
const remote = await gitOutput(execFile, ["remote", "get-url", "origin"]);
|
|
34
|
+
const branch = await gitOutput(execFile, [
|
|
35
|
+
"rev-parse",
|
|
36
|
+
"--symbolic-full-name",
|
|
37
|
+
"--abbrev-ref",
|
|
38
|
+
"HEAD"
|
|
39
|
+
]);
|
|
40
|
+
const commit = await gitOutput(execFile, ["rev-parse", "--short=8", "HEAD"]);
|
|
41
|
+
|
|
42
|
+
if (!remote || !branch || !commit) {
|
|
43
|
+
throw new Error("missing git metadata");
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return {
|
|
47
|
+
branch,
|
|
48
|
+
commit,
|
|
49
|
+
remote
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
async function fetchGitLabUser({ fetchImpl, gitlabUrl, token }) {
|
|
54
|
+
const response = await fetchImpl(`${gitlabUrl}/api/v4/user`, {
|
|
55
|
+
headers: {
|
|
56
|
+
"PRIVATE-TOKEN": token
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
const user = await response.json();
|
|
60
|
+
const email = user.commit_email || "";
|
|
61
|
+
const name = user.name || "";
|
|
62
|
+
|
|
63
|
+
if (!email || !name) {
|
|
64
|
+
throw new Error("missing GitLab user identity");
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
return {
|
|
68
|
+
email,
|
|
69
|
+
name
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function resolveSemanticReleaseBin() {
|
|
74
|
+
return require.resolve("semantic-release/bin/semantic-release.js");
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function nodePathEnv(existingNodePath) {
|
|
78
|
+
const paths = module.paths.join(path.delimiter);
|
|
79
|
+
|
|
80
|
+
if (!existingNodePath) {
|
|
81
|
+
return paths;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
return `${paths}${path.delimiter}${existingNodePath}`;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function indent(text) {
|
|
88
|
+
return text
|
|
89
|
+
.trimEnd()
|
|
90
|
+
.split("\n")
|
|
91
|
+
.map((line) => ` ${line}`)
|
|
92
|
+
.join("\n");
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function writeStartupSummary({ argv, configText, env, gitMetadata, stdout }) {
|
|
96
|
+
const extraParameters = argv.length > 0 ? argv.join(" ") : "NONE";
|
|
97
|
+
|
|
98
|
+
stdout.write("\n");
|
|
99
|
+
stdout.write("++++++++++++++++++++++++++++++++++++++++\n");
|
|
100
|
+
stdout.write("\n");
|
|
101
|
+
stdout.write("starting sematic-release on git repository\n");
|
|
102
|
+
stdout.write("\n");
|
|
103
|
+
stdout.write(` remote: ${gitMetadata.remote}\n`);
|
|
104
|
+
stdout.write(` branch: ${gitMetadata.branch}\n`);
|
|
105
|
+
stdout.write(` commit: ${gitMetadata.commit}\n`);
|
|
106
|
+
stdout.write("\n");
|
|
107
|
+
stdout.write("with env vars\n");
|
|
108
|
+
stdout.write("\n");
|
|
109
|
+
stdout.write(" GITLAB_TOKEN = [MASKED]\n");
|
|
110
|
+
stdout.write(` GITLAB_URL = ${env.GITLAB_URL}\n`);
|
|
111
|
+
stdout.write(` GIT_AUTHOR_EMAIL = ${env.GIT_AUTHOR_EMAIL}\n`);
|
|
112
|
+
stdout.write(` GIT_AUTHOR_NAME = ${env.GIT_AUTHOR_NAME}\n`);
|
|
113
|
+
stdout.write(` GIT_COMMITTER_EMAIL = ${env.GIT_COMMITTER_EMAIL}\n`);
|
|
114
|
+
stdout.write(` GIT_COMMITTER_NAME = ${env.GIT_COMMITTER_NAME}\n`);
|
|
115
|
+
stdout.write("\n");
|
|
116
|
+
stdout.write("with config\n");
|
|
117
|
+
stdout.write("\n");
|
|
118
|
+
stdout.write(`${indent(configText)}\n`);
|
|
119
|
+
stdout.write("\n");
|
|
120
|
+
stdout.write("with extra parameters\n");
|
|
121
|
+
stdout.write("\n");
|
|
122
|
+
stdout.write(`${indent(extraParameters)}\n`);
|
|
123
|
+
stdout.write("\n");
|
|
124
|
+
stdout.write("++++++++++++++++++++++++++++++++++++++++\n");
|
|
125
|
+
stdout.write("\n");
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function spawnProcess(command, args, options) {
|
|
129
|
+
return new Promise((resolve, reject) => {
|
|
130
|
+
const child = spawnCallback(command, args, {
|
|
131
|
+
...options,
|
|
132
|
+
stdio: "inherit"
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
child.on("error", reject);
|
|
136
|
+
child.on("close", (exitCode) => {
|
|
137
|
+
resolve({ exitCode: exitCode ?? 1 });
|
|
138
|
+
});
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
async function runReleasebot(options = {}) {
|
|
143
|
+
const argv = options.argv || [];
|
|
144
|
+
const configPath = options.configPath || defaultConfigPath;
|
|
145
|
+
const env = options.env || process.env;
|
|
146
|
+
const execFile = options.execFile || defaultExecFile;
|
|
147
|
+
const fetchImpl = options.fetch || globalThis.fetch;
|
|
148
|
+
const readFile = options.readFile || fs.readFile;
|
|
149
|
+
const spawn = options.spawn || spawnProcess;
|
|
150
|
+
const stderr = options.stderr || process.stderr;
|
|
151
|
+
const stdout = options.stdout || process.stdout;
|
|
152
|
+
|
|
153
|
+
if (!env.GITLAB_TOKEN) {
|
|
154
|
+
stderr.write("error - GITLAB_TOKEN not found in env vars\n");
|
|
155
|
+
return 1;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
let gitMetadata;
|
|
159
|
+
|
|
160
|
+
try {
|
|
161
|
+
gitMetadata = await readGitMetadata(execFile);
|
|
162
|
+
} catch (_error) {
|
|
163
|
+
stderr.write("error - could not interact with git - are you not inside a git repository?\n");
|
|
164
|
+
return 1;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
const gitlabUrl = inferGitLabUrl({
|
|
168
|
+
env,
|
|
169
|
+
remoteUrl: gitMetadata.remote
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
let gitLabUser;
|
|
173
|
+
|
|
174
|
+
try {
|
|
175
|
+
gitLabUser = await fetchGitLabUser({
|
|
176
|
+
fetchImpl,
|
|
177
|
+
gitlabUrl,
|
|
178
|
+
token: env.GITLAB_TOKEN
|
|
179
|
+
});
|
|
180
|
+
} catch (_error) {
|
|
181
|
+
stderr.write("error - could not get author email and name from gitlab - your GITLAB_TOKEN might be broken\n");
|
|
182
|
+
return 1;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
const releaseEnv = {
|
|
186
|
+
...env,
|
|
187
|
+
GITLAB_URL: gitlabUrl,
|
|
188
|
+
GIT_AUTHOR_EMAIL: gitLabUser.email,
|
|
189
|
+
GIT_AUTHOR_NAME: gitLabUser.name,
|
|
190
|
+
GIT_COMMITTER_EMAIL: gitLabUser.email,
|
|
191
|
+
GIT_COMMITTER_NAME: gitLabUser.name,
|
|
192
|
+
NODE_PATH: nodePathEnv(env.NODE_PATH)
|
|
193
|
+
};
|
|
194
|
+
const configText = await readFile(configPath, "utf8");
|
|
195
|
+
|
|
196
|
+
writeStartupSummary({
|
|
197
|
+
argv,
|
|
198
|
+
configText,
|
|
199
|
+
env: releaseEnv,
|
|
200
|
+
gitMetadata,
|
|
201
|
+
stdout
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
const result = await spawn(
|
|
205
|
+
process.execPath,
|
|
206
|
+
[options.semanticReleaseBin || resolveSemanticReleaseBin(), "--extends", configPath, ...argv],
|
|
207
|
+
{
|
|
208
|
+
env: releaseEnv
|
|
209
|
+
}
|
|
210
|
+
);
|
|
211
|
+
|
|
212
|
+
if (typeof result === "number") {
|
|
213
|
+
return result;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
return result.exitCode ?? 1;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
async function main() {
|
|
220
|
+
process.exitCode = await runReleasebot({
|
|
221
|
+
argv: process.argv.slice(2),
|
|
222
|
+
env: process.env,
|
|
223
|
+
stdout: process.stdout,
|
|
224
|
+
stderr: process.stderr
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
if (require.main === module) {
|
|
229
|
+
main().catch((error) => {
|
|
230
|
+
process.stderr.write(`${error.message}\n`);
|
|
231
|
+
process.exitCode = 1;
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
module.exports = {
|
|
236
|
+
fetchGitLabUser,
|
|
237
|
+
inferGitLabUrl,
|
|
238
|
+
main,
|
|
239
|
+
readGitMetadata,
|
|
240
|
+
resolveSemanticReleaseBin,
|
|
241
|
+
runReleasebot
|
|
242
|
+
};
|
package/src/constants.js
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
// In order to match the custom releaseRules, the file constants.js is replaced.
|
|
2
|
+
export const DEFAULT_COMMIT_TYPES = Object.freeze([
|
|
3
|
+
{
|
|
4
|
+
type: 'feat',
|
|
5
|
+
section: 'Features'
|
|
6
|
+
},
|
|
7
|
+
{
|
|
8
|
+
type: 'fix',
|
|
9
|
+
section: 'Bug Fixes'
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
type: 'perf',
|
|
13
|
+
section: 'Performance Improvements'
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
type: 'revert',
|
|
17
|
+
section: 'Reverts'
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
type: 'docs',
|
|
21
|
+
section: 'Documentation',
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
type: 'style',
|
|
25
|
+
section: 'Styles',
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
type: 'chore',
|
|
29
|
+
section: 'Miscellaneous Chores',
|
|
30
|
+
hidden: true
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
type: 'refactor',
|
|
34
|
+
section: 'Code Refactoring',
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
type: 'test',
|
|
38
|
+
section: 'Tests',
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
type: 'build',
|
|
42
|
+
section: 'Build System',
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
type: 'ci',
|
|
46
|
+
section: 'Continuous Integration',
|
|
47
|
+
}
|
|
48
|
+
].map(Object.freeze))
|
package/src/index.js
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
module.exports = {
|
|
2
|
+
branches: [
|
|
3
|
+
"main"
|
|
4
|
+
],
|
|
5
|
+
ci: false,
|
|
6
|
+
plugins: [
|
|
7
|
+
[
|
|
8
|
+
"@semantic-release/commit-analyzer",
|
|
9
|
+
{
|
|
10
|
+
preset: "conventionalcommits",
|
|
11
|
+
releaseRules: [
|
|
12
|
+
{ breaking: true, release: "major" },
|
|
13
|
+
{ type: "feat", release: "minor" },
|
|
14
|
+
{ revert: true, release: "patch" },
|
|
15
|
+
{ type: "build", release: "patch" },
|
|
16
|
+
{ type: "ci", release: "patch" },
|
|
17
|
+
{ type: "docs", release: "patch" },
|
|
18
|
+
{ type: "fix", release: "patch" },
|
|
19
|
+
{ type: "perf", release: "patch" },
|
|
20
|
+
{ type: "refactor", release: "patch" },
|
|
21
|
+
{ type: "revert", release: "patch" },
|
|
22
|
+
{ type: "style", release: "patch" },
|
|
23
|
+
{ type: "test", release: "patch" },
|
|
24
|
+
{ type: "chore", release: false }
|
|
25
|
+
]
|
|
26
|
+
}
|
|
27
|
+
],
|
|
28
|
+
[
|
|
29
|
+
// In order to match the custom releaseRules, the file constants.js is replaced.
|
|
30
|
+
"@semantic-release/release-notes-generator",
|
|
31
|
+
{
|
|
32
|
+
preset: "conventionalcommits"
|
|
33
|
+
}
|
|
34
|
+
],
|
|
35
|
+
[
|
|
36
|
+
"@semantic-release/changelog",
|
|
37
|
+
{
|
|
38
|
+
changelogFile: "CHANGELOG.md"
|
|
39
|
+
}
|
|
40
|
+
],
|
|
41
|
+
[
|
|
42
|
+
"@semantic-release/exec",
|
|
43
|
+
{
|
|
44
|
+
prepareCmd: "if [ -f VERSION ]; then echo ${nextRelease.version} > VERSION; fi; if [ -x version.sh ]; then ./version.sh ${nextRelease.version}; fi"
|
|
45
|
+
}
|
|
46
|
+
],
|
|
47
|
+
[
|
|
48
|
+
"@semantic-release/git",
|
|
49
|
+
{
|
|
50
|
+
assets: "**",
|
|
51
|
+
message: "chore(release): ${nextRelease.version}"
|
|
52
|
+
}
|
|
53
|
+
],
|
|
54
|
+
[
|
|
55
|
+
"@semantic-release/gitlab",
|
|
56
|
+
{
|
|
57
|
+
failCommentCondition: false,
|
|
58
|
+
failTitle: false,
|
|
59
|
+
labels: false,
|
|
60
|
+
successCommentCondition: false
|
|
61
|
+
}
|
|
62
|
+
]
|
|
63
|
+
]
|
|
64
|
+
}
|