Skip to content

Commit 2a6144c

Browse files
committed
Merge pull request electron#112 from electron/release-script
Create release script
2 parents d4628fb + 5847338 commit 2a6144c

File tree

3 files changed

+167
-1
lines changed

3 files changed

+167
-1
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
node_modules
22
out
3+
npm-debug.log

package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
{
22
"name": "electron-api-demos",
3-
"version": "1.0.0",
3+
"version": "0.1.0",
44
"description": "Electron interactive API demos",
5+
"private": true,
56
"main": "main.js",
67
"scripts": {
78
"start": "electron .",
@@ -40,6 +41,7 @@
4041
"electron-packager": "^6.0.0",
4142
"electron-prebuilt": "^0.37.2",
4243
"mocha": "^2.3.4",
44+
"request": "^2.70.0",
4345
"spectron": "~1.37.0",
4446
"standard-format": "^2.1.1"
4547
},

script/release

Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
#!/usr/bin/env node
2+
3+
const childProcess = require('child_process')
4+
const fs = require('fs')
5+
const path = require('path')
6+
const request = require('request')
7+
const util = require('util')
8+
9+
const token = process.env.ELECTRON_API_DEMO_GITHUB_TOKEN
10+
const version = require('../package').version
11+
12+
checkToken()
13+
.then(zipAssets)
14+
.then(createRelease)
15+
.then(uploadAssets)
16+
.then(publishRelease)
17+
.catch((error) => {
18+
console.error(error.message || error)
19+
process.exit(1)
20+
})
21+
22+
function checkToken () {
23+
if (!token) {
24+
return Promise.reject('ELECTRON_API_DEMO_GITHUB_TOKEN environment variable not set\nSet it to a token with repo scope created from https://github.com/settings/tokens/new')
25+
} else {
26+
return Promise.resolve(token)
27+
}
28+
}
29+
30+
function zipAsset (asset) {
31+
return new Promise((resolve, reject) => {
32+
const assetBase = path.basename(asset.path)
33+
const assetDirectory = path.dirname(asset.path)
34+
console.log(`Zipping ${assetBase} to ${asset.name}`)
35+
36+
if (!fs.existsSync(asset.path)) {
37+
return reject(new Error(`${asset.path} does not exist`))
38+
}
39+
40+
const zipCommand = `zip --recurse-paths --symlinks '${asset.name}' '${assetBase}'`
41+
const options = {cwd: assetDirectory, maxBuffer: Infinity}
42+
childProcess.exec(zipCommand, options, (error) => {
43+
if (error) {
44+
reject(error)
45+
} else {
46+
asset.zip = path.join(assetDirectory, asset.name)
47+
resolve(asset)
48+
}
49+
})
50+
})
51+
}
52+
53+
function zipAssets () {
54+
const assets = [{
55+
name: 'electron-api-demos-mac.zip',
56+
path: path.join(__dirname, '..', 'out', 'Electron API Demos-darwin-x64', 'Electron API Demos.app')
57+
},
58+
{
59+
name: 'electron-api-demos-windows.zip',
60+
path: path.join(__dirname, '..', 'out', 'Electron API Demos-win32-ia32')
61+
},
62+
{
63+
name: 'electron-api-demos-linux.zip',
64+
path: path.join(__dirname, '..', 'out', 'Electron API Demos-linux-x64')
65+
}]
66+
return Promise.all(assets.map(zipAsset))
67+
}
68+
69+
function createRelease (assets) {
70+
const options = {
71+
uri: 'https://api.github.com/repos/electron/electron-api-demos/releases',
72+
headers: {
73+
Authorization: `token ${token}`,
74+
'User-Agent': `node/${process.versions.node}`
75+
},
76+
json: {
77+
tag_name: `v${version}`,
78+
target_commitish: 'master',
79+
name: version,
80+
body: 'An awesome new release :tada:',
81+
draft: true,
82+
prerelease: true
83+
}
84+
}
85+
86+
return new Promise((resolve, reject) => {
87+
console.log('Creating new draft release')
88+
89+
request.post(options, (error, response, body) => {
90+
if (error) {
91+
return reject(Error(`Request failed: ${error.message || error}`))
92+
}
93+
if (response.statusCode !== 201) {
94+
return reject(Error(`Non-201 response: ${response.statusCode}\n${util.inspect(body)}`))
95+
}
96+
97+
resolve({assets: assets, draft: body})
98+
})
99+
})
100+
}
101+
102+
function uploadAsset (release, asset) {
103+
const options = {
104+
uri: release.upload_url.replace(/\{.*$/, `?name=${asset.name}`),
105+
headers: {
106+
Authorization: `token ${token}`,
107+
'Content-Type': 'application/zip',
108+
'Content-Length': fs.statSync(asset.zip).size,
109+
'User-Agent': `node/${process.versions.node}`
110+
}
111+
}
112+
113+
return new Promise((resolve, reject) => {
114+
console.log(`Uploading ${asset.name} as release asset`)
115+
116+
const assetRequest = request.post(options, (error, response, body) => {
117+
if (error) {
118+
return reject(Error(`Uploading asset failed: ${error.message || error}`))
119+
}
120+
if (response.statusCode >= 400) {
121+
return reject(Error(`400+ response: ${response.statusCode}\n${util.inspect(body)}`))
122+
}
123+
124+
resolve(asset)
125+
})
126+
fs.createReadStream(asset.zip).pipe(assetRequest)
127+
})
128+
}
129+
130+
function uploadAssets (release) {
131+
return Promise.all(release.assets.map((asset) => {
132+
return uploadAsset(release.draft, asset)
133+
})).then(() => release)
134+
}
135+
136+
function publishRelease (release) {
137+
const options = {
138+
uri: release.draft.url,
139+
headers: {
140+
Authorization: `token ${token}`,
141+
'User-Agent': `node/${process.versions.node}`
142+
},
143+
json: {
144+
draft: false
145+
}
146+
}
147+
148+
return new Promise((resolve, reject) => {
149+
console.log('Publishing release')
150+
151+
request.post(options, (error, response, body) => {
152+
if (error) {
153+
return reject(Error(`Request failed: ${error.message || error}`))
154+
}
155+
if (response.statusCode !== 200) {
156+
return reject(Error(`Non-200 response: ${response.statusCode}\n${util.inspect(body)}`))
157+
}
158+
159+
console.log(body.html_url)
160+
resolve(body)
161+
})
162+
})
163+
}

0 commit comments

Comments
 (0)