Skip to content

Commit

Permalink
feat: ✨ add skipOnPrerelease config to not update changelog on prerel…
Browse files Browse the repository at this point in the history
…eases

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
  • Loading branch information
BerniWittmann committed Jan 23, 2023
1 parent 86c8d81 commit c556422
Show file tree
Hide file tree
Showing 8 changed files with 122 additions and 10 deletions.
11 changes: 6 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

| Step | Description |
| ------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `verifyConditions` | Verify the `changelogFile` and `changelogTitle` options configuration. |
| `verifyConditions` | Verify the `changelogFile`, `changelogTitle` and `skipOnPrerelease` options configuration. |
| `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). |

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

### Options

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

### Examples

Expand Down
6 changes: 6 additions & 0 deletions lib/definitions/errors.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,10 @@ Your configuration for the \`changelogFile\` option is \`${changelogFile}\`.`,
Your configuration for the \`changelogTitle\` option is \`${changelogTitle}\`.`,
}),
EINVALIDSKIPONPRERELEASE: ({skipOnPrerelease}) => ({
message: 'Invalid `skipOnPrerelease` option.',
details: `The [skipOnPrerelease option](${linkify('README.md#options')}) option, if defined, must be a \`Boolean\`.
Your configuration for the \`skipOnPrerelease\` option is \`${skipOnPrerelease}\`.`,
}),
};
11 changes: 9 additions & 2 deletions lib/prepare.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,17 @@ const path = require('path');
const {readFile, writeFile, ensureFile} = require('fs-extra');
const resolveConfig = require('./resolve-config.js');

module.exports = async (pluginConfig, {cwd, nextRelease: {notes}, logger}) => {
const {changelogFile, changelogTitle} = resolveConfig(pluginConfig);
const isPrerelease = ({type, main}) => type === 'prerelease' || (type === 'release' && !main);

module.exports = async (pluginConfig, {cwd, nextRelease: {notes}, logger, branch}) => {
const {changelogFile, changelogTitle, skipOnPrerelease} = resolveConfig(pluginConfig);
const changelogPath = path.resolve(cwd, changelogFile);

if (skipOnPrerelease && isPrerelease(branch)) {
logger.log('Skipping because branch is a prerelease branch and option skipOnPrerelease is active');
return;
}

if (notes) {
await ensureFile(changelogPath);
const currentFile = (await readFile(changelogPath)).toString().trim();
Expand Down
3 changes: 2 additions & 1 deletion lib/resolve-config.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
const {isNil} = require('lodash');

module.exports = ({changelogFile, changelogTitle}) => ({
module.exports = ({changelogFile, changelogTitle, skipOnPrerelease}) => ({
changelogFile: isNil(changelogFile) ? 'CHANGELOG.md' : changelogFile,
changelogTitle,
skipOnPrerelease: isNil(skipOnPrerelease) ? false : skipOnPrerelease,
});
3 changes: 2 additions & 1 deletion lib/verify.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
const {isString, isNil} = require('lodash');
const {isString, isNil, isBoolean} = require('lodash');
const AggregateError = require('aggregate-error');
const getError = require('./get-error.js');
const resolveConfig = require('./resolve-config.js');
Expand All @@ -8,6 +8,7 @@ const isNonEmptyString = (value) => isString(value) && value.trim();
const VALIDATORS = {
changelogFile: isNonEmptyString,
changelogTitle: isNonEmptyString,
skipOnPrerelease: isBoolean,
};

module.exports = (pluginConfig) => {
Expand Down
15 changes: 15 additions & 0 deletions test/integration.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,21 @@ test.serial('Skip changelog update if the release is empty', async (t) => {
t.is((await readFile(changelogPath)).toString(), 'Initial CHANGELOG');
});

test.serial('Skip changelog update if the release is a prerelease and skipOnPrerelease option is set', async (t) => {
const cwd = tempy.directory();
const changelogFile = 'CHANGELOG.txt';
const changelogPath = path.resolve(cwd, changelogFile);
await outputFile(changelogPath, 'Initial CHANGELOG');

await t.context.m.prepare(
{skipOnPrerelease: true},
{cwd, options: {}, nextRelease: {}, logger: t.context.logger, branch: {type: 'prerelease'}}
);

// Verify the content of the CHANGELOG.md
t.is((await readFile(changelogPath)).toString(), 'Initial CHANGELOG');
});

test.serial('Verify only on the fist call', async (t) => {
const cwd = tempy.directory();
const notes = 'Test release note';
Expand Down
75 changes: 74 additions & 1 deletion test/prepare.test.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
const path = require('path');
const test = require('ava');
const {outputFile, readFile} = require('fs-extra');
const {outputFile, readFile, pathExists} = require('fs-extra');
const {stub} = require('sinon');
const tempy = require('tempy');
const prepare = require('../lib/prepare.js');
Expand Down Expand Up @@ -90,3 +90,76 @@ test.serial('Create new changelog with title if specified', async (t) => {

t.is((await readFile(changelogPath)).toString(), `${changelogTitle}\n\n${notes}\n`);
});

test.serial('Skip creation of changelog if skipOnPrerelease is set on prerelease branches', async (t) => {
const cwd = tempy.directory();
const notes = 'Test release note';
const changelogFile = 'CHANGELOG.md';
const changelogPath = path.resolve(cwd, changelogFile);

await prepare(
{skipOnPrerelease: true},
{cwd, nextRelease: {notes}, branch: {type: 'prerelease', main: false}, logger: t.context.logger}
);

// Verify the content of the CHANGELOG.md
t.is(await pathExists(changelogPath), false);
t.deepEqual(t.context.log.args[0], [
'Skipping because branch is a prerelease branch and option skipOnPrerelease is active',
]);
});

test('Skip update of changelog if skipOnPrerelease is set on prerelease branches', async (t) => {
const cwd = tempy.directory();
const notes = 'Test release note';
const changelogFile = 'CHANGELOG.md';
const changelogPath = path.resolve(cwd, changelogFile);
await outputFile(changelogPath, 'Initial CHANGELOG');

await prepare(
{skipOnPrerelease: true},
{cwd, nextRelease: {notes}, branch: {type: 'prerelease', main: false}, logger: t.context.logger}
);

// Verify the content of the CHANGELOG.md
t.is((await readFile(changelogPath)).toString(), `Initial CHANGELOG`);
t.deepEqual(t.context.log.args[0], [
'Skipping because branch is a prerelease branch and option skipOnPrerelease is active',
]);
});

test('Skip update of changelog if skipOnPrerelease is set on release branches but it is not main', async (t) => {
const cwd = tempy.directory();
const notes = 'Test release note';
const changelogFile = 'CHANGELOG.md';
const changelogPath = path.resolve(cwd, changelogFile);
await outputFile(changelogPath, 'Initial CHANGELOG');

await prepare(
{skipOnPrerelease: true},
{cwd, nextRelease: {notes}, branch: {type: 'release', main: false}, logger: t.context.logger}
);

// Verify the content of the CHANGELOG.md
t.is((await readFile(changelogPath)).toString(), `Initial CHANGELOG`);
t.deepEqual(t.context.log.args[0], [
'Skipping because branch is a prerelease branch and option skipOnPrerelease is active',
]);
});

test('Ensure update of changelog if skipOnPrerelease is not set on prerelease branches', async (t) => {
const cwd = tempy.directory();
const notes = 'Test release note';
const changelogFile = 'CHANGELOG.md';
const changelogPath = path.resolve(cwd, changelogFile);
await outputFile(changelogPath, 'Initial CHANGELOG');

await prepare(
{skipOnPrerelease: false},
{cwd, nextRelease: {notes}, branch: {type: 'prerelease', main: false}, logger: t.context.logger}
);

// Verify the content of the CHANGELOG.md
t.is((await readFile(changelogPath)).toString(), `${notes}\n\nInitial CHANGELOG\n`);
t.deepEqual(t.context.log.args[0], ['Update %s', changelogPath]);
});
8 changes: 8 additions & 0 deletions test/verify.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,3 +57,11 @@ test('Throw SemanticReleaseError if "changelogTitle" option is a whitespace Stri
t.is(error.name, 'SemanticReleaseError');
t.is(error.code, 'EINVALIDCHANGELOGTITLE');
});

test('Throw SemanticReleaseError if "skipOnPrerelease" option is not a boolean', (t) => {
const skipOnPrerelease = 'wrong';
const [error] = t.throws(() => verify({skipOnPrerelease}));

t.is(error.name, 'SemanticReleaseError');
t.is(error.code, 'EINVALIDSKIPONPRERELEASE');
});

0 comments on commit c556422

Please sign in to comment.