Source code

Revision control

Copy as Markdown

Other Tools

#!/usr/bin/env python3
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this file,
# You can obtain one at http://mozilla.org/MPL/2.0/.
import pathlib
import json
import urllib.request
import re
import subprocess
import sys
class Logger:
@classmethod
def info(cls, s):
print('[INFO]', s)
# Flush to make it apeear immediately in automation log.
sys.stdout.flush()
@classmethod
def fetch(cls, url):
cls.info(f'Fetching {url}')
@classmethod
def cmd(cls, cmd):
def format_cmd(s):
if ' ' in s:
escaped = s.replace('"', '\"')
return f'"{escaped}"'
return s
formatted_command = ' '.join(list(map(format_cmd, cmd)))
cls.info(f'$ {formatted_command}')
class GitRepository:
def __init__(self, path):
self.path = path
self.git_dir = self.path / '.git'
if not self.git_dir.exists():
print(f'{self.path} is not a Git repository.', file=sys.stderr)
sys.exit(1)
def get_output(self, *args):
cmd = ['git'] + list(args)
Logger.cmd(cmd)
output = subprocess.run(cmd,
capture_output=True,
cwd=self.path)
return output.stdout.decode()
def run(self, *args):
cmd = ['git'] + list(args)
Logger.cmd(cmd)
subprocess.run(cmd,
check=True,
cwd=self.path)
def commit_message(self, rev):
return self.get_output('log', '-1', '--pretty=format:%s%n', rev)
class MCRemoteRepository:
@classmethod
def call(cls, name, path):
url = f'{cls.HG_API_URL}{name}{path}'
Logger.fetch(url)
req = urllib.request.Request(url, None, {})
response = urllib.request.urlopen(req)
return response.read()
@classmethod
def call_json(cls, name, path):
return json.loads(cls.call(name, path))
@classmethod
def file(cls, rev, path):
return cls.call('raw-file', f'/{rev}{path}')
class TreeHerder:
@classmethod
def call(cls, name):
url = f'{cls.API_URL}{name}'
Logger.fetch(url)
req = urllib.request.Request(url, None, {
'User-Agent': 'smoosh-tools',
})
response = urllib.request.urlopen(req)
return response.read()
@classmethod
def call_json(cls, name):
return json.loads(cls.call(name))
@classmethod
def push_id(cls, rev):
push = cls.call_json(f'project/mozilla-central/push/?full=true&format=json&count=1&revision={rev}')
return push['results'][0]['id']
@classmethod
def jobs(cls, push_id):
push = cls.call_json(f'jobs/?push_id={push_id}&format=json')
count = push['count']
results = []
results += push['results']
page = 2
while len(results) < count:
push = cls.call_json(f'jobs/?push_id={push_id}&format=json&page={page}')
results += push['results']
page += 1
return results
class Status:
def run(is_ci):
Logger.info('Fetching ci_generated branch')
jsparagus = GitRepository(pathlib.Path('./'))
jsparagus.run('fetch', 'origin', 'ci_generated')
Logger.info('Checking mozilla-central tip revision')
m_c_rev = MCRemoteRepository.call_json('json-log', '/tip/')['node']
cargo_file = MCRemoteRepository.file(
m_c_rev,
'/js/src/frontend/smoosh/Cargo.toml'
).decode()
m = re.search('rev = "(.+)"', cargo_file)
ci_generated_rev = m.group(1)
Logger.info('Checking jsparagus referred by mozilla-central')
message = jsparagus.commit_message(ci_generated_rev)
m = re.search('for ([A-Fa-f0-9]+)', message)
master_rev = m.group(1)
Logger.info('Checking build status')
push_id = TreeHerder.push_id(m_c_rev)
jobs = TreeHerder.jobs(push_id)
nonunified_job = None
smoosh_job = None
for job in jobs:
if 'spidermonkey-sm-nonunified-linux64/debug' in job:
nonunified_job = job
if 'spidermonkey-sm-smoosh-linux64/debug' in job:
smoosh_job = job
def get_result(job):
if job:
if 'completed' in job:
if 'success' in job:
return 'OK'
else:
return 'NG'
else:
return 'not yet finished'
else:
return 'unknown'
nonunified_result = get_result(nonunified_job)
smoosh_result = get_result(smoosh_job)
if is_ci:
print(f'##[set-output name=mc;]{m_c_rev}')
print(f'##[set-output name=jsparagus;]{master_rev}')
print(f'##[set-output name=build;]{nonunified_result}')
print(f'##[set-output name=test;]{smoosh_result}')
else:
print(f'mozilla-central tip: {m_c_rev}')
print(f'referred jsparagus revision: {master_rev}')
print(f'Build status:')
print(f' Build with --enable-smoosh: {nonunified_result}')
print(f' Test with --smoosh: {smoosh_result}')
is_ci = False
if len(sys.argv) > 1:
if sys.argv[1] == 'ci':
is_ci = True
Status.run(is_ci)