Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: use conventionalcommits as the default preset #1836

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ This removes the immediate connection between human emotions and version numbers
**semantic-release** uses the commit messages to determine the consumer impact of changes in the codebase.
Following formalized conventions for commit messages, **semantic-release** automatically determines the next [semantic version](https://semver.org) number, generates a changelog and publishes the release.

By default, **semantic-release** uses [Angular Commit Message Conventions](https://github.com/angular/angular/blob/master/CONTRIBUTING.md#-commit-message-format).
By default **semantic-release** uses the [Conventional Commits convention](https://www.conventionalcommits.org/).
The commit message format can be changed with the [`preset` or `config` options](docs/usage/configuration.md#options) of the [@semantic-release/commit-analyzer](https://github.com/semantic-release/commit-analyzer#options) and [@semantic-release/release-notes-generator](https://github.com/semantic-release/release-notes-generator#options) plugins.

Tools such as [commitizen](https://github.com/commitizen/cz-cli) or [commitlint](https://github.com/conventional-changelog/commitlint) can be used to help contributors and enforce valid commit messages.
Expand Down
1 change: 1 addition & 0 deletions cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ Usage:
.option('r', {alias: 'repository-url', describe: 'Git repository URL', type: 'string', group: 'Options'})
.option('t', {alias: 'tag-format', describe: 'Git tag format', type: 'string', group: 'Options'})
.option('p', {alias: 'plugins', describe: 'Plugins', ...stringList, group: 'Options'})
.option('preset', {describe: 'Commit message format convention', type: 'string', group: 'Options'})
.option('e', {alias: 'extends', describe: 'Shareable configurations', ...stringList, group: 'Options'})
.option('ci', {describe: 'Toggle CI verifications', type: 'boolean', group: 'Options'})
.option('verify-conditions', {...stringList, group: 'Plugins'})
Expand Down
1 change: 1 addition & 0 deletions lib/get-config.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ module.exports = async (context, cliOptions) => {
'@semantic-release/npm',
'@semantic-release/github',
],
preset: 'conventionalcommits',
// Remove `null` and `undefined` options so they can be replaced with default ones
...pickBy(options, (option) => !isNil(option)),
...(options.branches ? {branches: castArray(options.branches)} : {}),
Expand Down
24 changes: 24 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
"@semantic-release/npm": "^8.0.0",
"@semantic-release/release-notes-generator": "^10.0.0",
"aggregate-error": "^3.0.0",
"conventional-changelog-conventionalcommits": "^4.6.3",
"cosmiconfig": "^7.0.0",
"debug": "^4.0.0",
"env-ci": "^5.0.0",
Expand Down
69 changes: 56 additions & 13 deletions test/get-config.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ test('Read options from package.json', async (t) => {

const {options: result} = await t.context.getConfig({cwd});

const expected = {...options, branches: ['test_branch']};
const expected = {...options, branches: ['test_branch'], preset: 'conventionalcommits'};
// Verify the options contains the plugin config from package.json
t.deepEqual(result, expected);
// Verify the plugins module is called with the plugin options from package.json
Expand All @@ -140,7 +140,7 @@ test('Read options from .releaserc.yml', async (t) => {

const {options: result} = await t.context.getConfig({cwd});

const expected = {...options, branches: ['test_branch']};
const expected = {...options, branches: ['test_branch'], preset: 'conventionalcommits'};
// Verify the options contains the plugin config from package.json
t.deepEqual(result, expected);
// Verify the plugins module is called with the plugin options from package.json
Expand All @@ -162,7 +162,7 @@ test('Read options from .releaserc.json', async (t) => {

const {options: result} = await t.context.getConfig({cwd});

const expected = {...options, branches: ['test_branch']};
const expected = {...options, branches: ['test_branch'], preset: 'conventionalcommits'};
// Verify the options contains the plugin config from package.json
t.deepEqual(result, expected);
// Verify the plugins module is called with the plugin options from package.json
Expand All @@ -184,7 +184,7 @@ test('Read options from .releaserc.js', async (t) => {

const {options: result} = await t.context.getConfig({cwd});

const expected = {...options, branches: ['test_branch']};
const expected = {...options, branches: ['test_branch'], preset: 'conventionalcommits'};
// Verify the options contains the plugin config from package.json
t.deepEqual(result, expected);
// Verify the plugins module is called with the plugin options from package.json
Expand All @@ -206,7 +206,7 @@ test('Read options from .releaserc.cjs', async (t) => {

const {options: result} = await t.context.getConfig({cwd});

const expected = {...options, branches: ['test_branch']};
const expected = {...options, branches: ['test_branch'], preset: 'conventionalcommits'};
// Verify the options contains the plugin config from .releaserc.cjs
t.deepEqual(result, expected);
// Verify the plugins module is called with the plugin options from .releaserc.cjs
Expand All @@ -228,7 +228,7 @@ test('Read options from release.config.js', async (t) => {

const {options: result} = await t.context.getConfig({cwd});

const expected = {...options, branches: ['test_branch']};
const expected = {...options, branches: ['test_branch'], preset: 'conventionalcommits'};
// Verify the options contains the plugin config from package.json
t.deepEqual(result, expected);
// Verify the plugins module is called with the plugin options from package.json
Expand All @@ -250,7 +250,7 @@ test('Read options from release.config.cjs', async (t) => {

const {options: result} = await t.context.getConfig({cwd});

const expected = {...options, branches: ['test_branch']};
const expected = {...options, branches: ['test_branch'], preset: 'conventionalcommits'};
// Verify the options contains the plugin config from release.config.cjs
t.deepEqual(result, expected);
// Verify the plugins module is called with the plugin options from release.config.cjs
Expand Down Expand Up @@ -280,7 +280,7 @@ test('Prioritise CLI/API parameters over file configuration and git repo', async

const result = await t.context.getConfig({cwd}, options);

const expected = {...options, branches: ['branch_cli']};
const expected = {...options, branches: ['branch_cli'], preset: 'conventionalcommits'};
// Verify the options contains the plugin config from CLI/API
t.deepEqual(result.options, expected);
// Verify the plugins module is called with the plugin options from CLI/API
Expand All @@ -305,7 +305,7 @@ test('Read configuration from file path in "extends"', async (t) => {

const {options: result} = await t.context.getConfig({cwd});

const expected = {...options, branches: ['test_branch']};
const expected = {...options, branches: ['test_branch'], preset: 'conventionalcommits'};
// Verify the options contains the plugin config from shareable.json
t.deepEqual(result, expected);
// Verify the plugins module is called with the plugin options from shareable.json
Expand Down Expand Up @@ -336,7 +336,7 @@ test('Read configuration from module path in "extends"', async (t) => {

const {options: result} = await t.context.getConfig({cwd});

const expected = {...options, branches: ['test_branch']};
const expected = {...options, branches: ['test_branch'], preset: 'conventionalcommits'};
// Verify the options contains the plugin config from shareable.json
t.deepEqual(result, expected);
// Verify the plugins module is called with the plugin options from shareable.json
Expand Down Expand Up @@ -372,7 +372,7 @@ test('Read configuration from an array of paths in "extends"', async (t) => {

const {options: result} = await t.context.getConfig({cwd});

const expected = {...options1, ...options2, branches: ['test_branch']};
const expected = {...options1, ...options2, branches: ['test_branch'], preset: 'conventionalcommits'};
// Verify the options contains the plugin config from shareable1.json and shareable2.json
t.deepEqual(result, expected);
// Verify the plugins module is called with the plugin options from shareable1.json and shareable2.json
Expand Down Expand Up @@ -410,7 +410,7 @@ test('Prioritize configuration from config file over "extends"', async (t) => {

const {options: result} = await t.context.getConfig({cwd});

const expected = omit({...options1, ...pkgOptions, branches: ['test_pkg']}, 'extends');
const expected = omit({...options1, ...pkgOptions, branches: ['test_pkg'], preset: 'conventionalcommits'}, 'extends');
// Verify the options contains the plugin config from package.json and shareable.json
t.deepEqual(result, expected);
// Verify the plugins module is called with the plugin options from package.json and shareable.json
Expand Down Expand Up @@ -458,7 +458,10 @@ test('Prioritize configuration from cli/API options over "extends"', async (t) =

const {options: result} = await t.context.getConfig({cwd}, cliOptions);

const expected = omit({...options2, ...pkgOptions, ...cliOptions, branches: ['branch_opts']}, 'extends');
const expected = omit(
{...options2, ...pkgOptions, ...cliOptions, branches: ['branch_opts'], preset: 'conventionalcommits'},
'extends'
);
// Verify the options contains the plugin config from package.json and shareable2.json
t.deepEqual(result, expected);
// Verify the plugins module is called with the plugin options from package.json and shareable2.json
Expand Down Expand Up @@ -492,13 +495,15 @@ test('Allow to unset properties defined in shareable config with "null"', async
...omit(options1, ['analyzeCommits']),
...omit(pkgOptions, ['extends', 'analyzeCommits']),
plugins: DEFAULT_PLUGINS,
preset: 'conventionalcommits',
});
// Verify the plugins module is called with the plugin options from shareable.json and the default `plugins`
t.deepEqual(t.context.plugins.args[0][0], {
options: {
...omit(options1, 'analyzeCommits'),
...omit(pkgOptions, ['extends', 'analyzeCommits']),
plugins: DEFAULT_PLUGINS,
preset: 'conventionalcommits',
},
cwd,
});
Expand Down Expand Up @@ -535,6 +540,7 @@ test('Allow to unset properties defined in shareable config with "undefined"', a
...omit(options1, 'analyzeCommits'),
...omit(pkgOptions, ['extends', 'analyzeCommits']),
branches: ['test_branch'],
preset: 'conventionalcommits',
};
// Verify the options contains the plugin config from shareable.json
t.deepEqual(result, expected);
Expand Down Expand Up @@ -577,3 +583,40 @@ test('Convert "ci" option to "noCi" when set from extended config', async (t) =>
t.is(result.ci, false);
t.is(result.noCi, true);
});

test('Allow to override preset', async (t) => {
// Create a git repository, set the current working directory at the root of the repo
const {cwd} = await gitRepo();
const pkgOptions = {
preset: '1',
};
// Create package.json in repository root
await outputJson(path.resolve(cwd, 'package.json'), {release: pkgOptions});

const {
options: {preset: result},
} = await t.context.getConfig({cwd});

// Verify the preset contains the config from CLI/API
t.deepEqual(result, pkgOptions.preset);
});

test('Allow to override preset through CLI option --preset', async (t) => {
// Create a git repository, set the current working directory at the root of the repo
const {cwd} = await gitRepo();
const pkgOptions = {
preset: '1',
};
const cliOptions = {
preset: '2',
};
// Create package.json in repository root
await outputJson(path.resolve(cwd, 'package.json'), {release: pkgOptions});

const {
options: {preset: result},
} = await t.context.getConfig({cwd}, cliOptions);

// Verify the preset contains the config from CLI/API
t.deepEqual(result, cliOptions.preset);
});
16 changes: 14 additions & 2 deletions test/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ test('Plugins are called with expected values', async (t) => {
repositoryUrl,
globalOpt: 'global',
tagFormat: `v\${version}`,
preset: 'conventionalcommits',
};
const branches = [
{
Expand Down Expand Up @@ -883,6 +884,7 @@ test('Call all "success" plugins even if one errors out', async (t) => {
repositoryUrl,
globalOpt: 'global',
tagFormat: `v\${version}`,
preset: 'conventionalcommits',
};
const options = {
...config,
Expand Down Expand Up @@ -927,7 +929,12 @@ test('Log all "verifyConditions" errors', async (t) => {
const error2 = new SemanticReleaseError('error 2', 'ERR2');
const error3 = new SemanticReleaseError('error 3', 'ERR3');
const fail = stub().resolves();
const config = {branches: [{name: 'master'}], repositoryUrl, tagFormat: `v\${version}`};
const config = {
branches: [{name: 'master'}],
repositoryUrl,
tagFormat: `v\${version}`,
preset: 'conventionalcommits',
};
const options = {
...config,
plugins: false,
Expand Down Expand Up @@ -971,7 +978,12 @@ test('Log all "verifyRelease" errors', async (t) => {
const error1 = new SemanticReleaseError('error 1', 'ERR1');
const error2 = new SemanticReleaseError('error 2', 'ERR2');
const fail = stub().resolves();
const config = {branches: [{name: 'master'}], repositoryUrl, tagFormat: `v\${version}`};
const config = {
branches: [{name: 'master'}],
repositoryUrl,
tagFormat: `v\${version}`,
preset: 'conventionalcommits',
};
const options = {
...config,
verifyConditions: stub().resolves(),
Expand Down