Skip to content

Commit 5a3b5bc

Browse files
committed
Add github-release script
1 parent 4d074ae commit 5a3b5bc

File tree

3 files changed

+213
-6
lines changed

3 files changed

+213
-6
lines changed

.travis.yml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ before_install:
1616
- npm install -g npm
1717
- npm --version
1818

19+
install:
20+
- npm install
21+
1922
after_success:
2023
- mkdir -p releases
2124
- PACKAGE_NAME=`scripts/package-name.sh package.json`
@@ -28,6 +31,15 @@ after_success:
2831
zip -r "../releases/${RELEASE}.zip" *;
2932
popd;
3033
ls -al releases/*;
34+
if [[ -z "$TRAVIS_TAG" ]]; then
35+
npm run github-release -- \
36+
--owner=cncjs \
37+
--repo=cncjs-pendant-tinyweb \
38+
--tag="${TRAVIS_BRANCH}" \
39+
--name="${TRAVIS_BRANCH}" \
40+
--body="${COMMIT_LOG}" \
41+
"releases/${RELEASE}.zip"
42+
fi
3143
fi
3244
3345
before_deploy:

github-release.js

Lines changed: 197 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,197 @@
1+
#!/usr/bin/env node
2+
/* eslint no-console: 0 */
3+
/* eslint max-len: 0 */
4+
import path from 'path';
5+
import _ from 'lodash';
6+
import GitHubApi from 'github';
7+
import program from 'commander';
8+
import pkg from './package.json';
9+
10+
program
11+
.version(pkg.version)
12+
.option('-T, --token <token>', 'OAuth2 token')
13+
.option('-o, --owner <owner>', 'owner')
14+
.option('-r, --repo <repo>', 'repo')
15+
.option('-t, --tag <tag>', 'tag')
16+
.option('-n, --name <name>', 'name')
17+
.option('-b, --body <body>', 'body', false)
18+
.parse(process.argv);
19+
20+
const github = new GitHubApi({
21+
version: '3.0.0',
22+
timeout: 5000,
23+
headers: {
24+
'user-agent': 'GitHub-Release-App'
25+
}
26+
});
27+
const files = program.args;
28+
29+
github.authenticate({
30+
type: 'oauth',
31+
token: program.token || process.env.GITHUB_TOKEN
32+
});
33+
34+
const getReleaseByTag = (options) => {
35+
return new Promise((resolve, reject) => {
36+
github.repos.getReleaseByTag(options, (err, res) => {
37+
err ? reject(err) : resolve(res);
38+
});
39+
});
40+
};
41+
42+
const createRelease = (options) => {
43+
return new Promise((resolve, reject) => {
44+
github.repos.createRelease(options, (err, res) => {
45+
err ? reject(err) : resolve(res);
46+
});
47+
});
48+
};
49+
50+
const editRelease = (options) => {
51+
return new Promise((resolve, reject) => {
52+
github.repos.editRelease(options, (err, res) => {
53+
err ? reject(err) : resolve(res);
54+
});
55+
});
56+
};
57+
58+
const getAssets = (options) => {
59+
return new Promise((resolve, reject) => {
60+
github.repos.getAssets(options, (err, res) => {
61+
err ? reject(err) : resolve(res);
62+
});
63+
});
64+
};
65+
66+
const deleteAsset = (options) => {
67+
return new Promise((resolve, reject) => {
68+
github.repos.deleteAsset(options, (err, res) => {
69+
err ? reject(err) : resolve(res);
70+
});
71+
});
72+
};
73+
74+
const uploadAsset = (options) => {
75+
return new Promise((resolve, reject) => {
76+
github.repos.uploadAsset(options, (err, res) => {
77+
err ? reject(err) : resolve(res);
78+
});
79+
});
80+
};
81+
82+
const main = async () => {
83+
const { owner, repo, tag, name, body } = program;
84+
85+
try {
86+
console.log('> releases#getReleaseByTag');
87+
let release = await getReleaseByTag({
88+
owner: owner,
89+
repo: repo,
90+
tag: tag
91+
});
92+
if (!release) {
93+
console.log('> releases#createRelease');
94+
release = await createRelease({
95+
owner: owner,
96+
repo: repo,
97+
tag_name: tag,
98+
name: name || tag,
99+
body: body || ''
100+
});
101+
console.log('ok', release);
102+
} else if (release.body !== body) {
103+
console.log('> releases#editRelease');
104+
let releaseOptions = {
105+
owner: owner,
106+
repo: repo,
107+
id: release.id,
108+
tag_name: tag,
109+
name: name || tag
110+
};
111+
if (body) {
112+
releaseOptions.body = body || '';
113+
}
114+
release = await editRelease(releaseOptions);
115+
console.log('ok', release);
116+
}
117+
118+
console.log('> releases#getAssets');
119+
let assets = await getAssets({
120+
owner: owner,
121+
repo: repo,
122+
id: release.id
123+
});
124+
console.log('assets=%d', assets.length);
125+
126+
assets = _.filter(assets, (asset) => {
127+
// Example:
128+
// 'cnc-1.1.0-latest-08c256a-linux-x64.tar.gz'
129+
// ["cnc-1.1.0-latest-08c256a-linux-x64.tar.gz", "cnc", "1.1.0-latest-08c256a", "linux", "x64", "tar.gz"]
130+
const pattern = new RegExp(/([a-zA-Z0-9][a-zA-Z0-9\-]*)\-(\d+\.\d+\.\d+(?:\-[a-zA-Z0-9][a-zA-Z0-9\-]*)?)(?:\-(mac|win|linux|tinyweb))(?:(?:\-([a-zA-Z0-9_\-]+))?\.(.*))/);
131+
132+
return _.some(files, (file) => {
133+
const r1 = asset.name.match(pattern);
134+
const r2 = path.basename(file).match(pattern);
135+
136+
if ((r1 === null) || (r2 === null)) {
137+
console.error('Unable to match file: asset="%s", file="%s"', asset.name, path.basename(file));
138+
return false;
139+
}
140+
141+
// 0: full
142+
// 1: name
143+
// 2: version
144+
// 3: platform
145+
// 4: arch
146+
// 5: extname
147+
148+
// Skip checking for #0 (full) and #2 (version)
149+
r1[0] = r1[2] = undefined;
150+
r2[0] = r2[2] = undefined;
151+
152+
return _.isEqual(_.compact(r1), _.compact(r2));
153+
});
154+
});
155+
156+
if (assets.length > 0) {
157+
console.log('> releases#deleteAsset');
158+
for (let i = 0; i < assets.length; ++i) {
159+
const asset = assets[i];
160+
console.log('#%d', i + 1, {
161+
id: asset.id,
162+
name: asset.name,
163+
label: asset.label,
164+
state: asset.state,
165+
size: asset.size,
166+
download_count: asset.download_count,
167+
created_at: asset.created_at,
168+
updated_at: asset.updated_at
169+
});
170+
await deleteAsset({
171+
owner: owner,
172+
repo: repo,
173+
id: asset.id
174+
});
175+
}
176+
}
177+
178+
if (files.length > 0) {
179+
console.log('> releases#uploadAsset');
180+
for (let i = 0; i < files.length; ++i) {
181+
const file = files[i];
182+
console.log('#%d name="%s" filePath="%s"', i + 1, path.basename(file), file);
183+
await uploadAsset({
184+
owner: owner,
185+
repo: repo,
186+
id: release.id,
187+
filePath: file,
188+
name: path.basename(file)
189+
});
190+
}
191+
}
192+
} catch (err) {
193+
console.error(err);
194+
}
195+
};
196+
197+
main();

package.json

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,8 @@
44
"description": "A tiny web console for small 320x240 LCD display",
55
"homepage": "https://github.com/cncjs/cncjs-pendant-tinyweb",
66
"author": "Cheton Wu <cheton@gmail.com>",
7-
"bin": {
8-
},
9-
"files": [
10-
],
7+
"bin": {},
8+
"files": [],
119
"repository": {
1210
"type": "git",
1311
"url": "git@github.com:cncjs/cncjs-pendant-tinyweb.git"
@@ -22,8 +20,8 @@
2220
"pendant",
2321
"tinyweb"
2422
],
25-
"dependencies": {
26-
},
23+
"dependencies": {},
2724
"devDependencies": {
25+
"github": "^8.1.1"
2826
}
2927
}

0 commit comments

Comments
 (0)