Raymond Hill
7 years ago
No known key found for this signature in database
GPG Key ID: 25E1490B761470C2
2 changed files with 223 additions and 9 deletions
@ -0,0 +1,192 @@ |
|||
#!/usr/bin/env python3 |
|||
|
|||
import datetime |
|||
import json |
|||
import jwt |
|||
import os |
|||
import re |
|||
import requests |
|||
import shutil |
|||
import subprocess |
|||
import sys |
|||
import tempfile |
|||
import time |
|||
import zipfile |
|||
|
|||
from distutils.version import StrictVersion |
|||
from string import Template |
|||
|
|||
# - Download target (raw) uMatrix.chromium.zip from GitHub |
|||
# - This is referred to as "raw" package |
|||
# - This will fail if not a dev build |
|||
# - Upload uMatrix.chromium.zip to Chrome store |
|||
# - Publish uMatrix.chromium.zip to Chrome store |
|||
|
|||
# Find path to project root |
|||
projdir = os.path.split(os.path.abspath(__file__))[0] |
|||
while not os.path.isdir(os.path.join(projdir, '.git')): |
|||
projdir = os.path.normpath(os.path.join(projdir, '..')) |
|||
|
|||
cs_extension_id = 'eckgcipdkhcfghnmincccnhpdmnbefki' |
|||
tmpdir = tempfile.TemporaryDirectory() |
|||
raw_zip_filename = 'uMatrix.chromium.zip' |
|||
raw_zip_filepath = os.path.join(tmpdir.name, raw_zip_filename) |
|||
github_owner = 'gorhill' |
|||
github_repo = 'uMatrix' |
|||
|
|||
# We need a version string to work with |
|||
if len(sys.argv) >= 2 and sys.argv[1]: |
|||
version = sys.argv[1] |
|||
else: |
|||
version = input('Github release version: ') |
|||
version.strip() |
|||
if not re.search('^\d+\.\d+\.\d+(b|rc)\d+$', version): |
|||
print('Error: Invalid version string.') |
|||
exit(1) |
|||
|
|||
# Load/save auth secrets |
|||
# The build directory is excluded from git |
|||
ubo_secrets = dict() |
|||
ubo_secrets_filename = os.path.join(projdir, 'dist', 'build', 'ubo_secrets') |
|||
if os.path.isfile(ubo_secrets_filename): |
|||
with open(ubo_secrets_filename) as f: |
|||
ubo_secrets = json.load(f) |
|||
|
|||
def input_secret(prompt, token): |
|||
if token in ubo_secrets: |
|||
prompt += ' ✔' |
|||
prompt += ': ' |
|||
value = input(prompt).strip() |
|||
if len(value) == 0: |
|||
if token not in ubo_secrets: |
|||
print('Token error:', token) |
|||
exit(1) |
|||
value = ubo_secrets[token] |
|||
elif token not in ubo_secrets or value != ubo_secrets[token]: |
|||
ubo_secrets[token] = value |
|||
exists = os.path.isfile(ubo_secrets_filename) |
|||
with open(ubo_secrets_filename, 'w') as f: |
|||
json.dump(ubo_secrets, f, indent=2) |
|||
if not exists: |
|||
os.chmod(ubo_secrets_filename, 0o600) |
|||
return value |
|||
|
|||
|
|||
# GitHub API token |
|||
github_token = input_secret('Github token', 'github_token') |
|||
github_auth = 'token ' + github_token |
|||
|
|||
# |
|||
# Get metadata from GitHub about the release |
|||
# |
|||
|
|||
# https://developer.github.com/v3/repos/releases/#get-a-single-release |
|||
print('Downloading release info from GitHub...') |
|||
release_info_url = 'https://api.github.com/repos/{0}/{1}/releases/tags/{2}'.format(github_owner, github_repo, version) |
|||
headers = { 'Authorization': github_auth, } |
|||
response = requests.get(release_info_url, headers=headers) |
|||
if response.status_code != 200: |
|||
print('Error: Release not found: {0}'.format(response.status_code)) |
|||
exit(1) |
|||
release_info = response.json() |
|||
|
|||
# |
|||
# Extract URL to raw package from metadata |
|||
# |
|||
|
|||
# Find url for uMatrix.chromium.zip |
|||
raw_zip_url = '' |
|||
for asset in release_info['assets']: |
|||
if asset['name'] == raw_zip_filename: |
|||
raw_zip_url = asset['url'] |
|||
if len(raw_zip_url) == 0: |
|||
print('Error: Release asset URL not found') |
|||
exit(1) |
|||
|
|||
# |
|||
# Download raw package from GitHub |
|||
# |
|||
|
|||
# https://developer.github.com/v3/repos/releases/#get-a-single-release-asset |
|||
print('Downloading raw zip package from GitHub...') |
|||
headers = { |
|||
'Authorization': github_auth, |
|||
'Accept': 'application/octet-stream', |
|||
} |
|||
response = requests.get(raw_zip_url, headers=headers) |
|||
# Redirections are transparently handled: |
|||
# http://docs.python-requests.org/en/master/user/quickstart/#redirection-and-history |
|||
if response.status_code != 200: |
|||
print('Error: Downloading raw package failed -- server error {0}'.format(response.status_code)) |
|||
exit(1) |
|||
with open(raw_zip_filepath, 'wb') as f: |
|||
f.write(response.content) |
|||
print('Downloaded raw package saved as {0}'.format(raw_zip_filepath)) |
|||
|
|||
# |
|||
# Upload to Chrome store |
|||
# |
|||
|
|||
# Auth tokens |
|||
cs_id = input_secret('Chrome store id', 'cs_id') |
|||
cs_secret = input_secret('Chrome store secret', 'cs_secret') |
|||
cs_refresh = input_secret('Chrome store refresh token', 'cs_refresh') |
|||
|
|||
print('Uploading to Chrome store...') |
|||
with open(raw_zip_filepath, 'rb') as f: |
|||
print('Generating access token...') |
|||
auth_url = 'https://accounts.google.com/o/oauth2/token' |
|||
auth_payload = { |
|||
'client_id': cs_id, |
|||
'client_secret': cs_secret, |
|||
'grant_type': 'refresh_token', |
|||
'refresh_token': cs_refresh, |
|||
} |
|||
auth_response = requests.post(auth_url, data=auth_payload) |
|||
if auth_response.status_code != 200: |
|||
print('Error: Auth failed -- server error {0}'.format(auth_response.status_code)) |
|||
print(auth_response.text) |
|||
exit(1) |
|||
response_dict = auth_response.json() |
|||
if 'access_token' not in response_dict: |
|||
print('Error: Auth failed -- no access token') |
|||
exit(1) |
|||
# Prepare access token |
|||
cs_auth = 'Bearer ' + response_dict['access_token'] |
|||
headers = { |
|||
'Authorization': cs_auth, |
|||
'x-goog-api-version': '2', |
|||
} |
|||
# Upload |
|||
print('Uploading package...') |
|||
upload_url = 'https://www.googleapis.com/upload/chromewebstore/v1.1/items/{0}'.format(cs_extension_id) |
|||
upload_response = requests.put(upload_url, headers=headers, data=f) |
|||
f.close() |
|||
if upload_response.status_code != 200: |
|||
print('Upload failed -- server error {0}'.format(upload_response.status_code)) |
|||
print(upload_response.text) |
|||
exit(1) |
|||
response_dict = upload_response.json(); |
|||
if 'uploadState' not in response_dict or response_dict['uploadState'] != 'SUCCESS': |
|||
print('Upload failed -- server error {0}'.format(response_dict['uploadState'])) |
|||
exit(1) |
|||
print('Upload succeeded.') |
|||
# Publish |
|||
print('Publishing package...') |
|||
publish_url = 'https://www.googleapis.com/chromewebstore/v1.1/items/{0}/publish'.format(cs_extension_id) |
|||
headers = { |
|||
'Authorization': cs_auth, |
|||
'x-goog-api-version': '2', |
|||
'Content-Length': '0', |
|||
} |
|||
publish_response = requests.post(publish_url, headers=headers) |
|||
if publish_response.status_code != 200: |
|||
print('Error: Chrome store publishing failed -- server error {0}'.format(publish_response.status_code)) |
|||
exit(1) |
|||
response_dict = publish_response.json(); |
|||
if 'status' not in response_dict or response_dict['status'][0] != 'OK': |
|||
print('Publishing failed -- server error {0}'.format(response_dict['status'])) |
|||
exit(1) |
|||
print('Publishing succeeded.') |
|||
|
|||
print('All done.') |
Write
Preview
Loading…
Cancel
Save
Reference in new issue