[TOC]
- Automate Releases
Automate Releases
If your project follows a semantic versioning, it may be a good idea to automatize the steps needed to do a release. The recipe below bumps the project version, commits the changes to git and creates a new GitHub release.
For publishing a GitHub release you’ll need to create a personal access token and add it to your project. However, we don’t want to commit it, so we’ll use dotenv to load it from a git-ignored .env file:
GH_TOKEN=ff34885...
Don’t forget to add .env to your .gitignore.
Next, install all the necessary dependencies for this recipe:
npm install --save-dev conventional-recommended-bump conventional-changelog-cli conventional-github-releaser dotenv execa
Based on your environment, setup and preferences, your release workflow might look something like this:
const gulp = require('gulp');const conventionalRecommendedBump = require('conventional-recommended-bump');const conventionalGithubReleaser = require('conventional-github-releaser');const execa = require('execa');const fs = require('fs');const { promisify } = require('util');const dotenv = require('dotenv');// load environment variablesconst result = dotenv.config();if (result.error) { throw result.error;}// Conventional Changelog presetconst preset = 'angular';// print output of commands into the terminalconst stdio = 'inherit';async function bumpVersion() { // get recommended version bump based on commits const { releaseType } = await promisify(conventionalRecommendedBump)({ preset }); // bump version without committing and tagging await execa('npm', ['version', releaseType, '--no-git-tag-version'], { stdio, });}async function changelog() { await execa( 'npx', [ 'conventional-changelog', '--preset', preset, '--infile', 'CHANGELOG.md', '--same-file', ], { stdio } );}async function commitTagPush() { // even though we could get away with "require" in this case, we're taking the safe route // because "require" caches the value, so if we happen to use "require" again somewhere else // we wouldn't get the current value, but the value of the last time we called "require" const { version } = JSON.parse(await promisify(fs.readFile)('package.json')); const commitMsg = `chore: release ${version}`; await execa('git', ['add', '.'], { stdio }); await execa('git', ['commit', '--message', commitMsg], { stdio }); await execa('git', ['tag', `v${version}`], { stdio }); await execa('git', ['push', '--follow-tags'], { stdio });}function githubRelease(done) { conventionalGithubReleaser( { type: 'oauth', token: process.env.GH_TOKEN }, { preset }, done );}exports.release = gulp.series( bumpVersion, changelog, commitTagPush, githubRelease);
