summaryrefslogtreecommitdiffstats
path: root/dist/chromium/publish-beta.py
diff options
context:
space:
mode:
Diffstat (limited to 'dist/chromium/publish-beta.py')
-rwxr-xr-xdist/chromium/publish-beta.py190
1 files changed, 190 insertions, 0 deletions
diff --git a/dist/chromium/publish-beta.py b/dist/chromium/publish-beta.py
new file mode 100755
index 0000000..5a6e19f
--- /dev/null
+++ b/dist/chromium/publish-beta.py
@@ -0,0 +1,190 @@
+#!/usr/bin/env python3
+
+import datetime
+import json
+import os
+import re
+import requests
+import shutil
+import subprocess
+import sys
+import tempfile
+import time
+import zipfile
+
+from string import Template
+
+# - Download target (raw) uBlock0.chromium.zip from GitHub
+# - This is referred to as "raw" package
+# - This will fail if not a dev build
+# - Upload uBlock0.chromium.zip to Chrome store
+# - Publish uBlock0.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, '..'))
+
+# 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)
+
+cs_extension_id = 'cgbcahbpdhpcegmbfconppldiemgcoii'
+tmpdir = tempfile.TemporaryDirectory()
+raw_zip_filename = 'uBlock0_' + version + '.chromium.zip'
+raw_zip_filepath = os.path.join(tmpdir.name, raw_zip_filename)
+github_owner = 'gorhill'
+github_repo = 'uBlock'
+
+# 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 uBlock0.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.')