Move github release checking to node.js

Our upload script was relying on an old python script to find the GitHub release for uploading.
This commit is contained in:
John Kleinschmidt 2018-07-09 18:46:31 -04:00 committed by Electron Bot
parent d478906f9c
commit d6f2c26b0f
3 changed files with 63 additions and 167 deletions

37
script/find-release.js Normal file
View file

@ -0,0 +1,37 @@
const GitHub = require('github')
const github = new GitHub()
if (process.argv.length < 3) {
console.log('Usage: find-release version')
process.exit(1)
}
const version = process.argv[2]
async function findRelease () {
github.authenticate({type: 'token', token: process.env.ELECTRON_GITHUB_TOKEN})
let releases = await github.repos.getReleases({
owner: 'electron',
repo: 'electron'
})
let targetRelease = releases.data.find(release => {
return release.tag_name === version
})
let returnObject = {}
if (targetRelease) {
returnObject = {
id: targetRelease.id,
draft: targetRelease.draft,
exists: true
}
} else {
returnObject = {
exists: false,
draft: false
}
}
console.log(JSON.stringify(returnObject))
}
findRelease()

View file

@ -1,76 +0,0 @@
#!/usr/bin/env python
import json
import os
import re
import sys
REQUESTS_DIR = os.path.abspath(os.path.join(__file__, '..', '..', '..',
'vendor', 'requests'))
sys.path.append(os.path.join(REQUESTS_DIR, 'build', 'lib'))
sys.path.append(os.path.join(REQUESTS_DIR, 'build', 'lib.linux-x86_64-2.7'))
import requests
GITHUB_URL = 'https://api.github.com'
GITHUB_UPLOAD_ASSET_URL = 'https://uploads.github.com'
class GitHub:
def __init__(self, access_token):
self._authorization = 'token %s' % access_token
pattern = '^/repos/{0}/{0}/releases/{1}/assets$'.format('[^/]+', '[0-9]+')
self._releases_upload_api_pattern = re.compile(pattern)
def __getattr__(self, attr):
return _Callable(self, '/%s' % attr)
def send(self, method, path, **kw):
if not 'headers' in kw:
kw['headers'] = dict()
headers = kw['headers']
headers['Authorization'] = self._authorization
headers['Accept'] = 'application/vnd.github.manifold-preview'
# Switch to a different domain for the releases uploading API.
if self._releases_upload_api_pattern.match(path):
url = '%s%s' % (GITHUB_UPLOAD_ASSET_URL, path)
else:
url = '%s%s' % (GITHUB_URL, path)
# Data are sent in JSON format.
if 'data' in kw:
kw['data'] = json.dumps(kw['data'])
r = getattr(requests, method)(url, **kw).json()
if 'message' in r:
raise Exception(json.dumps(r, indent=2, separators=(',', ': ')))
return r
class _Executable:
def __init__(self, gh, method, path):
self._gh = gh
self._method = method
self._path = path
def __call__(self, **kw):
return self._gh.send(self._method, self._path, **kw)
class _Callable(object):
def __init__(self, gh, name):
self._gh = gh
self._name = name
def __call__(self, *args):
if len(args) == 0:
return self
name = '%s/%s' % (self._name, '/'.join([str(arg) for arg in args]))
return _Callable(self._gh, name)
def __getattr__(self, attr):
if attr in ['get', 'put', 'post', 'patch', 'delete']:
return _Executable(self._gh, attr, self._name)
name = '%s/%s' % (self._name, attr)
return _Callable(self._gh, name)

View file

@ -4,6 +4,7 @@ import argparse
import datetime import datetime
import errno import errno
import hashlib import hashlib
import json
import os import os
import subprocess import subprocess
import sys import sys
@ -14,7 +15,6 @@ from lib.config import PLATFORM, get_target_arch, get_env_var, s3_config, \
get_zip_name get_zip_name
from lib.util import electron_gyp, execute, get_electron_version, \ from lib.util import electron_gyp, execute, get_electron_version, \
parse_version, scoped_cwd, s3put parse_version, scoped_cwd, s3put
from lib.github import GitHub
ELECTRON_REPO = 'electron/electron' ELECTRON_REPO = 'electron/electron'
@ -50,58 +50,40 @@ def main():
sys.stderr.flush() sys.stderr.flush()
return 1 return 1
github = GitHub(auth_token())
releases = github.repos(ELECTRON_REPO).releases.get()
tag_exists = False tag_exists = False
release = None release = get_release(args.version)
for r in releases: if not release['draft']:
if not r['draft'] and r['tag_name'] == args.version: tag_exists = True
release = r
tag_exists = True
break
if not args.upload_to_s3: if not args.upload_to_s3:
assert release['exists'], 'Release does not exist; cannot upload to GitHub!'
assert tag_exists == args.overwrite, \ assert tag_exists == args.overwrite, \
'You have to pass --overwrite to overwrite a published release' 'You have to pass --overwrite to overwrite a published release'
if not args.overwrite:
release = create_or_get_release_draft(github, releases, args.version,
tag_exists)
elif release is None:
release = dict(tag_name=args.version)
# Upload Electron files.
# Upload Electron with GitHub Releases API. upload_electron(release, os.path.join(DIST_DIR, DIST_NAME), args)
upload_electron(github, release, os.path.join(DIST_DIR, DIST_NAME), args)
if get_target_arch() != 'mips64el': if get_target_arch() != 'mips64el':
upload_electron(github, release, os.path.join(DIST_DIR, SYMBOLS_NAME), args) upload_electron(release, os.path.join(DIST_DIR, SYMBOLS_NAME), args)
if PLATFORM == 'darwin': if PLATFORM == 'darwin':
upload_electron(github, release, os.path.join(DIST_DIR, upload_electron(release, os.path.join(DIST_DIR, 'electron-api.json'), args)
'electron-api.json'), args) upload_electron(release, os.path.join(DIST_DIR, 'electron.d.ts'), args)
upload_electron(github, release, os.path.join(DIST_DIR, 'electron.d.ts'), upload_electron(release, os.path.join(DIST_DIR, DSYM_NAME), args)
args)
upload_electron(github, release, os.path.join(DIST_DIR, DSYM_NAME),
args)
elif PLATFORM == 'win32': elif PLATFORM == 'win32':
upload_electron(github, release, os.path.join(DIST_DIR, PDB_NAME), upload_electron(release, os.path.join(DIST_DIR, PDB_NAME), args)
args)
# Upload free version of ffmpeg. # Upload free version of ffmpeg.
ffmpeg = get_zip_name('ffmpeg', ELECTRON_VERSION) ffmpeg = get_zip_name('ffmpeg', ELECTRON_VERSION)
upload_electron(github, release, os.path.join(DIST_DIR, ffmpeg), upload_electron(release, os.path.join(DIST_DIR, ffmpeg), args)
args)
chromedriver = get_zip_name('chromedriver', ELECTRON_VERSION) chromedriver = get_zip_name('chromedriver', ELECTRON_VERSION)
upload_electron(github, release, os.path.join(DIST_DIR, chromedriver), upload_electron(release, os.path.join(DIST_DIR, chromedriver), args)
args)
mksnapshot = get_zip_name('mksnapshot', ELECTRON_VERSION) mksnapshot = get_zip_name('mksnapshot', ELECTRON_VERSION)
upload_electron(github, release, os.path.join(DIST_DIR, mksnapshot), upload_electron(release, os.path.join(DIST_DIR, mksnapshot), args)
args)
if get_target_arch().startswith('arm'): if get_target_arch().startswith('arm'):
# Upload the x64 binary for arm/arm64 mksnapshot # Upload the x64 binary for arm/arm64 mksnapshot
mksnapshot = get_zip_name('mksnapshot', ELECTRON_VERSION, 'x64') mksnapshot = get_zip_name('mksnapshot', ELECTRON_VERSION, 'x64')
upload_electron(github, release, os.path.join(DIST_DIR, mksnapshot), upload_electron(release, os.path.join(DIST_DIR, mksnapshot), args)
args)
if not tag_exists and not args.upload_to_s3: if not tag_exists and not args.upload_to_s3:
# Upload symbols to symbol server. # Upload symbols to symbol server.
@ -167,79 +149,26 @@ def dist_newer_than_head():
return dist_time > int(head_time) return dist_time > int(head_time)
def get_text_with_editor(name): def upload_electron(release, file_path, args):
editor = os.environ.get('EDITOR', 'nano')
initial_message = '\n# Please enter the body of your release note for %s.' \
% name
t = tempfile.NamedTemporaryFile(suffix='.tmp', delete=False)
t.write(initial_message)
t.close()
subprocess.call([editor, t.name])
text = ''
for line in open(t.name, 'r'):
if len(line) == 0 or line[0] != '#':
text += line
os.unlink(t.name)
return text
def create_or_get_release_draft(github, releases, tag, tag_exists):
# Search for existing draft.
for release in releases:
if release['draft'] and release['tag_name'] == tag:
return release
if tag_exists:
tag = 'do-not-publish-me'
return create_release_draft(github, tag)
def create_release_draft(github, tag):
name = '{0} {1} beta'.format(PROJECT_NAME, tag)
if os.environ.has_key('CI'):
body = '(placeholder)'
else:
body = get_text_with_editor(name)
if body == '':
sys.stderr.write('Quit due to empty release note.\n')
sys.exit(0)
data = dict(tag_name=tag, name=name, body=body, draft=True, prerelease=True)
r = github.repos(ELECTRON_REPO).releases.post(data=data)
return r
def upload_electron(github, release, file_path, args):
filename = os.path.basename(file_path) filename = os.path.basename(file_path)
# if upload_to_s3 is set, skip github upload. # if upload_to_s3 is set, skip github upload.
if args.upload_to_s3: if args.upload_to_s3:
bucket, access_key, secret_key = s3_config() bucket, access_key, secret_key = s3_config()
key_prefix = 'electron-artifacts/{0}_{1}'.format(release['tag_name'], key_prefix = 'electron-artifacts/{0}_{1}'.format(args.version,
args.upload_timestamp) args.upload_timestamp)
s3put(bucket, access_key, secret_key, os.path.dirname(file_path), s3put(bucket, access_key, secret_key, os.path.dirname(file_path),
key_prefix, [file_path]) key_prefix, [file_path])
upload_sha256_checksum(release['tag_name'], file_path, key_prefix) upload_sha256_checksum(args.version, file_path, key_prefix)
s3url = 'https://gh-contractor-zcbenz.s3.amazonaws.com' s3url = 'https://gh-contractor-zcbenz.s3.amazonaws.com'
print '{0} uploaded to {1}/{2}/{0}'.format(filename, s3url, key_prefix) print '{0} uploaded to {1}/{2}/{0}'.format(filename, s3url, key_prefix)
return return
# Delete the original file before uploading in CI.
if os.environ.has_key('CI'):
try:
for asset in release['assets']:
if asset['name'] == filename:
github.repos(ELECTRON_REPO).releases.assets(asset['id']).delete()
except Exception:
pass
# Upload the file. # Upload the file.
upload_io_to_github(release, filename, file_path) upload_io_to_github(release, filename, file_path)
# Upload the checksum file. # Upload the checksum file.
upload_sha256_checksum(release['tag_name'], file_path) upload_sha256_checksum(args.version, file_path)
def upload_io_to_github(release, filename, filepath): def upload_io_to_github(release, filename, filepath):
@ -273,6 +202,12 @@ def auth_token():
return token return token
def get_release(version):
script_path = os.path.join(SOURCE_ROOT, 'script', 'find-release.js')
release_info = execute(['node', script_path, version])
release = json.loads(release_info)
return release
if __name__ == '__main__': if __name__ == '__main__':
import sys import sys
sys.exit(main()) sys.exit(main())