bug 1269355 - Enable sccache for taskcluster linux32/64 builds. r=dustin,gps
authorTed Mielczarek <ted@mielczarek.org>
Thu, 10 Nov 2016 13:02:54 -0500
changeset 323900 c1b55d39dd28c6a5b07aba6533f9aae286c4a72f
parent 323899 0ad8cb5077d44ca8f9af39cacaa6f65d3b831310
child 323901 e5a62d4ce95aa7d460b3745332e0878974d12714
push id24
push usermaklebus@msu.edu
push dateTue, 20 Dec 2016 03:11:33 +0000
reviewersdustin, gps
bugs1269355
milestone53.0a1
bug 1269355 - Enable sccache for taskcluster linux32/64 builds. r=dustin,gps MozReview-Commit-ID: LGqpNDb7uHN
build/mozconfig.cache
taskcluster/scripts/builder/build-linux.sh
taskcluster/taskgraph/transforms/build.py
taskcluster/taskgraph/transforms/job/__init__.py
taskcluster/taskgraph/transforms/task.py
--- a/build/mozconfig.cache
+++ b/build/mozconfig.cache
@@ -36,25 +36,30 @@ if test -z "$SCCACHE_DISABLE" -a -z "$no
             ;;
         *usw2.mozilla.com*)
             bucket=mozilla-releng-s3-cache-us-west-2-prod
             ;;
         esac
         ;;
     esac
 fi
+fi
 
-# builds without buildprops (eg: taskcluster or non-buildbot) and without ccache env config and without sccache disabled:
-elif test -z "$CCACHE_DIR" -a -z "$SCCACHE_DISABLE" -a -z "$no_sccache" -a -z "$MOZ_PGO_IS_SET" -a -z "$MOZ_PGO"; then
+# builds where buildprops didn't have the data (eg: taskcluster or non-buildbot) and without sccache disabled:
+if test -z "$bucket" -a -z "$SCCACHE_DISABLE" -a -z "$no_sccache" -a -z "$MOZ_PGO_IS_SET" -a -z "$MOZ_PGO"; then
 
     # prevent rerun if az is set, or wget is not available
     if test -z "$availability_zone" -a -x "$(command -v wget)"; then
-        # timeout after 1 second, and don't retry (failure indicates instance is not in ec2 or network issue)
-        # availability_zone is of the form <region><letter> where region is e.g. us-west-2, and az is us-west-2a
-        availability_zone=$(wget -T 1 -t 1 -q -O - http://169.254.169.254/latest/meta-data/placement/availability-zone || true)
+        if test -n "${TASKCLUSTER_WORKER_GROUP}"; then
+            availability_zone="${TASKCLUSTER_WORKER_GROUP}"
+        else
+            # timeout after 1 second, and don't retry (failure indicates instance is not in ec2 or network issue)
+            # availability_zone is of the form <region><letter> where region is e.g. us-west-2, and az is us-west-2a
+            availability_zone=$(wget -T 1 -t 1 -q -O - http://169.254.169.254/latest/meta-data/placement/availability-zone || true)
+        fi
         if test -z "$availability_zone" -o "$availability_zone" = "not-ec2"; then
             availability_zone=not-ec2
         else
             # region is az with last letter trimmed
             region=${availability_zone%?}
             # set S3 bucket according to tree (level)
             case "${GECKO_HEAD_REPOSITORY}" in
             *hg.mozilla.org/try*)
--- a/taskcluster/scripts/builder/build-linux.sh
+++ b/taskcluster/scripts/builder/build-linux.sh
@@ -45,16 +45,21 @@ export TINDERBOX_OUTPUT=1
 export MOZ_SIMPLE_PACKAGE_NAME=target
 
 # Do not try to upload symbols (see https://bugzilla.mozilla.org/show_bug.cgi?id=1164615)
 export MOZ_AUTOMATION_UPLOAD_SYMBOLS=0
 
 # Ensure that in tree libraries can be found
 export LIBRARY_PATH=$LIBRARY_PATH:$WORKSPACE/src/obj-firefox:$WORKSPACE/src/gcc/lib64
 
+if [[ -n ${USE_SCCACHE} ]]; then
+    # Point sccache at the Taskcluster proxy for AWS credentials.
+    export AWS_IAM_CREDENTIALS_URL="http://taskcluster/auth/v1/aws/s3/read-write/taskcluster-level-${MOZ_SCM_LEVEL}-sccache-${TASKCLUSTER_WORKER_GROUP%?}/?format=iam-role-compat"
+fi
+
 # test required parameters are supplied
 if [[ -z ${MOZHARNESS_SCRIPT} ]]; then fail "MOZHARNESS_SCRIPT is not set"; fi
 if [[ -z ${MOZHARNESS_CONFIG} ]]; then fail "MOZHARNESS_CONFIG is not set"; fi
 
 cleanup() {
     local rv=$?
     cleanup_xvfb
     exit $rv
--- a/taskcluster/taskgraph/transforms/build.py
+++ b/taskcluster/taskgraph/transforms/build.py
@@ -14,16 +14,17 @@ transforms = TransformSequence()
 
 
 @transforms.add
 def set_defaults(config, jobs):
     """Set defaults, including those that differ per worker implementation"""
     for job in jobs:
         job['treeherder'].setdefault('kind', 'build')
         job['treeherder'].setdefault('tier', 1)
+        job.setdefault('needs-sccache', True)
         if job['worker']['implementation'] in ('docker-worker', 'docker-engine'):
             job['worker'].setdefault('docker-image', {'in-tree': 'desktop-build'})
             job['worker']['chain-of-trust'] = True
             job.setdefault('extra', {})
             job['extra'].setdefault('chainOfTrust', {})
             job['extra']['chainOfTrust'].setdefault('inputs', {})
             job['extra']['chainOfTrust']['inputs']['docker-image'] = {
                 "task-reference": "<docker-image>"
--- a/taskcluster/taskgraph/transforms/job/__init__.py
+++ b/taskcluster/taskgraph/transforms/job/__init__.py
@@ -48,16 +48,17 @@ job_description_schema = Schema({
     Optional('routes'): task_description_schema['routes'],
     Optional('scopes'): task_description_schema['scopes'],
     Optional('extra'): task_description_schema['extra'],
     Optional('treeherder'): task_description_schema['treeherder'],
     Optional('index'): task_description_schema['index'],
     Optional('run-on-projects'): task_description_schema['run-on-projects'],
     Optional('coalesce-name'): task_description_schema['coalesce-name'],
     Optional('worker-type'): task_description_schema['worker-type'],
+    Optional('needs-sccache'): task_description_schema['needs-sccache'],
     Required('worker'): task_description_schema['worker'],
     Optional('when'): task_description_schema['when'],
 
     # A description of how to run this job.
     'run': {
         # The key to a job implementation in a peer module to this one
         'using': basestring,
 
--- a/taskcluster/taskgraph/transforms/task.py
+++ b/taskcluster/taskgraph/transforms/task.py
@@ -135,16 +135,19 @@ task_description_schema = Schema({
     # tasks are never coalesced
     Optional('coalesce-name'): basestring,
 
     # the provisioner-id/worker-type for the task.  The following parameters will
     # be substituted in this string:
     #  {level} -- the scm level of this push
     'worker-type': basestring,
 
+    # Whether the job should use sccache compiler caching.
+    Required('needs-sccache', default=False): bool,
+
     # information specific to the worker implementation that will run this task
     'worker': Any({
         Required('implementation'): Any('docker-worker', 'docker-engine'),
 
         # For tasks that will run in docker-worker or docker-engine, this is the
         # name of the docker image or in-tree docker image to run the task in.  If
         # in-tree, then a dependency will be created automatically.  This is
         # generally `desktop-test`, or an image that acts an awful lot like it.
@@ -365,16 +368,24 @@ def build_docker_worker_payload(config, 
 
     if worker.get('allow-ptrace'):
         features['allowPtrace'] = True
         task_def['scopes'].append('docker-worker:feature:allowPtrace')
 
     if worker.get('chain-of-trust'):
         features['chainOfTrust'] = True
 
+    if task.get('needs-sccache'):
+        features['taskclusterProxy'] = True
+        task_def['scopes'].append(
+            'assume:project:taskcluster:level-{level}-sccache-buckets'.format(
+                level=config.params['level'])
+        )
+        worker['env']['USE_SCCACHE'] = '1'
+
     capabilities = {}
 
     for lo in 'audio', 'video':
         if worker.get('loopback-' + lo):
             capitalized = 'loopback' + lo.capitalize()
             devices = capabilities.setdefault('devices', {})
             devices[capitalized] = True
             task_def['scopes'].append('docker-worker:capability:device:' + capitalized)
@@ -446,16 +457,18 @@ def build_generic_worker_payload(config,
         'command': worker['command'],
         'artifacts': artifacts,
         'env': worker.get('env', {}),
         'mounts': mounts,
         'maxRunTime': worker['max-run-time'],
         'osGroups': worker.get('os-groups', []),
     }
 
+    # needs-sccache is handled in mozharness_on_windows
+
     if 'retry-exit-status' in worker:
         raise Exception("retry-exit-status not supported in generic-worker")
 
 
 @payload_builder('macosx-engine')
 def build_macosx_engine_payload(config, task, task_def):
     worker = task['worker']
     artifacts = map(lambda artifact: {
@@ -467,16 +480,18 @@ def build_macosx_engine_payload(config, 
 
     task_def['payload'] = {
         'link': worker['link'],
         'command': worker['command'],
         'env': worker['env'],
         'artifacts': artifacts,
     }
 
+    if task.get('needs-sccache'):
+        raise Exception('needs-sccache not supported in macosx-engine')
 
 @payload_builder('buildbot-bridge')
 def build_buildbot_bridge_payload(config, task, task_def):
     worker = task['worker']
     task_def['payload'] = {
         'buildername': worker['buildername'],
         'sourcestamp': worker['sourcestamp'],
         'properties': worker['properties'],