1 | #! /usr/bin/env node
|
2 |
|
3 | const childProcess = require('child_process');
|
4 | const c = require('chalk');
|
5 | const _ = require('lodash/fp');
|
6 | const {headClean, headMessage, pushFiles} = require('./core/git');
|
7 | const {makeError} = require('./core/utils');
|
8 | const executeScript = require('./core/script');
|
9 |
|
10 | const MAJOR = 'major';
|
11 | const MINOR = 'minor';
|
12 | const PATCH = 'patch';
|
13 |
|
14 | const builtInSelectReleaseType = message => {
|
15 | const firstLine = message.split('\n')[0];
|
16 | const containsPatchKeyWords = /bug|fix|tweak|plugging/i.test(firstLine);
|
17 | const tooShortMessage = firstLine.split(' ').length < 5;
|
18 | const hashtagMinor = /#minor\b/i.test(firstLine);
|
19 | const hashtagBug = /#bug\b/i.test(firstLine);
|
20 | const containsMinorKeyWords = /release|feature/i.test(firstLine);
|
21 | const isSquashOrMerge = /Merge pull request #\d+|\(#\D+\)/.test(firstLine);
|
22 |
|
23 | if (hashtagBug || containsPatchKeyWords) return PATCH;
|
24 | if (hashtagMinor || containsMinorKeyWords) return MINOR;
|
25 | if (!isSquashOrMerge) return MINOR;
|
26 | if (tooShortMessage) return PATCH;
|
27 | return MINOR;
|
28 | };
|
29 |
|
30 | const getCustomSelection = cmd => {
|
31 | try {
|
32 | return childProcess.execSync(cmd, {encoding: 'utf-8'}).trim();
|
33 | } catch (err) {
|
34 | throw makeError('Failed to get release type', {
|
35 | details: `Exit code of selection command '${cmd}' was ${err.status}`,
|
36 | exitCode: 5
|
37 | });
|
38 | }
|
39 | };
|
40 |
|
41 | const getReleaseType = async selectionCommand => {
|
42 | const releaseType = selectionCommand
|
43 | ? getCustomSelection(selectionCommand)
|
44 | : await builtInSelectReleaseType(await headMessage());
|
45 | if (!_.includes(releaseType, [MAJOR, MINOR, PATCH]))
|
46 | throw makeError(`Invalid release type ${releaseType}`);
|
47 | return releaseType;
|
48 | };
|
49 |
|
50 | module.exports = async config => {
|
51 | if (!(await headClean())) throw makeError('Not a clean state', {exitCode: 4});
|
52 | const autoBumpConfig = config['auto-bump'];
|
53 | if (_.isBoolean(autoBumpConfig)) {
|
54 | if (!autoBumpConfig) {
|
55 | process.stdout.write(c.bold.yellow('Auto-bump is deactivated in config'));
|
56 | return;
|
57 | }
|
58 | } else if (_.isEmpty(autoBumpConfig)) throw makeError('No Config for autobump', {exitCode: 3});
|
59 | const releaseSelector = autoBumpConfig['release-type-command'];
|
60 | const releaseType = await getReleaseType(releaseSelector);
|
61 |
|
62 | process.stdout.write(`About to make a ${c.bold.blue(releaseType)} release\n`);
|
63 | const bumpVersionCommand = autoBumpConfig['bump-command'] || 'npm version -m "v%s"';
|
64 | await executeScript([`${bumpVersionCommand} ${releaseType}`]);
|
65 | if (!config.local) await pushFiles('master', config.token, config.repoSlug, true);
|
66 | process.stdout.write(c.bold.green(`Successfully made a ${releaseType} release\n`));
|
67 | if (autoBumpConfig.publish || autoBumpConfig['publish-command']) {
|
68 | await executeScript([autoBumpConfig['publish-command'] || 'npm publish']);
|
69 | process.stdout.write(c.bold.green(`Successfully publish the ${releaseType} release\n`));
|
70 | }
|
71 | if (autoBumpConfig['sync-branch']) {
|
72 | const branch = autoBumpConfig['sync-branch'];
|
73 | await executeScript([
|
74 | `git config remote.gh.url >/dev/null || git remote add gh https://${config.token}@github.com/${config.repoSlug}.git`,
|
75 | `git pull gh ${branch} && git checkout ${branch} && git reset --hard master`,
|
76 | `git push gh ${branch}:refs/heads/${branch} --force || (git remote remove gh && exit 12)`,
|
77 | 'git remote remove gh'
|
78 | ]);
|
79 | process.stdout.write(c.bold.green(`Successfully sync branch ${branch}\n`));
|
80 | }
|
81 | if (autoBumpConfig['merge-branch']) {
|
82 | const branch = autoBumpConfig['merge-branch'];
|
83 | await executeScript([
|
84 | `git config remote.gh.url >/dev/null || git remote add gh https://${config.token}@github.com/${config.repoSlug}.git`,
|
85 | `git pull gh ${branch} && git checkout ${branch} && git merge master`,
|
86 | `git push gh ${branch}:refs/heads/${branch} || (git remote remove gh && exit 12)`,
|
87 | 'git remote remove gh'
|
88 | ]);
|
89 | process.stdout.write(c.bold.green(`Successfully merged branch ${branch}\n`));
|
90 | }
|
91 | };
|