Skip to content

Commit d2315c5

Browse files
committed
Docs: Update and refactor release workflow recipe
- infer version bump from commits - make release commit message adhere to Conventional Commits - read GitHub personal access token from git-ignored `.env` file - functions instead of `gulp.task` - eliminate usage of gulp plugins - improve readability with `execa` and `util.promisify`
1 parent b7b70b8 commit d2315c5

File tree

1 file changed

+86
-72
lines changed

1 file changed

+86
-72
lines changed
Lines changed: 86 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -1,79 +1,93 @@
11
# Automate release workflow
22

33
If your project follows a semantic versioning, it may be a good idea to automatize the steps needed to do a release.
4-
Below you have a simple recipe that bumps the project version, commits the changes to git and creates a new tag.
5-
6-
``` javascript
7-
8-
var gulp = require('gulp');
9-
var conventionalChangelog = require('gulp-conventional-changelog');
10-
var conventionalGithubReleaser = require('conventional-github-releaser');
11-
var bump = require('gulp-bump');
12-
var log = require('gulplog');
13-
var git = require('gulp-git');
14-
var fs = require('fs');
15-
16-
gulp.task('changelog', function () {
17-
return gulp.src('CHANGELOG.md', {
18-
buffer: false
19-
})
20-
.pipe(conventionalChangelog({
21-
preset: 'angular' // Or to any other commit message convention you use.
22-
}))
23-
.pipe(gulp.dest('./'));
24-
});
25-
26-
gulp.task('github-release', function(done) {
27-
conventionalGithubReleaser({
28-
type: "oauth",
29-
token: 'abcdefghijklmnopqrstuvwxyz1234567890' // change this to your own GitHub token or use an environment variable
30-
}, {
31-
preset: 'angular' // Or to any other commit message convention you use.
32-
}, done);
33-
});
34-
35-
gulp.task('bump-version', function () {
36-
// We hardcode the version change type to 'patch' but it may be a good idea to
37-
// use minimist (https://www.npmjs.com/package/minimist) to determine with a
38-
// command argument whether you are doing a 'major', 'minor' or a 'patch' change.
39-
return gulp.src(['./bower.json', './package.json'])
40-
.pipe(bump({type: "patch"}).on('error', log.error))
41-
.pipe(gulp.dest('./'));
42-
});
43-
44-
gulp.task('commit-changes', function () {
45-
return gulp.src('.')
46-
.pipe(git.add())
47-
.pipe(git.commit('[Prerelease] Bumped version number'));
48-
});
49-
50-
gulp.task('push-changes', function (done) {
51-
git.push('origin', 'master', done);
52-
});
53-
54-
gulp.task('create-new-tag', function (done) {
55-
var version = getPackageJsonVersion();
56-
git.tag(version, 'Created Tag for version: ' + version, function (error) {
57-
if (error) {
58-
return done(error);
59-
}
60-
git.push('origin', 'master', {args: '--tags'}, done);
4+
The recipe below bumps the project version, commits the changes to git and creates a new GitHub release.
5+
6+
For publishing a GitHub release you'll need to [create a personal access token](https://docs.github.com/en/free-pro-team@latest/github/authenticating-to-github/creating-a-personal-access-token) and add it to your project. However, we don't want to commit it, so we'll use [`dotenv`](https://www.npmjs.com/package/dotenv) to load it from a git-ignored `.env` file:
7+
8+
```
9+
GH_TOKEN=ff34885...
10+
```
11+
12+
Don't forget to add `.env` to your `.gitignore`.
13+
14+
Next, install all the necessary dependencies for this recipe:
15+
16+
```sh
17+
npm install --save-dev conventional-recommended-bump conventional-changelog-cli conventional-github-releaser dotenv execa
18+
```
19+
20+
Based on your environment, setup and preferences, your release workflow might look something like this:
21+
22+
``` js
23+
const gulp = require('gulp');
24+
const conventionalRecommendedBump = require('conventional-recommended-bump');
25+
const conventionalGithubReleaser = require('conventional-github-releaser');
26+
const execa = require('execa');
27+
const fs = require('fs');
28+
const { promisify } = require('util');
29+
const dotenv = require('dotenv');
30+
31+
// load environment variables
32+
const result = dotenv.config();
33+
34+
if (result.error) {
35+
throw result.error;
36+
}
37+
38+
// Conventional Changelog preset
39+
const preset = 'angular';
40+
// print output of commands into the terminal
41+
const stdio = 'inherit';
42+
43+
async function bumpVersion() {
44+
// get recommended version bump based on commits
45+
const { releaseType } = await promisify(conventionalRecommendedBump)({ preset });
46+
// bump version without committing and tagging
47+
await execa('npm', ['version', releaseType, '--no-git-tag-version'], {
48+
stdio,
6149
});
50+
}
51+
52+
async function changelog() {
53+
await execa(
54+
'npx',
55+
[
56+
'conventional-changelog',
57+
'--preset',
58+
preset,
59+
'--infile',
60+
'CHANGELOG.md',
61+
'--same-file',
62+
],
63+
{ stdio }
64+
);
65+
}
66+
67+
async function commitTagPush() {
68+
// even though we could get away with "require" in this case, we're taking the safe route
69+
// because "require" caches the value, so if we happen to use "require" again somewhere else
70+
// we wouldn't get the current value, but the value of the last time we called "require"
71+
const { version } = JSON.parse(await promisify(fs.readFile)('package.json'));
72+
const commitMsg = `chore: release ${version}`;
73+
await execa('git', ['add', '.'], { stdio });
74+
await execa('git', ['commit', '--message', commitMsg], { stdio });
75+
await execa('git', ['tag', `v${version}`], { stdio });
76+
await execa('git', ['push', '--follow-tags'], { stdio });
77+
}
6278

63-
function getPackageJsonVersion () {
64-
// We parse the json file instead of using require because require caches
65-
// multiple calls so the version number won't be updated
66-
return JSON.parse(fs.readFileSync('./package.json', 'utf8')).version;
67-
};
68-
});
69-
70-
gulp.task('release', gulp.series(
71-
'bump-version',
72-
'changelog',
73-
'commit-changes',
74-
'push-changes',
75-
'create-new-tag',
76-
'github-release'
77-
));
79+
function githubRelease(done) {
80+
conventionalGithubReleaser(
81+
{ type: 'oauth', token: process.env.GH_TOKEN },
82+
{ preset },
83+
done
84+
);
85+
}
7886

87+
exports.release = gulp.series(
88+
bumpVersion,
89+
changelog,
90+
commitTagPush,
91+
githubRelease
92+
);
7993
```

0 commit comments

Comments
 (0)