# tools - release workflow
By release workflow, i mean all the tasks starting to the commit to be published (excluding Work In Progress, aka WIP commits, to be squashed).
The tasks are :
- commit to be released
- CHANGELOG generation
- CHANGELOG commit
- tagging
- npm packaging
git push
- Git PR/MR (Pull Request / Merge Request) resolution (including CI job)
- release to npm registry or deploy to environment (depending of the deliverable nature)
The operational workflow varies depending on where theses tasks are executed.
They can be executed on the developer computer or/and in the CI pipeline.
The release workflow is highly coupled the Git workflow, anyway this is another matter.
We could resume the release workflow this way :
commit ---> CHANGELOG ---> tag ---> merge
|
|
V
package ---> release
2
3
4
5
6
7
8
9
# foundation basics
Theses tools are based on Git, a common commits messages convention, the semver specification and obviously npm.
# codebase (Git)
The famous Source Control Manager.
Manage the codebase contained in a repository.
# codebase revisions (Git commits messages convention)
Popularized by AngularJS team. Can be found here.
Each codebase revision is hold in a commit. Each commit contain a commit message.
Commit message standardization leads to :
- CHANGELOG generation automation.
- version generation (tagging) automation.
# versions system (Semver)
Popularized by npm to manage the version system.
It is about how to structure a version number and for what meaning.
# deliverable management (npm)
The node package manager.
- Manage the dependencies in a project.
- Structure the deliverable (named "package" in npm world), the npm registry store the deliverable. Users download packages from it.
The following npm CLI commands are especially involved :
Commands like npm build
, npm test
, npm ci
are obviously also involved, but they are already involved in the development process.
# articles
- Automate your releases and semantic versioning with
semantic-release
- Use
commitizen
withcz-convential-changelog
to capture additional details about each commit- Run Automated Tests that generate Code Coverage reports
- Maintain coverage standards with
Codecov
- Ensure consistent code formatting, and avoid simple mistakes by Linting your code
- Keep your dependencies up to date with
GreenKeeper
Semantic Release with Lerna and Conventional Commits - michaljanaszek.com/blog - 20180616
In this tutorial, I will show you how to configure Lerna with Conventional Commits to achieve automatic Semantic Release based only on the history of commits.
Conventional Commits + Conventional Changelog + Semantic Release + Commitlint
Lerna Independent Mode with Semver - samhogy.co.uk - 20180816
focus on lerna independent mode with semantic versioning.
# tools overview
# monorepo management
lerna/lerna
- github.com
/ lernajs.io
A tool for managing JavaScript projects with multiple packages
Lerna config belongs to lerna.json
file.
Logs goes into lerna-debug.log
file.
# Features
- Version / tag management in 2 modes :
- Fixed/Locked mode (every package got the same version number / tag)
- Independent mode (each package got his own version number / tag)
- Common
devDependencies
(hoisting of common dependencies, most of thedevDependencies
are commons)
WARNING : lerna used with semantic-release is not mature at all. See issue on semantic-release repo.
# dependencies automatic management
greenkeeper.io greenkeeperio
- github.com
Get safety & consistency with real-time monitoring and automatic updates for npm dependencies
# commit message management
A specification for adding human and machine readable meaning to commit messages
Commit message structure :
<type>[optional scope]: <description>
[optional body]
[optional footer]
2
3
4
5
conventional-changelog/commitlint
- github.com
Lint commit messages
commitizen/cz-cli
- github.com
The commitizen command line utility.
commitizen/cz-conventional-changelog
- github.com
A commitizen adapter for the angular preset of conventional-changelog.
# CHANGELOG.md
management
2 years time range give a better view :
- generate-changelog have really low usage.
- conventional-changelog is the older and the most used but adoption seems stable.
- semantic-release is growing quite fast since mid-2018, close to conventional-changelog adoption and still growing.
# lob/generate-changelog
lob/generate-changelog
- github.com
The simpler one.
Limited to the CHANGELOG.md
file generation.
Recommendations available for the tag and push tasks.
# conventional-changelog
Executed on the developer computer manually by the developer.
conventional-changelog
- github.com
standard-version is the high level entry point repo.
standard-version
does the following:
- bumps the version in metadata files (package.json, composer.json, etc).
- uses conventional-changelog to update CHANGELOG.md
- commits package.json (et al.) and CHANGELOG.md
- tags a new release
# Others tools
releaser-tools
- github.com/conventional-changelog
Create a GitHub/GitLab/etc. release using a project's commit messages and metadata.
# semantic-release
Executed by a CI job.
semantic-release
- semantic-release.gitbook.io
semantic-release automates the whole package release workflow including: determining the next version number, generating the release notes and publishing the package.
This removes the immediate connection between human emotions and version numbers, strictly following the Semantic Versioning specification.
# conventional-changelog versus semantic-release
explain the relationship to semantic-release - github.com/conventional-changelog
How is it different than semantic-release
- github.com/conventional-changelog
semantic-release
is a fully automated library/system for versioning, changelog generation, Git tagging, and publishing to the npm registry.
standard-version
is different because it handles the versioning, changelog generation, and Git tagging for you without automatic pushing (to GitHub) or publishing (to an npm registry). Use ofstandard-version
only affects your local Git repo - it doesn't affect remote resources at all. After you runstandard-version
, you still have to ability to review things and correct mistakes if you want to.They are both based on the same foundation of structured commit messages (using Angular format), but
standard-version
is a good choice for folks who are not yet comfortable letting publishes go out automatically. In this way, you can viewstandard-version
as an incremental step to adoptingsemantic-release
.
# a working continuous delivery workflow
# overview
Setup a continuous delivery workflow with as much automation as possible from commit to deployment.
The CI service used is TravisCI.
GitHooks are managed by Husky.
Commit message convention used is www.conventionalcommits.org.
Commit messages are linted by commitlint.
Commit can be produced with the help of the commitizen CLI with the cz-conventional-changelog config.
Automation is provided by semantic-release.
# Git workflow
Two branches, master
and develop
, both must be protected.
develop
is the target for every PR. Set it as default branch instead of master
branch.
PR are done with classic features branches based on develop
, never based on master
.
master
is the distribution channel to deploy.
Every branch push trigger a CI job.
A CI job is composed of 3 stages :
commitlint
stage to reject malformed commit messagetest
stage to reject invalid commit content (test should execute at least lint + tests)deploy
stage triggered only by themaster
branch to build the package and deploy it to the npm registry.
It also determine the version number, compute the release CHANGELOG, tag the tip of the branch and push it with release CHANGELOG to origin.
To deploy, the Git owner must merge locally develop
into master
. It should be always a fast-forward, develop
and master
are mirrors.
Never use a PR to merge develop
into master
, semantic-release will not trigger the deploy stage for a PR.
# installation
Before any steps, be sure to have a valid package.json
file, and especially a fulfilled "repository"
section in it.
You should also already have a .npmignore
file with a content like this :
node_modules/
public/
dist/
npm-debug.log
.DS_Store
.idea/
*.tgz
test-utils/
tests/
.editorconfig
.eslintignore
.eslintrc.json
.npmrc
tsconfig.json
tsconfig-dev.json
tslint.json
.travis.yml
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
install semantic-release in your project :
npm i -D semantic-release
install semantic-release-cli :
npm i -g semantic-release-cli
configure semantic-release :
semantic-release-cli setup
Answer the questions, you will need to provide your logins / passwords for npm registry and GitHub account. semantic-release will generate tokens with them and will push them to TravisCI to allows the CI job to push into them.
GitHub webhook will be automatically configured.
TravisCI job will be automatically created and configured during the first deploy attempt (push on the master
branch).
The version number in your package.json
will be set to 0.0.0-development
and will never move.
semantic-release modify only the package.json
put into the npm package sent to the registry.
install commitizen :
npm i -D commitizen cz-conventional-changelog
commitizen
provide a CLI wizard to help creating valid commit messages
cz-conventional-changelog
describe the desired commit format (for this example it is the conventional changelog spec)
configure commitizen :
In your package.json
, add this section to configure commitizen
:
"config": {
"commitizen": {
"path": "./node_modules/cz-conventional-changelog"
}
},
2
3
4
5
And under the script
section add this command :
"cz-commit": "git-cz"
To avoid conflict with husky
, prefix the script with cz-
(defaut in the documentation is just commit
).
commitizen usage :
Stages the files you want to commit, then use the CLI tool with npm run cz-commit
then answer the questions.
install commitlint :
npm i -D @commitlint/cli @commitlint/config-conventional @commitlint/travis-cli
Same as commitizen
, the commitlint
CLI is configured with the @commitlint/config-conventional
package to define the commit message convention used.
The @commitlint/travis-cli
will be used in the TravisCI job to lint server side en enforce the convention.
configure commitlint :
Add this section to your package.json
to configure commitlint
:
"commitlint": {
"extends": [
"@commitlint/config-conventional"
]
},
2
3
4
5
Add a hook to the husky
configuration in your package.json
:
"commit-msg": "commitlint -E HUSKY_GIT_PARAMS",
Each local commit attempt will trigger commitlint
.
Your husky
configuraton in your package.json
should look like this :
"husky": {
"hooks": {
"commit-msg": "commitlint -E HUSKY_GIT_PARAMS",
"pre-commit": "npm test",
"pre-push": "npm test"
}
},
2
3
4
5
6
7
create and fill your .travis.yml
file.
This content should do the job :
language: node_js
node_js:
- 10
cache: npm
install:
- npm ci
branches:
except:
- '/^v\d+\.\d+\.\d+$/'
jobs:
include:
- stage: commitlint
script:
- commitlint-travis
- stage: test
script:
- npm run test
- stage: deploy
if: branch == master && !fork
node_js: '10'
script:
- npm install -g semantic-release@^15
- semantic-release
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
semantic-release
is tested only with the last LTS node version. So your app should do the same.
# initialize the workflow
You should have already an initial commit. The message commit convention for this commit is not important.
The next commit should contain all this configuration and should be able to generate something to package and deliver to the npm registry.
Be careful to choose a feat or fix type for the commit message. Others type will not trigger a release.
The develop
branch should not exist yet.
When the commit is written, push it directly into master
to trigger the first CI job and the first deploy.
This deploy is mandatory because TravisCI needs the .travis.yml
files present into each branches in order to run.
So you need first to deploy a dummy app version, then the contribution branch which will be the destination for PR will be created based on master
.
Check the CI result. Check also the npm registry.
At this point, if everything is ok you have the CI up and runnning and a first package version in the npm registry.
Now you can create the develop
branch in your remote repository. Don't forget to protect it and to set it to the default branch.
The master branch needs also to be protected.
You can add rules to the protected branches to force some checks when a PR occurs. After the first CI completed job you are able to force a CI status check to validate a PR.
You're done.