blob: 12728ee02dfc5e6b3b9e21b23f1ab7ed45b82880 [file] [log] [blame]
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Copyright 2015 WebAssembly Community Group participants
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
'''
Trigger the EMSDK release workflow on github when HEAD is an LTO release
After an LTO build has finished, check whether all associated builds
have been uploaded. If so, post an API call to GitHub to trigger the
create-release.yml workflow on EMSDK.
LTO builds are builds with touch DEPS.tagged-release and have the
corresponding non-LTO build in their commit message.
'''
import build
import cloud
from google.api_core import exceptions
from google.cloud import secretmanager
import google_crc32c
import os
import re
import requests
import subprocess
import sys
MAX_ATTEMPTS = 3
SECRET_NAME = 'projects/956827487526/secrets/emscripten-releases-token/versions/latest'
# To test this script locally or on a trybot, modify this and lto_sha below
EMSDK_REPO_OWNER = 'emscripten-core'
script_dir = os.path.dirname(os.path.abspath(__file__))
root_dir = os.path.dirname(script_dir)
def get_github_token():
client = secretmanager.SecretManagerServiceClient()
retry = 0
response = None
while retry < MAX_ATTEMPTS:
try:
# Access the latest secret version.
response = client.access_secret_version(
request={'name': SECRET_NAME}, timeout=30.0)
crc32c = google_crc32c.Checksum()
crc32c.update(response.payload.data)
if response.payload.data_crc32c != int(crc32c.hexdigest(), 16):
raise Exception('Secret checksum fail %s' %
response.payload.data_crc32c)
return response.payload.data.decode('UTF-8')
except exceptions.RetryError:
retry += 1
print(
'Fetching OTA from Secret Manager has timed out. '
'Retrying %d' % retry)
# If we come here, we have hit the retry limit. Fail this run.
raise Exception('Failed to fetch the OTA password.')
def trigger_emsdk_workflow(lto, nonlto):
owner = EMSDK_REPO_OWNER
token = get_github_token()
url = f'https://api.github.com/repos/{owner}/emsdk/actions/workflows/create-release.yml/dispatches'
payload = {
'ref': 'main',
'inputs': {
'lto-sha': lto,
'nonlto-sha': nonlto,
}
}
headers = {
'Authorization': f'Bearer {token}',
'Accept': 'application/vnd.github.v3+json'
}
response = requests.post(url, json=payload, headers=headers)
if response.status_code == 204:
print('Workflow dispatch event triggered successfully!')
else:
print('Failed to trigger workflow dispatch event.'
f'Status code: {response.status_code}')
print(response.text)
def main(argv):
deps_file = os.path.join(root_dir, build.RELEASE_DEPS_FILE)
if not build.RevisionModifiesFile(deps_file):
print(f'HEAD revision does not modify {deps_file}')
return 0
lto_sha = subprocess.check_output(['git', 'rev-parse', 'HEAD'],
cwd=root_dir, text=True).strip()
message_body = subprocess.check_output(
['git', 'log', '-1', '--pretty=%b', lto_sha], cwd=root_dir, text=True)
match = re.search('DEPS from revision (.*)', message_body)
if not match:
print('non-LTO DEPS revision not found in commit message')
# TODO: exit with error instead?
# Would make sense if this runs as a test rather than build step
return 0
nonlto_sha = match.group(1)
builds = cloud.ListBuilds(lto_sha)
print('Already-uploaded builds:')
print(builds)
# We expect 2 builds each for Linux and Mac, and one for Windows
builds_done = len(builds)
if builds_done >= 5:
print('All builds found, triggering release workflow.')
trigger_emsdk_workflow(lto_sha, nonlto_sha)
else:
print(f'{builds_done} of 5 builds found, not triggering release workflow.')
if __name__ == '__main__':
sys.exit(main(sys.argv))