Skip to content

Commit c556422

Browse files
committed
feat: ✨ add skipOnPrerelease config to not update changelog on prereleases
When working a lot with prereleases the changelog file can become quite bloated with the prereleases To provide easier overview one might only want to include normal releases in the changelog. That is why i added the skipOnPrerelease config flag which is false by default But if you turn it on it will prevent updates on prereleases
1 parent 86c8d81 commit c556422

File tree

8 files changed

+122
-10
lines changed

8 files changed

+122
-10
lines changed

README.md

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
| Step | Description |
99
| ------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
10-
| `verifyConditions` | Verify the `changelogFile` and `changelogTitle` options configuration. |
10+
| `verifyConditions` | Verify the `changelogFile`, `changelogTitle` and `skipOnPrerelease` options configuration. |
1111
| `prepare` | Create or update a changelog file in the local project directory with the changelog content created in the [generate notes step](https://github.com/semantic-release/semantic-release#release-steps). |
1212

1313
## Install
@@ -47,10 +47,11 @@ With this example, for each release, a `docs/CHANGELOG.md` will be created or up
4747

4848
### Options
4949

50-
| Options | Description | Default |
51-
| ---------------- | ----------------------------------------------------- | -------------- |
52-
| `changelogFile` | File path of the changelog. | `CHANGELOG.md` |
53-
| `changelogTitle` | Title of the changelog file (first line of the file). | - |
50+
| Options | Description | Default |
51+
| ------------------ | -------------------------------------------------------- | -------------- |
52+
| `changelogFile` | File path of the changelog. | `CHANGELOG.md` |
53+
| `changelogTitle` | Title of the changelog file (first line of the file). | - |
54+
| `skipOnPrerelease` | Skip changelog update when branch is a prerelease branch | `false` |
5455

5556
### Examples
5657

lib/definitions/errors.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,10 @@ Your configuration for the \`changelogFile\` option is \`${changelogFile}\`.`,
2020
2121
Your configuration for the \`changelogTitle\` option is \`${changelogTitle}\`.`,
2222
}),
23+
EINVALIDSKIPONPRERELEASE: ({skipOnPrerelease}) => ({
24+
message: 'Invalid `skipOnPrerelease` option.',
25+
details: `The [skipOnPrerelease option](${linkify('README.md#options')}) option, if defined, must be a \`Boolean\`.
26+
27+
Your configuration for the \`skipOnPrerelease\` option is \`${skipOnPrerelease}\`.`,
28+
}),
2329
};

lib/prepare.js

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,17 @@ const path = require('path');
22
const {readFile, writeFile, ensureFile} = require('fs-extra');
33
const resolveConfig = require('./resolve-config.js');
44

5-
module.exports = async (pluginConfig, {cwd, nextRelease: {notes}, logger}) => {
6-
const {changelogFile, changelogTitle} = resolveConfig(pluginConfig);
5+
const isPrerelease = ({type, main}) => type === 'prerelease' || (type === 'release' && !main);
6+
7+
module.exports = async (pluginConfig, {cwd, nextRelease: {notes}, logger, branch}) => {
8+
const {changelogFile, changelogTitle, skipOnPrerelease} = resolveConfig(pluginConfig);
79
const changelogPath = path.resolve(cwd, changelogFile);
810

11+
if (skipOnPrerelease && isPrerelease(branch)) {
12+
logger.log('Skipping because branch is a prerelease branch and option skipOnPrerelease is active');
13+
return;
14+
}
15+
916
if (notes) {
1017
await ensureFile(changelogPath);
1118
const currentFile = (await readFile(changelogPath)).toString().trim();

lib/resolve-config.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
const {isNil} = require('lodash');
22

3-
module.exports = ({changelogFile, changelogTitle}) => ({
3+
module.exports = ({changelogFile, changelogTitle, skipOnPrerelease}) => ({
44
changelogFile: isNil(changelogFile) ? 'CHANGELOG.md' : changelogFile,
55
changelogTitle,
6+
skipOnPrerelease: isNil(skipOnPrerelease) ? false : skipOnPrerelease,
67
});

lib/verify.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
const {isString, isNil} = require('lodash');
1+
const {isString, isNil, isBoolean} = require('lodash');
22
const AggregateError = require('aggregate-error');
33
const getError = require('./get-error.js');
44
const resolveConfig = require('./resolve-config.js');
@@ -8,6 +8,7 @@ const isNonEmptyString = (value) => isString(value) && value.trim();
88
const VALIDATORS = {
99
changelogFile: isNonEmptyString,
1010
changelogTitle: isNonEmptyString,
11+
skipOnPrerelease: isBoolean,
1112
};
1213

1314
module.exports = (pluginConfig) => {

test/integration.test.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,21 @@ test.serial('Skip changelog update if the release is empty', async (t) => {
4848
t.is((await readFile(changelogPath)).toString(), 'Initial CHANGELOG');
4949
});
5050

51+
test.serial('Skip changelog update if the release is a prerelease and skipOnPrerelease option is set', async (t) => {
52+
const cwd = tempy.directory();
53+
const changelogFile = 'CHANGELOG.txt';
54+
const changelogPath = path.resolve(cwd, changelogFile);
55+
await outputFile(changelogPath, 'Initial CHANGELOG');
56+
57+
await t.context.m.prepare(
58+
{skipOnPrerelease: true},
59+
{cwd, options: {}, nextRelease: {}, logger: t.context.logger, branch: {type: 'prerelease'}}
60+
);
61+
62+
// Verify the content of the CHANGELOG.md
63+
t.is((await readFile(changelogPath)).toString(), 'Initial CHANGELOG');
64+
});
65+
5166
test.serial('Verify only on the fist call', async (t) => {
5267
const cwd = tempy.directory();
5368
const notes = 'Test release note';

test/prepare.test.js

Lines changed: 74 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
const path = require('path');
22
const test = require('ava');
3-
const {outputFile, readFile} = require('fs-extra');
3+
const {outputFile, readFile, pathExists} = require('fs-extra');
44
const {stub} = require('sinon');
55
const tempy = require('tempy');
66
const prepare = require('../lib/prepare.js');
@@ -90,3 +90,76 @@ test.serial('Create new changelog with title if specified', async (t) => {
9090

9191
t.is((await readFile(changelogPath)).toString(), `${changelogTitle}\n\n${notes}\n`);
9292
});
93+
94+
test.serial('Skip creation of changelog if skipOnPrerelease is set on prerelease branches', async (t) => {
95+
const cwd = tempy.directory();
96+
const notes = 'Test release note';
97+
const changelogFile = 'CHANGELOG.md';
98+
const changelogPath = path.resolve(cwd, changelogFile);
99+
100+
await prepare(
101+
{skipOnPrerelease: true},
102+
{cwd, nextRelease: {notes}, branch: {type: 'prerelease', main: false}, logger: t.context.logger}
103+
);
104+
105+
// Verify the content of the CHANGELOG.md
106+
t.is(await pathExists(changelogPath), false);
107+
t.deepEqual(t.context.log.args[0], [
108+
'Skipping because branch is a prerelease branch and option skipOnPrerelease is active',
109+
]);
110+
});
111+
112+
test('Skip update of changelog if skipOnPrerelease is set on prerelease branches', async (t) => {
113+
const cwd = tempy.directory();
114+
const notes = 'Test release note';
115+
const changelogFile = 'CHANGELOG.md';
116+
const changelogPath = path.resolve(cwd, changelogFile);
117+
await outputFile(changelogPath, 'Initial CHANGELOG');
118+
119+
await prepare(
120+
{skipOnPrerelease: true},
121+
{cwd, nextRelease: {notes}, branch: {type: 'prerelease', main: false}, logger: t.context.logger}
122+
);
123+
124+
// Verify the content of the CHANGELOG.md
125+
t.is((await readFile(changelogPath)).toString(), `Initial CHANGELOG`);
126+
t.deepEqual(t.context.log.args[0], [
127+
'Skipping because branch is a prerelease branch and option skipOnPrerelease is active',
128+
]);
129+
});
130+
131+
test('Skip update of changelog if skipOnPrerelease is set on release branches but it is not main', async (t) => {
132+
const cwd = tempy.directory();
133+
const notes = 'Test release note';
134+
const changelogFile = 'CHANGELOG.md';
135+
const changelogPath = path.resolve(cwd, changelogFile);
136+
await outputFile(changelogPath, 'Initial CHANGELOG');
137+
138+
await prepare(
139+
{skipOnPrerelease: true},
140+
{cwd, nextRelease: {notes}, branch: {type: 'release', main: false}, logger: t.context.logger}
141+
);
142+
143+
// Verify the content of the CHANGELOG.md
144+
t.is((await readFile(changelogPath)).toString(), `Initial CHANGELOG`);
145+
t.deepEqual(t.context.log.args[0], [
146+
'Skipping because branch is a prerelease branch and option skipOnPrerelease is active',
147+
]);
148+
});
149+
150+
test('Ensure update of changelog if skipOnPrerelease is not set on prerelease branches', async (t) => {
151+
const cwd = tempy.directory();
152+
const notes = 'Test release note';
153+
const changelogFile = 'CHANGELOG.md';
154+
const changelogPath = path.resolve(cwd, changelogFile);
155+
await outputFile(changelogPath, 'Initial CHANGELOG');
156+
157+
await prepare(
158+
{skipOnPrerelease: false},
159+
{cwd, nextRelease: {notes}, branch: {type: 'prerelease', main: false}, logger: t.context.logger}
160+
);
161+
162+
// Verify the content of the CHANGELOG.md
163+
t.is((await readFile(changelogPath)).toString(), `${notes}\n\nInitial CHANGELOG\n`);
164+
t.deepEqual(t.context.log.args[0], ['Update %s', changelogPath]);
165+
});

test/verify.test.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,3 +57,11 @@ test('Throw SemanticReleaseError if "changelogTitle" option is a whitespace Stri
5757
t.is(error.name, 'SemanticReleaseError');
5858
t.is(error.code, 'EINVALIDCHANGELOGTITLE');
5959
});
60+
61+
test('Throw SemanticReleaseError if "skipOnPrerelease" option is not a boolean', (t) => {
62+
const skipOnPrerelease = 'wrong';
63+
const [error] = t.throws(() => verify({skipOnPrerelease}));
64+
65+
t.is(error.name, 'SemanticReleaseError');
66+
t.is(error.code, 'EINVALIDSKIPONPRERELEASE');
67+
});

0 commit comments

Comments
 (0)