Skip to content

Commit a86ff5d

Browse files
committed
feat: create changelog file with dedicated plugin
BREAKING CHANGE: The `changelog` options has been removed. The `CHANGELOG.md` is not created or updated anymore. Use https://github.com/semantic-release/changelog to create/update the `CHANGELOG.md`. By default if a `CHANGELOG.md` file exists and has been modified it will be included in the release commit.
1 parent ddaf44c commit a86ff5d

File tree

7 files changed

+102
-182
lines changed

7 files changed

+102
-182
lines changed

README.md

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ Determine the Git tag and version of the last tagged release.
1616

1717
## publish
1818

19-
Update the `CHANGELOG.md` file and publish a release commit, optionnaly including addtional files.
19+
Publish a release commit, including configurable files.
2020

2121
## Configuration
2222

@@ -32,7 +32,7 @@ Using the `GIT_CREDENTIALS` environment variable is the recommended configuratio
3232

3333
`GIT_CREDENTIALS` can be your Git username and passort in the format `<username>:<password>` or a token for certain Git providers like [Github](https://help.github.com/articles/creating-a-personal-access-token-for-the-command-line/), [Bitbucket](https://confluence.atlassian.com/bitbucketserver/personal-access-tokens-939515499.html) or [Gitlab](https://docs.gitlab.com/ce/user/profile/personal_access_tokens.html).
3434

35-
If the `GH_TOKEN` or `GITHUB_TOKEN` environment variables are defined their value will be used as a replacement for `GIT_CREDENTIALS`.
35+
If the `GH_TOKEN` or `GITHUB_TOKEN` environment variables are defined their value will be used as a replacement for `GIT_CREDENTIALS`.
3636

3737
### Environment variables
3838

@@ -46,7 +46,6 @@ If the `GH_TOKEN` or `GITHUB_TOKEN` environment variables are defined their valu
4646

4747
| Options | Description | Default |
4848
| -------------- | -------------------------------------------------------------- | --------------------------------------------------------------------------- |
49-
| `changelog` | Whether to create/update the `CHANGELOG.md` file. | `true` |
5049
| `message` | The message for the release commit. See [message](#message). | `chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}` |
5150
| `assets` | Files to include in the release commit. See [assets](#assets). | `["package.json", "npm-shrinkwrap.json"]` |
5251

@@ -113,18 +112,19 @@ Options can be set within the plugin definition in the `semantic-release` config
113112
}
114113
```
115114

116-
When using with the [npm](https://github.com/semantic-release/npm) plugin or the [github](https://github.com/semantic-release/github) plugin:
117-
- The [npm](https://github.com/semantic-release/npm) plugin must be called first in order to update the `package.json` file so the [git](https://github.com/semantic-release/git) plugin can include it in the release commit.
115+
When using with the [changelog](https://github.com/semantic-release/changelog), [npm](https://github.com/semantic-release/npm) or [github](https://github.com/semantic-release/github) plugins:
116+
- The [changelog](https://github.com/semantic-release/changelog) plugin must be called first in order to update the changelog file so the [git](https://github.com/semantic-release/git) and [npm](https://github.com/semantic-release/npm) plugin can include it in the release.
117+
- The [npm](https://github.com/semantic-release/npm) plugin must be called second in order to update the `package.json` file so the [git](https://github.com/semantic-release/git) plugin can include it in the release commit.
118118
- The [github](https://github.com/semantic-release/github) plugin must be called last to create a [Github Release](https://help.github.com/articles/about-releases/) that reference the tag created by the [git](https://github.com/semantic-release/git) plugin.
119119

120-
To use with [github](https://github.com/semantic-release/github), [npm](https://github.com/semantic-release/npm) and [condition-travis](https://github.com/semantic-release/condition-travis):
120+
To use with the [changelog](https://github.com/semantic-release/changelog), [github](https://github.com/semantic-release/github), [npm](https://github.com/semantic-release/npm) and [condition-travis](https://github.com/semantic-release/condition-travis) plugins:
121121

122122
```json
123123
{
124124
"release": {
125-
"verifyConditions": ["@semantic-release/condition-travis", "@semantic-release/npm", "@semantic-release/git", "@semantic-release/github"],
125+
"verifyConditions": ["@semantic-release/condition-travis", "@semantic-release/changelog", "@semantic-release/npm", "@semantic-release/git", "@semantic-release/github"],
126126
"getLastRelease": "@semantic-release/npm",
127-
"publish": ["@semantic-release/npm", "@semantic-release/git", "@semantic-release/github"]
127+
"publish": ["@semantic-release/changelog", "@semantic-release/npm", "@semantic-release/git", "@semantic-release/github"]
128128
}
129129
}
130130
```
@@ -330,7 +330,7 @@ $ travis login
330330
Add the [environment](https://github.com/travis-ci/travis.rb#env) variable `SSH_PASSPHRASE` to Travis with the value set during the [SSH keys generation](#generate-the-ssh-keys) step:
331331

332332
```bash
333-
$ travis env set SSH_PASSPHRASE <ssh_passphrase>
333+
$ travis env set SSH_PASSPHRASE <ssh_passphrase>
334334
```
335335

336336
[Encrypt](https://github.com/travis-ci/travis.rb#encrypt) the `git_deploy_key` (private key) using a symmetric encryption (AES-256), and store the secret in a secure environment variable in the Travis environment:

lib/publish.js

Lines changed: 7 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
const {readFile, writeFile, ensureFile, pathExists} = require('fs-extra');
1+
const {pathExists} = require('fs-extra');
22
const {isUndefined, isPlainObject, isArray} = require('lodash');
33
const {template, castArray, uniq} = require('lodash');
44
const micromatch = require('micromatch');
@@ -14,14 +14,13 @@ const PKG_JSON = 'package.json';
1414
const SKW_JSON = 'npm-shrinkwrap.json';
1515

1616
/**
17-
* Update the `CHANGELOG.md` file and publish a release commit optionnaly including addtional files.
17+
* Publish a release commit including configurable files.
1818
*
1919
* @param {Object} pluginConfig The plugin configuration.
2020
* @param {String|Array<String>} [pluginConfig.assets] Files to include in the release commit. Can be files path or globs.
2121
* @param {String} [pluginConfig.message] The message for the release commit.
2222
* @param {String} [pluginConfig.gitUserName] The username to use for commiting (git `user.name` config).
2323
* @param {String} [pluginConfig.gitUserEmail] The email to use for commiting (git `user.email` config).
24-
* @param {String} [pluginConfig.changelog] If `false` do not include the `CHANGELOG.md`.
2524
* @param {Object} options `semantic-release` configuration.
2625
* @param {String} options.repositoryUrl The remote git repository URL.
2726
* @param {String} options.branch The remote branch to publish to.
@@ -37,23 +36,14 @@ const SKW_JSON = 'npm-shrinkwrap.json';
3736
* @param {Object} logger Global logger.
3837
*/
3938
module.exports = async (pluginConfig, {branch, repositoryUrl}, lastRelease, nextRelease, logger) => {
40-
const {gitCredentials, gitUserEmail, gitUserName, changelog, message, assets} = resolveConfig(pluginConfig);
39+
const {gitCredentials, gitUserEmail, gitUserName, message, assets} = resolveConfig(pluginConfig);
4140
const patterns = [];
42-
if (changelog !== false && nextRelease.notes) {
43-
await ensureFile(CHANGELOG);
44-
const changelogFile = (await readFile(CHANGELOG)).toString().trim();
45-
if (changelogFile) {
46-
logger.log('Update %s', CHANGELOG);
47-
} else {
48-
logger.log('Create %s', CHANGELOG);
49-
}
50-
await writeFile(CHANGELOG, `${nextRelease.notes.trim()}\n${changelogFile ? `\n${changelogFile}\n` : ''}`);
41+
const modifiedFiles = await getModifiedFiles();
42+
43+
if (isUndefined(assets) && (await pathExists(CHANGELOG))) {
5144
logger.log('Add %s to the release commit', CHANGELOG);
5245
patterns.push(CHANGELOG);
5346
}
54-
55-
const modifiedFiles = await getModifiedFiles();
56-
5747
if (isUndefined(assets) && (await pathExists(PKG_JSON))) {
5848
logger.log('Add %s to the release commit', PKG_JSON);
5949
patterns.push(PKG_JSON);
@@ -106,5 +96,5 @@ module.exports = async (pluginConfig, {branch, repositoryUrl}, lastRelease, next
10696
logger.log('Creating tag %s', nextRelease.gitTag);
10797
await tag(nextRelease.gitTag);
10898
await push(url, branch);
109-
logger.log('Published Github release: %s', nextRelease.gitTag);
99+
logger.log('Published Git release: %s', nextRelease.gitTag);
110100
};

lib/resolve-config.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
const {castArray} = require('lodash');
22

3-
module.exports = ({changelog, message, assets, githubToken}) => ({
3+
module.exports = ({message, assets, githubToken}) => ({
44
gitCredentials: process.env.GIT_CREDENTIALS || githubToken || process.env.GH_TOKEN || process.env.GITHUB_TOKEN,
55
gitUserName: process.env.GIT_USERNAME || 'semantic-release-bot',
66
gitUserEmail: process.env.GIT_EMAIL || 'semantic-release-bot@martynus.net',
7-
changelog,
87
message,
98
assets: assets ? castArray(assets) : assets,
109
});

lib/verify.js

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
const {isString, isUndefined, isArray, isPlainObject, isBoolean} = require('lodash');
1+
const {isString, isUndefined, isArray, isPlainObject} = require('lodash');
22
const SemanticReleaseError = require('@semantic-release/error');
33
const resolveConfig = require('./resolve-config');
44
const getAuthUrl = require('./get-auth-url');
@@ -20,7 +20,7 @@ const {verifyAuth} = require('./git');
2020
*/
2121
module.exports = async (pluginConfig, {repositoryUrl, branch}, logger) => {
2222
logger.log('Verify authentication for repository %s', repositoryUrl);
23-
const {changelog, message, assets, gitCredentials} = resolveConfig(pluginConfig);
23+
const {message, assets, gitCredentials} = resolveConfig(pluginConfig);
2424

2525
if (
2626
!isUndefined(assets) &&
@@ -36,10 +36,6 @@ module.exports = async (pluginConfig, {repositoryUrl, branch}, logger) => {
3636
);
3737
}
3838

39-
if (!isUndefined(changelog) && !isBoolean(changelog)) {
40-
throw new SemanticReleaseError('The "changelog" options, if defined, must be a Boolean.', 'EINVALIDCHANGELOG');
41-
}
42-
4339
if (!isUndefined(message) && !(isString(message) && message.trim())) {
4440
throw new SemanticReleaseError('The "message" options, if defined, must be a non empty String.', 'EINVALIDMESSAGE');
4541
}

test/integration.test.js

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import {outputFile, readFile} from 'fs-extra';
1+
import {outputFile} from 'fs-extra';
22
import test from 'ava';
33
import {stub} from 'sinon';
44
import clearModule from 'clear-module';
@@ -156,7 +156,6 @@ test.serial('Publish from a shallow clone', async t => {
156156
const branch = 'master';
157157
// Create a remote repo, initialize it, create a local shallow clone and set the cwd to the clone
158158
const {repositoryUrl, authUrl} = await gitbox.createRepo('publish', branch);
159-
await outputFile('CHANGELOG.md', 'Version 1.0.0 changelog');
160159
await outputFile('package.json', "{name: 'test-package', version: '1.0.0'}");
161160
await outputFile('dist/file.js', 'Initial content');
162161
await outputFile('dist/file.css', 'Initial content');
@@ -176,8 +175,7 @@ test.serial('Publish from a shallow clone', async t => {
176175
};
177176
await t.context.m.publish(pluginConfig, {logger: t.context.logger, options: {repositoryUrl, branch}, nextRelease});
178177

179-
t.is((await readFile('CHANGELOG.md')).toString(), `${nextRelease.notes}\n\nVersion 1.0.0 changelog\n`);
180-
t.deepEqual(await gitCommitedFiles(), ['CHANGELOG.md', 'dist/file.js', 'package.json']);
178+
t.deepEqual(await gitCommitedFiles(), ['dist/file.js', 'package.json']);
181179
const commit = (await gitGetCommit())[0];
182180
t.is(commit.subject, `Release version ${nextRelease.version} from branch ${branch}`);
183181
t.is(commit.body, `${nextRelease.notes}\n`);
@@ -191,7 +189,6 @@ test.serial('Publish from a detached head repository', async t => {
191189
const branch = 'master';
192190
// Create a remote repo, initialize it, create a local shallow clone and set the cwd to the clone
193191
const {repositoryUrl, authUrl} = await gitbox.createRepo('publish-detached-head', branch);
194-
await outputFile('CHANGELOG.md', 'Version 1.0.0 changelog');
195192
await outputFile('package.json', "{name: 'test-package', version: '1.0.0'}");
196193
await outputFile('dist/file.js', 'Initial content');
197194
await outputFile('dist/file.css', 'Initial content');
@@ -211,8 +208,7 @@ test.serial('Publish from a detached head repository', async t => {
211208
};
212209
await t.context.m.publish(pluginConfig, {logger: t.context.logger, options: {repositoryUrl, branch}, nextRelease});
213210

214-
t.is((await readFile('CHANGELOG.md')).toString(), `${nextRelease.notes}\n\nVersion 1.0.0 changelog\n`);
215-
t.deepEqual(await gitCommitedFiles(), ['CHANGELOG.md', 'dist/file.js', 'package.json']);
211+
t.deepEqual(await gitCommitedFiles(), ['dist/file.js', 'package.json']);
216212
const commit = (await gitGetCommit())[0];
217213
t.is(commit.subject, `Release version ${nextRelease.version} from branch ${branch}`);
218214
t.is(commit.body, `${nextRelease.notes}\n`);
@@ -224,7 +220,7 @@ test.serial('Verify authentication only on the fist call', async t => {
224220
const branch = 'master';
225221
// Create a remote repo, initialize it, create a local shallow clone and set the cwd to the clone
226222
const {repositoryUrl} = await gitbox.createRepo('complete-release', branch);
227-
const nextRelease = {version: '2.0.0', gitTag: 'v2.0.0', notes: 'Version 2.0.0 changelog'};
223+
const nextRelease = {version: '2.0.0', gitTag: 'v2.0.0'};
228224

229225
await t.notThrows(t.context.m.verifyConditions({}, {logger: t.context.logger, options: {repositoryUrl, branch}}));
230226
t.falsy(await t.context.m.getLastRelease({}, {logger: t.context.logger, options: {repositoryUrl, branch}}));

0 commit comments

Comments
 (0)