upload.py 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. #!/usr/bin/env python
  2. import argparse
  3. import datetime
  4. import errno
  5. import hashlib
  6. import json
  7. import os
  8. import shutil
  9. import subprocess
  10. import sys
  11. import tempfile
  12. from io import StringIO
  13. from lib.config import PLATFORM, get_target_arch, get_env_var, s3_config, \
  14. get_zip_name
  15. from lib.util import electron_gyp, execute, get_electron_version, \
  16. parse_version, scoped_cwd, s3put
  17. ELECTRON_REPO = 'electron/electron'
  18. ELECTRON_VERSION = get_electron_version()
  19. PROJECT_NAME = electron_gyp()['project_name%']
  20. PRODUCT_NAME = electron_gyp()['product_name%']
  21. SOURCE_ROOT = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
  22. OUT_DIR = os.path.join(SOURCE_ROOT, 'out', 'R')
  23. DIST_DIR = os.path.join(SOURCE_ROOT, 'dist')
  24. DIST_NAME = get_zip_name(PROJECT_NAME, ELECTRON_VERSION)
  25. SYMBOLS_NAME = get_zip_name(PROJECT_NAME, ELECTRON_VERSION, 'symbols')
  26. DSYM_NAME = get_zip_name(PROJECT_NAME, ELECTRON_VERSION, 'dsym')
  27. PDB_NAME = get_zip_name(PROJECT_NAME, ELECTRON_VERSION, 'pdb')
  28. def main():
  29. args = parse_args()
  30. if args.upload_to_s3:
  31. utcnow = datetime.datetime.utcnow()
  32. args.upload_timestamp = utcnow.strftime('%Y-%m-%d_%H:%M:%S')
  33. if not dist_newer_than_head():
  34. run_python_script('create-dist.py')
  35. build_version = get_electron_build_version()
  36. if not ELECTRON_VERSION.startswith(build_version):
  37. error = 'Tag name ({0}) should match build version ({1})\n'.format(
  38. ELECTRON_VERSION, build_version)
  39. sys.stderr.write(error)
  40. sys.stderr.flush()
  41. return 1
  42. tag_exists = False
  43. release = get_release(args.version)
  44. if not release['draft']:
  45. tag_exists = True
  46. if not args.upload_to_s3:
  47. assert release['exists'], 'Release does not exist; cannot upload to GitHub!'
  48. assert tag_exists == args.overwrite, \
  49. 'You have to pass --overwrite to overwrite a published release'
  50. # Upload Electron files.
  51. upload_electron(release, os.path.join(DIST_DIR, DIST_NAME), args)
  52. if get_target_arch() != 'mips64el':
  53. upload_electron(release, os.path.join(DIST_DIR, SYMBOLS_NAME), args)
  54. if PLATFORM == 'darwin':
  55. upload_electron(release, os.path.join(DIST_DIR, 'electron-api.json'), args)
  56. upload_electron(release, os.path.join(DIST_DIR, 'electron.d.ts'), args)
  57. upload_electron(release, os.path.join(DIST_DIR, DSYM_NAME), args)
  58. elif PLATFORM == 'win32':
  59. upload_electron(release, os.path.join(DIST_DIR, PDB_NAME), args)
  60. # Upload free version of ffmpeg.
  61. ffmpeg = get_zip_name('ffmpeg', ELECTRON_VERSION)
  62. upload_electron(release, os.path.join(DIST_DIR, ffmpeg), args)
  63. chromedriver = get_zip_name('chromedriver', ELECTRON_VERSION)
  64. upload_electron(release, os.path.join(DIST_DIR, chromedriver), args)
  65. mksnapshot = get_zip_name('mksnapshot', ELECTRON_VERSION)
  66. upload_electron(release, os.path.join(DIST_DIR, mksnapshot), args)
  67. if get_target_arch().startswith('arm'):
  68. # Upload the x64 binary for arm/arm64 mksnapshot
  69. mksnapshot = get_zip_name('mksnapshot', ELECTRON_VERSION, 'x64')
  70. upload_electron(release, os.path.join(DIST_DIR, mksnapshot), args)
  71. if PLATFORM == 'win32' and not tag_exists and not args.upload_to_s3:
  72. # Upload PDBs to Windows symbol server.
  73. run_python_script('upload-windows-pdb.py')
  74. # Upload node headers.
  75. run_python_script('create-node-headers.py', '-v', args.version)
  76. run_python_script('upload-node-headers.py', '-v', args.version)
  77. def parse_args():
  78. parser = argparse.ArgumentParser(description='upload distribution file')
  79. parser.add_argument('-v', '--version', help='Specify the version',
  80. default=ELECTRON_VERSION)
  81. parser.add_argument('-o', '--overwrite',
  82. help='Overwrite a published release',
  83. action='store_true')
  84. parser.add_argument('-p', '--publish-release',
  85. help='Publish the release',
  86. action='store_true')
  87. parser.add_argument('-s', '--upload_to_s3',
  88. help='Upload assets to s3 bucket',
  89. dest='upload_to_s3',
  90. action='store_true',
  91. default=False,
  92. required=False)
  93. return parser.parse_args()
  94. def run_python_script(script, *args):
  95. script_path = os.path.join(SOURCE_ROOT, 'script', script)
  96. return execute([sys.executable, script_path] + list(args))
  97. def get_electron_build_version():
  98. if get_target_arch().startswith('arm') or os.environ.has_key('CI'):
  99. # In CI we just build as told.
  100. return ELECTRON_VERSION
  101. if PLATFORM == 'darwin':
  102. electron = os.path.join(SOURCE_ROOT, 'out', 'R',
  103. '{0}.app'.format(PRODUCT_NAME), 'Contents',
  104. 'MacOS', PRODUCT_NAME)
  105. elif PLATFORM == 'win32':
  106. electron = os.path.join(SOURCE_ROOT, 'out', 'R',
  107. '{0}.exe'.format(PROJECT_NAME))
  108. else:
  109. electron = os.path.join(SOURCE_ROOT, 'out', 'R', PROJECT_NAME)
  110. return subprocess.check_output([electron, '--version']).strip()
  111. def dist_newer_than_head():
  112. with scoped_cwd(SOURCE_ROOT):
  113. try:
  114. head_time = subprocess.check_output(['git', 'log', '--pretty=format:%at',
  115. '-n', '1']).strip()
  116. dist_time = os.path.getmtime(os.path.join(DIST_DIR, DIST_NAME))
  117. except OSError as e:
  118. if e.errno != errno.ENOENT:
  119. raise
  120. return False
  121. return dist_time > int(head_time)
  122. def upload_electron(release, file_path, args):
  123. filename = os.path.basename(file_path)
  124. # if upload_to_s3 is set, skip github upload.
  125. if args.upload_to_s3:
  126. bucket, access_key, secret_key = s3_config()
  127. key_prefix = 'electron-artifacts/{0}_{1}'.format(args.version,
  128. args.upload_timestamp)
  129. s3put(bucket, access_key, secret_key, os.path.dirname(file_path),
  130. key_prefix, [file_path])
  131. upload_sha256_checksum(args.version, file_path, key_prefix)
  132. s3url = 'https://gh-contractor-zcbenz.s3.amazonaws.com'
  133. print '{0} uploaded to {1}/{2}/{0}'.format(filename, s3url, key_prefix)
  134. return
  135. # Upload the file.
  136. upload_io_to_github(release, filename, file_path)
  137. # Upload the checksum file.
  138. upload_sha256_checksum(args.version, file_path)
  139. # Upload ARM assets without the v7l suffix for backwards compatibility
  140. # TODO Remove for 2.0
  141. if 'armv7l' in filename:
  142. arm_filename = filename.replace('armv7l', 'arm')
  143. arm_file_path = os.path.join(os.path.dirname(file_path), arm_filename)
  144. shutil.copy2(file_path, arm_file_path)
  145. upload_electron(release, arm_file_path, args)
  146. def upload_io_to_github(release, filename, filepath):
  147. print 'Uploading %s to Github' % \
  148. (filename)
  149. script_path = os.path.join(SOURCE_ROOT, 'script', 'upload-to-github.js')
  150. execute(['node', script_path, filepath, filename, str(release['id'])])
  151. def upload_sha256_checksum(version, file_path, key_prefix=None):
  152. bucket, access_key, secret_key = s3_config()
  153. checksum_path = '{}.sha256sum'.format(file_path)
  154. if key_prefix is None:
  155. key_prefix = 'atom-shell/tmp/{0}'.format(version)
  156. sha256 = hashlib.sha256()
  157. with open(file_path, 'rb') as f:
  158. sha256.update(f.read())
  159. filename = os.path.basename(file_path)
  160. with open(checksum_path, 'w') as checksum:
  161. checksum.write('{} *{}'.format(sha256.hexdigest(), filename))
  162. s3put(bucket, access_key, secret_key, os.path.dirname(checksum_path),
  163. key_prefix, [checksum_path])
  164. def auth_token():
  165. token = get_env_var('GITHUB_TOKEN')
  166. message = ('Error: Please set the $ELECTRON_GITHUB_TOKEN '
  167. 'environment variable, which is your personal token')
  168. assert token, message
  169. return token
  170. def get_release(version):
  171. script_path = os.path.join(SOURCE_ROOT, 'script', 'find-release.js')
  172. release_info = execute(['node', script_path, version])
  173. release = json.loads(release_info)
  174. return release
  175. if __name__ == '__main__':
  176. import sys
  177. sys.exit(main())