Adds schedule_nightly_graph.py
parent
1d865471af
commit
8476587ed6
|
@ -34,7 +34,7 @@ tasks:
|
||||||
$flatten:
|
$flatten:
|
||||||
- queue:scheduler-id:${scheduler_id}
|
- queue:scheduler-id:${scheduler_id}
|
||||||
- queue:create-task:highest:aws-provisioner-v1/gecko-focus
|
- queue:create-task:highest:aws-provisioner-v1/gecko-focus
|
||||||
- project:mobile:fenix:releng:signing:format:autograph_fenix
|
- project:mobile:fenix:releng:signing:format:autograph_apk
|
||||||
- $if: is_mozilla_mobile_repo
|
- $if: is_mozilla_mobile_repo
|
||||||
then:
|
then:
|
||||||
- queue:create-task:highest:scriptworker-prov-v1/mobile-signing-v1
|
- queue:create-task:highest:scriptworker-prov-v1/mobile-signing-v1
|
||||||
|
@ -69,8 +69,7 @@ tasks:
|
||||||
cd ..
|
cd ..
|
||||||
&& git clone ${repository} repository
|
&& git clone ${repository} repository
|
||||||
&& cd repository
|
&& cd repository
|
||||||
&& pip install arrow
|
&& python automation/taskcluster/decision_task_nightly.py \
|
||||||
&& python tools/taskcluster/decision_task_nightly.py \
|
|
||||||
--track ${track} \
|
--track ${track} \
|
||||||
--commit \
|
--commit \
|
||||||
--output /opt/repository/app/build/outputs/apk \
|
--output /opt/repository/app/build/outputs/apk \
|
||||||
|
|
|
@ -43,7 +43,7 @@ android.applicationVariants.all { variant ->
|
||||||
// same version code. Therefore we need to have different version codes for our ARM and x86
|
// same version code. Therefore we need to have different version codes for our ARM and x86
|
||||||
// builds.
|
// builds.
|
||||||
|
|
||||||
// Our generated version code now has a length of 9 (See tools/gradle/versionCode.gradle).
|
// Our generated version code now has a length of 9 (See automation/gradle/versionCode.gradle).
|
||||||
// Our x86 builds need a higher version code to avoid installing ARM builds on an x86 device
|
// Our x86 builds need a higher version code to avoid installing ARM builds on an x86 device
|
||||||
// with ARM compatibility mode.
|
// with ARM compatibility mode.
|
||||||
|
|
||||||
|
|
|
@ -52,7 +52,7 @@ def generate_build_task(apks):
|
||||||
def generate_signing_task(build_task_id, apks, date, is_staging):
|
def generate_signing_task(build_task_id, apks, date, is_staging):
|
||||||
artifacts = ["public/{}".format(os.path.basename(apk)) for apk in apks]
|
artifacts = ["public/{}".format(os.path.basename(apk)) for apk in apks]
|
||||||
|
|
||||||
signing_format = 'autograph_fenix'
|
signing_format = 'autograph_apk'
|
||||||
index_release = 'staging-signed-nightly' if is_staging else 'signed-nightly'
|
index_release = 'staging-signed-nightly' if is_staging else 'signed-nightly'
|
||||||
routes = [
|
routes = [
|
||||||
"index.project.mobile.fenix.{}.nightly.{}.{}.{}.latest".format(index_release, date.year, date.month, date.day),
|
"index.project.mobile.fenix.{}.nightly.{}.{}.{}.latest".format(index_release, date.year, date.month, date.day),
|
||||||
|
@ -139,12 +139,12 @@ if __name__ == "__main__":
|
||||||
description='Create a release pipeline (build, sign, publish) on taskcluster.')
|
description='Create a release pipeline (build, sign, publish) on taskcluster.')
|
||||||
|
|
||||||
parser.add_argument('--track', dest="track", action="store", choices=['nightly', 'staging-nightly'], required=True)
|
parser.add_argument('--track', dest="track", action="store", choices=['nightly', 'staging-nightly'], required=True)
|
||||||
parser.add_argument('--commit', dest="commit", action="store_true", help="commit the google play transaction")
|
parser.add_argument('--commit', action="store_true", help="commit the google play transaction")
|
||||||
parser.add_argument('--apk', dest="apks", metavar="path", action="append", help="Path to APKs to sign and upload",
|
parser.add_argument('--apk', dest="apks", metavar="path", action="append", help="Path to APKs to sign and upload",
|
||||||
required=True)
|
required=True)
|
||||||
parser.add_argument('--output', dest="track", metavar="path", action="store", help="Path to the build output",
|
parser.add_argument('--output', metavar="path", action="store", help="Path to the build output",
|
||||||
required=True)
|
required=True)
|
||||||
parser.add_argument('--date', dest="date", action="store", help="ISO8601 timestamp for build")
|
parser.add_argument('--date', action="store", help="ISO8601 timestamp for build")
|
||||||
|
|
||||||
result = parser.parse_args()
|
result = parser.parse_args()
|
||||||
apks = ["{}/{}".format(result.output, apk) for apk in result.apks]
|
apks = ["{}/{}".format(result.output, apk) for apk in result.apks]
|
||||||
|
|
|
@ -9,11 +9,8 @@ import taskcluster
|
||||||
|
|
||||||
|
|
||||||
class TaskBuilder(object):
|
class TaskBuilder(object):
|
||||||
def __init__(self, task_id, repo_url, branch, commit, owner, source, scheduler_id):
|
def __init__(self, task_id, owner, source, scheduler_id):
|
||||||
self.task_id = task_id
|
self.task_id = task_id
|
||||||
self.repo_url = repo_url
|
|
||||||
self.branch = branch
|
|
||||||
self.commit = commit
|
|
||||||
self.owner = owner
|
self.owner = owner
|
||||||
self.source = source
|
self.source = source
|
||||||
self.scheduler_id = scheduler_id
|
self.scheduler_id = scheduler_id
|
||||||
|
@ -29,7 +26,7 @@ class TaskBuilder(object):
|
||||||
})
|
})
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"workerType": 'github-worker',
|
"workerType": 'gecko-focus',
|
||||||
"taskGroupId": self.task_id,
|
"taskGroupId": self.task_id,
|
||||||
"schedulerId": self.scheduler_id,
|
"schedulerId": self.scheduler_id,
|
||||||
"expires": taskcluster.stringDate(expires),
|
"expires": taskcluster.stringDate(expires),
|
||||||
|
|
|
@ -0,0 +1,101 @@
|
||||||
|
# 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 argparse
|
||||||
|
import datetime
|
||||||
|
import jsone
|
||||||
|
import os
|
||||||
|
import slugid
|
||||||
|
import taskcluster
|
||||||
|
import yaml
|
||||||
|
|
||||||
|
from git import Repo
|
||||||
|
from lib.tasks import schedule_task
|
||||||
|
|
||||||
|
ROOT = os.path.join(os.path.dirname(__file__), '../..')
|
||||||
|
|
||||||
|
|
||||||
|
class InvalidGithubRepositoryError(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def calculate_git_references(root):
|
||||||
|
repo = Repo(root)
|
||||||
|
remote = repo.remote()
|
||||||
|
branch = repo.head.reference
|
||||||
|
|
||||||
|
if not remote.url.startswith('https://github.com'):
|
||||||
|
raise InvalidGithubRepositoryError('expected remote to be a GitHub repository (accessed via HTTPs)')
|
||||||
|
|
||||||
|
url = remote.url[:-4] if remote.url.endswith('.git') else remote.url
|
||||||
|
return url, str(branch), str(branch.commit)
|
||||||
|
|
||||||
|
|
||||||
|
def make_decision_task(params):
|
||||||
|
"""Generate a basic decision task, based on the root .taskcluster.yml"""
|
||||||
|
with open(os.path.join(ROOT, '.taskcluster.yml'), 'rb') as f:
|
||||||
|
taskcluster_yml = yaml.safe_load(f)
|
||||||
|
|
||||||
|
slugids = {}
|
||||||
|
|
||||||
|
def as_slugid(name):
|
||||||
|
if name not in slugids:
|
||||||
|
slugids[name] = slugid.nice()
|
||||||
|
return slugids[name]
|
||||||
|
|
||||||
|
# provide a similar JSON-e context to what taskcluster-github provides
|
||||||
|
context = {
|
||||||
|
'tasks_for': 'cron',
|
||||||
|
'cron': {
|
||||||
|
'task_id': params['cron_task_id']
|
||||||
|
},
|
||||||
|
'now': datetime.datetime.utcnow().isoformat()[:23] + 'Z',
|
||||||
|
'as_slugid': as_slugid,
|
||||||
|
'event': {
|
||||||
|
'repository': {
|
||||||
|
'clone_url': params['repository_github_http_url']
|
||||||
|
},
|
||||||
|
'release': {
|
||||||
|
'tag_name': params['head_rev'],
|
||||||
|
'target_commitish': params['branch']
|
||||||
|
},
|
||||||
|
'sender': {
|
||||||
|
'login': 'TaskclusterHook'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rendered = jsone.render(taskcluster_yml, context)
|
||||||
|
if len(rendered['tasks']) != 1:
|
||||||
|
raise Exception('Expected .taskcluster.yml to only produce one cron task')
|
||||||
|
task = rendered['tasks'][0]
|
||||||
|
|
||||||
|
task_id = task.pop('taskId')
|
||||||
|
return task_id, task
|
||||||
|
|
||||||
|
|
||||||
|
def schedule(is_staging):
|
||||||
|
queue = taskcluster.Queue({'baseUrl': 'http://taskcluster/queue/v1'})
|
||||||
|
|
||||||
|
repository_github_http_url, branch, head_rev = calculate_git_references(ROOT)
|
||||||
|
params = {
|
||||||
|
'is_staging': is_staging,
|
||||||
|
'repository_github_http_url': repository_github_http_url,
|
||||||
|
'head_rev': head_rev,
|
||||||
|
'branch': branch,
|
||||||
|
'cron_task_id': os.environ.get('CRON_TASK_ID', '<cron_task_id>')
|
||||||
|
}
|
||||||
|
decision_task_id, decision_task = make_decision_task(params)
|
||||||
|
schedule_task(queue, decision_task_id, decision_task)
|
||||||
|
print('All scheduled!')
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
parser = argparse.ArgumentParser(description='Schedule a nightly release pipeline')
|
||||||
|
|
||||||
|
parser.add_argument('--staging', action='store_true',
|
||||||
|
help="Perform a staging build (use dep workers, don't communicate with Google Play) ")
|
||||||
|
|
||||||
|
result = parser.parse_args()
|
||||||
|
schedule(result.staging)
|
Loading…
Reference in New Issue