release-flow
is a command line tool that simplifies the developer side of software release process taking over tedious and error prone tasks.
release-flow
mixes git flow releases with conventional commits to make release process safe and painless.
- Based on commit conventions
- Complements perfectly with CI tools
- Flexible branching model
- Pluggable design
- Completely configurable and customizable
- Stand-alone (gulp/grunt integration is possible)
- Suitable for any kind of project and language (small apps, opensource projects, libs, enterprise applications)
- Built in plugins for Changelog generation and NPM bumps
Globally (use from console)
npm i -g release-flow
As project dependency (use through npm script or programmatically)
npm i --save-dev release-flow
In your package.json
"scripts": {
"release": "release-flow"
}
release-flow start
Effect:
- Fetches remote changes
- Compute the next version bump from commits (ie.
feat commit === minor
) - Validates the operation (no uncommitted/untracked changes, no existing tag for the version)
- Creates and checks out a new release branch
- Commits (without pushing) any eventual changes made to start the release (ie. changelog, bump package.json)
release-flow publish
release-flow finish
Effect:
- Fetches remote changes
- Validates the operation (no uncommitted/untracked changes)
- Merges release branch on master
- Tags master after the release version
- Merges back to development (if different from master)
release-flow full
Effect:
Same then issuing release-flow start
, release-flow publish
and release-flow finish
in sequence.
NOTE: This approach is especially suitable for libraries and small projects that does not require a QA phase on the release branch.
release-flow
supports both the canonical git-flow
branching model with develop/master and a
simplified branching with just master.
// releaseflowrc
module.exports = {
developmentBranch: 'develop',
productionBranch: 'master'
};
// releaseflowrc
module.exports = {
developmentBranch: 'master',
productionBranch: 'master'
};
Release flow uses conventional commits to simplify the release process (computing next version, generating changelogs).
Conventional commits are commits with a specific message format:
type([scope]): message [BREAKING]
ie.
- fix(homepage): fixed title alignment
- feat: implemented user login
- feat(api): BREAKING changed endpoint to list users
- Has one commit whose message contains
BREAKING
→major
- Has one commit whose type is feat →
minor
- Otherwise →
patch
release-flow
loads a releaseflowrc
javascript file to allow configuration.
The following is an extract of the default configuration file:
export default {
developmentBranch: 'develop',
productionBranch: 'master',
releaseBranchPrefix: 'release/',
tagPrefix: 'v',
remoteName: 'origin',
logLevel: 'info',
initialVersion: '1.0.0',
repoHttpUrl: null,
ErrorFactory: DefaultErrorFactory,
Logger: DefaultLogger,
repoHttpProtocol: 'https',
getBump: getBump,
plugins: []
};
Bumps package json version on start.
// releaseflowrc
module.exports = {
plugins: [
'bump-package-json'
]
};
Generates a changelog for the release and prepend it CHANGELOG.md
or the choosen path on start.
// releaseflowrc
module.exports = {
changelogPath: 'CHANGELOG.md'
changelogTemplate: release => 'changelog contents'
plugins: [
'generate-changelog'
]
};
A plugin is just a function of the form install(release) => null
. To register it is enough to pass it in releaseflowrc
// releaseflowrc
module.exports = {
plugins: [
release => {
// ... do something
}
]
};
Tiplcally a plugin adds some step
to a release phase (one of start, publish or finish).
A step is an object with a name
and a run()
function.
To attach a step to a phase is possible to use array methods like push
or splice
on the release.phases.[start/publish/finish].steps
array or use the release.phases.[start/publish/finish].before
method to insert the step before another specific step:
// releaseflowrc
module.exports = {
plugins: [
release => {
let logVersion = {
name: 'logVersion',
run(release) {
console.log(release.version);
}
};
release.phases.start.before('commit', logVersion);
}
]
};