Skip to content

Commit aea8dbb

Browse files
committed
workflow: improve release workflow
1 parent 3236bc2 commit aea8dbb

File tree

6 files changed

+238
-16
lines changed

6 files changed

+238
-16
lines changed

.eslintrc.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ module.exports = {
1717
'prefer-object-spread': 'off',
1818
'no-param-reassign': 'off',
1919
'arrow-parens': 'off',
20-
'linebreak-style': ['off', 'windows']
20+
'linebreak-style': ['off', 'windows'],
2121
},
2222
parserOptions: {
2323
parser: 'babel-eslint',

.github/workflows/release.yml

Lines changed: 53 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,62 @@
1-
name: Publish Package
1+
name: Release
22

33
on:
4-
release:
5-
types: [published]
4+
push:
5+
tags:
6+
- 'v*'
67

78
jobs:
8-
9+
tag:
10+
name: Create release tag
11+
runs-on: ubuntu-latest
12+
steps:
13+
- uses: actions/checkout@v2
14+
- name: Create release tag
15+
id: release_tag
16+
uses: yyx990803/release-tag@master
17+
env:
18+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
19+
with:
20+
tag_name: ${{ github.ref }}
21+
body: |
22+
[CHANGELOG.md](https://github.com/hujiulong/vue-3d-model/blob/master/CHANGELOG.md)
23+
924
publish-npm:
25+
name: Publish to NPM
26+
runs-on: ubuntu-latest
27+
needs: tag
28+
steps:
29+
- uses: actions/checkout@v2
30+
- name: Setup node
31+
uses: actions/setup-node@v2
32+
with:
33+
node-version: '14'
34+
registry-url: 'https://registry.npmjs.org'
35+
- name: Build & publish
36+
run: |
37+
npm install
38+
npm run build
39+
npm publish
40+
env:
41+
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
42+
43+
publish-gpr:
44+
name: Publish to GPR
1045
runs-on: ubuntu-latest
46+
needs: tag
1147
steps:
12-
- uses: actions/checkout@v1
13-
- uses: actions/setup-node@v1
48+
- uses: actions/checkout@v2
49+
- name: Setup node
50+
uses: actions/setup-node@v2
1451
with:
15-
node-version: 12
16-
registry-url: https://registry.npmjs.org/
17-
- run: npm install
18-
- run: npm run test
19-
- run: npm run build
20-
- run: npm publish
52+
node-version: '14'
53+
registry-url: 'https://npm.pkg.github.com/'
54+
scope: '@hujiulong'
55+
- name: Build & publish
56+
run: |
57+
npm install
58+
npm run build
59+
npm run gpr-setup
60+
npm publish
2161
env:
22-
NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}}
62+
NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

package.json

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,13 @@
2323
"build": "vue-cli-service build --target lib --name vue-3d-model src/index.js",
2424
"lint": "vue-cli-service lint src/ tests/ examples/",
2525
"lint:fix": "npm run lint -- --fix",
26-
"test": "vue-cli-service test:unit"
26+
"test": "vue-cli-service test:unit",
27+
"gpr-setup": "node scripts/gpr-setup.js",
28+
"release": "node scripts/release.js",
29+
"changelog": "conventional-changelog -p angular -i CHANGELOG.md -s -r 0"
30+
},
31+
"gitHooks": {
32+
"commit-msg": "node scripts/verify-commit.js"
2733
},
2834
"peerDependencies": {
2935
"vue": ">=2.0.0"
@@ -39,13 +45,20 @@
3945
"@vue/eslint-config-airbnb": "^5.0.2",
4046
"@vue/test-utils": "^1.0.3",
4147
"babel-eslint": "^10.1.0",
48+
"chalk": "^4.1.1",
49+
"conventional-changelog-cli": "^2.1.1",
50+
"enquirer": "^2.3.6",
4251
"eslint": "^7.5.0",
4352
"eslint-plugin-import": "^2.20.2",
4453
"eslint-plugin-vue": "^7.1.0",
54+
"execa": "^5.1.1",
4555
"less": "^4.1.1",
4656
"less-loader": "^10.0.0",
57+
"minimist": "^1.2.5",
58+
"semver": "^7.3.5",
4759
"vue": "^2.6.11",
4860
"vue-router": "^3.3.4",
49-
"vue-template-compiler": "^2.6.11"
61+
"vue-template-compiler": "^2.6.11",
62+
"yorkie": "^2.0.0"
5063
}
5164
}

scripts/gpr-setup.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
const fs = require('fs');
2+
const path = require('path');
3+
const pkg = require('../package.json');
4+
5+
pkg.name = '@hujiulong/vue-3d-model';
6+
7+
// Update package.json with the udpated name
8+
fs.writeFileSync(
9+
path.join(__dirname, '../package.json'),
10+
JSON.stringify(pkg, null, 2),
11+
);

scripts/release.js

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
/* eslint-disable */
2+
3+
const args = require('minimist')(process.argv.slice(2));
4+
const fs = require('fs');
5+
const path = require('path');
6+
const chalk = require('chalk');
7+
const semver = require('semver');
8+
const { prompt } = require('enquirer');
9+
const execa = require('execa');
10+
const pkg = require('../package.json');
11+
12+
const currentVersion = pkg.version;
13+
const preId =
14+
args.preid ||
15+
(semver.prerelease(currentVersion) && semver.prerelease(currentVersion)[0]);
16+
const isDryRun = args.dry;
17+
const skipTests = args.skipTests;
18+
const skipBuild = args.skipBuild;
19+
20+
const pkgPath = path.resolve(__dirname, '../package.json');
21+
const versionIncrements = [
22+
'patch',
23+
'minor',
24+
'major',
25+
...(preId ? ['prepatch', 'preminor', 'premajor', 'prerelease'] : []),
26+
];
27+
28+
const inc = (i) => semver.inc(currentVersion, i, preId);
29+
const run = (bin, args, opts = {}) =>
30+
execa(bin, args, { stdio: 'inherit', ...opts });
31+
const dryRun = (bin, args, opts = {}) =>
32+
console.log(chalk.blue(`[dryrun] ${bin} ${args.join(' ')}`), opts);
33+
const runIfNotDry = isDryRun ? dryRun : run;
34+
const step = (msg) => console.log(chalk.cyan(msg));
35+
36+
async function main() {
37+
let targetVersion = args._[0];
38+
39+
if (!targetVersion) {
40+
// no explicit version, offer suggestions
41+
const { release } = await prompt({
42+
type: 'select',
43+
name: 'release',
44+
message: 'Select release type',
45+
choices: versionIncrements
46+
.map((i) => `${i} (${inc(i)})`)
47+
.concat(['custom']),
48+
});
49+
50+
if (release === 'custom') {
51+
targetVersion = (
52+
await prompt({
53+
type: 'input',
54+
name: 'version',
55+
message: 'Input custom version',
56+
initial: currentVersion,
57+
})
58+
).version;
59+
} else {
60+
targetVersion = release.match(/\((.*)\)/)[1];
61+
}
62+
}
63+
64+
if (!semver.valid(targetVersion)) {
65+
throw new Error(`invalid target version: ${targetVersion}`);
66+
}
67+
68+
const { yes } = await prompt({
69+
type: 'confirm',
70+
name: 'yes',
71+
message: `Releasing v${targetVersion}. Confirm?`,
72+
});
73+
74+
if (!yes) {
75+
return;
76+
}
77+
78+
// update all package versions and inter-dependencies
79+
step('\nUpdating cross dependencies...');
80+
if (!isDryRun) {
81+
pkg.version = targetVersion;
82+
fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + '\n');
83+
} else {
84+
console.log(`(skipped)`);
85+
}
86+
87+
// run tests before release
88+
step('\nRunning tests...');
89+
if (!skipTests && !isDryRun) {
90+
await run('npm', ['test']);
91+
} else {
92+
console.log(`(skipped)`);
93+
}
94+
95+
// build package
96+
step('\nBuilding package...');
97+
if (!skipBuild && !isDryRun) {
98+
await run('npm', ['build', '--release']);
99+
} else {
100+
console.log(`(skipped)`);
101+
}
102+
103+
// generate changelog
104+
await run(`npm`, ['run', 'changelog']);
105+
106+
const { stdout } = await run('git', ['diff'], { stdio: 'pipe' });
107+
if (stdout) {
108+
step('\nCommitting changes...');
109+
await runIfNotDry('git', ['add', '-A']);
110+
await runIfNotDry('git', ['commit', '-m', `release: v${targetVersion}`]);
111+
} else {
112+
console.log('No changes to commit.');
113+
}
114+
115+
// push to GitHub
116+
step('\nPushing to GitHub...');
117+
await runIfNotDry('git', ['tag', `v${targetVersion}`]);
118+
await runIfNotDry('git', ['push', 'origin', `refs/tags/v${targetVersion}`]);
119+
await runIfNotDry('git', ['push']);
120+
121+
if (isDryRun) {
122+
console.log(`\nDry run finished - run git diff to see package changes.`);
123+
}
124+
125+
console.log();
126+
}
127+
128+
main().catch((err) => {
129+
console.error(err);
130+
});

scripts/verify-commit.js

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// Invoked on the commit-msg git hook by yorkie.
2+
3+
/* eslint-disable prefer-template, quotes, operator-linebreak */
4+
5+
const chalk = require('chalk');
6+
7+
const msgPath = process.env.GIT_PARAMS;
8+
const msg = require('fs').readFileSync(msgPath, 'utf-8').trim();
9+
10+
const commitRE = /^(revert: )?(feat|fix|docs|dx|style|refactor|perf|test|workflow|build|ci|chore|types|wip|release)(\(.+\))?: .{1,50}/;
11+
12+
if (!commitRE.test(msg)) {
13+
console.log();
14+
console.error(
15+
` ${chalk.bgRed.white(' ERROR ')} ${chalk.red(
16+
`invalid commit message format.`,
17+
)}\n\n` +
18+
chalk.red(
19+
` Proper commit message format is required for automated changelog generation. Examples:\n\n`,
20+
) +
21+
` ${chalk.green(`feat(compiler): add 'comments' option`)}\n` +
22+
` ${chalk.green(
23+
`fix(v-model): handle events on blur (close #28)`,
24+
)}\n\n` +
25+
chalk.red(` See .github/commit-convention.md for more details.\n`),
26+
);
27+
process.exit(1);
28+
}

0 commit comments

Comments
 (0)