summaryrefslogtreecommitdiffstats
path: root/testing/docker/rust-build
diff options
context:
space:
mode:
Diffstat (limited to 'testing/docker/rust-build')
-rw-r--r--testing/docker/rust-build/Dockerfile37
-rw-r--r--testing/docker/rust-build/README.md2
-rw-r--r--testing/docker/rust-build/REGISTRY1
-rw-r--r--testing/docker/rust-build/VERSION1
-rw-r--r--testing/docker/rust-build/build_cargo.sh20
-rw-r--r--testing/docker/rust-build/build_rust.sh26
-rw-r--r--testing/docker/rust-build/build_rust_mac.sh36
-rw-r--r--testing/docker/rust-build/fetch_cargo.sh21
-rw-r--r--testing/docker/rust-build/fetch_rust.sh20
-rw-r--r--testing/docker/rust-build/package_rust.sh13
-rw-r--r--testing/docker/rust-build/repack_rust.py177
-rw-r--r--testing/docker/rust-build/task.json37
-rw-r--r--testing/docker/rust-build/tcbuild.py206
-rw-r--r--testing/docker/rust-build/upload_rust.sh22
14 files changed, 619 insertions, 0 deletions
diff --git a/testing/docker/rust-build/Dockerfile b/testing/docker/rust-build/Dockerfile
new file mode 100644
index 000000000..45d64def5
--- /dev/null
+++ b/testing/docker/rust-build/Dockerfile
@@ -0,0 +1,37 @@
+FROM quay.io/rust/rust-buildbot
+MAINTAINER Ralph Giles <giles@mozilla.com>
+
+# Reset user/workdir from parent image so we can install software.
+WORKDIR /
+USER root
+
+# Update base.
+RUN yum upgrade -y
+RUN yum clean all
+
+# Install tooltool directly from github.
+RUN mkdir /builds
+ADD https://raw.githubusercontent.com/mozilla/build-tooltool/master/tooltool.py /build/tooltool.py
+RUN chmod +rx /build/tooltool.py
+
+# Add build scripts.
+ADD fetch_rust.sh build_rust.sh /build/
+ADD fetch_cargo.sh build_cargo.sh /build/
+ADD package_rust.sh upload_rust.sh /build/
+ADD repack_rust.py /build/
+RUN chmod +x /build/*
+
+# Create user for doing the build.
+ENV USER worker
+ENV HOME /home/${USER}
+
+RUN useradd -d ${HOME} -m ${USER}
+
+# Set up the user's tree
+WORKDIR ${HOME}
+
+# Invoke our build scripts by default, but allow other commands.
+USER ${USER}
+ENTRYPOINT /build/fetch_rust.sh && /build/build_rust.sh && \
+ /build/fetch_cargo.sh && /build/build_cargo.sh && \
+ /build/package_rust.sh && /build/upload_rust.sh
diff --git a/testing/docker/rust-build/README.md b/testing/docker/rust-build/README.md
new file mode 100644
index 000000000..3241051ec
--- /dev/null
+++ b/testing/docker/rust-build/README.md
@@ -0,0 +1,2 @@
+This is a docker script for building rust toolchains for
+use in Mozilla's build clusters.
diff --git a/testing/docker/rust-build/REGISTRY b/testing/docker/rust-build/REGISTRY
new file mode 100644
index 000000000..e32374498
--- /dev/null
+++ b/testing/docker/rust-build/REGISTRY
@@ -0,0 +1 @@
+quay.io/rust
diff --git a/testing/docker/rust-build/VERSION b/testing/docker/rust-build/VERSION
new file mode 100644
index 000000000..0d91a54c7
--- /dev/null
+++ b/testing/docker/rust-build/VERSION
@@ -0,0 +1 @@
+0.3.0
diff --git a/testing/docker/rust-build/build_cargo.sh b/testing/docker/rust-build/build_cargo.sh
new file mode 100644
index 000000000..33b56e6f9
--- /dev/null
+++ b/testing/docker/rust-build/build_cargo.sh
@@ -0,0 +1,20 @@
+#!/bin/bash -vex
+
+set -x -e
+
+: WORKSPACE ${WORKSPACE:=/home/worker}
+
+set -v
+
+# Configure and build cargo.
+
+if test $(uname -s) = "Darwin"; then
+ export MACOSX_DEPLOYMENT_TARGET=10.7
+fi
+
+pushd ${WORKSPACE}/cargo
+./configure --prefix=${WORKSPACE}/rustc --local-rust-root=${WORKSPACE}/rustc
+make
+make dist
+make install
+popd
diff --git a/testing/docker/rust-build/build_rust.sh b/testing/docker/rust-build/build_rust.sh
new file mode 100644
index 000000000..2f57128ae
--- /dev/null
+++ b/testing/docker/rust-build/build_rust.sh
@@ -0,0 +1,26 @@
+#!/bin/bash -vex
+
+set -x -e
+
+: WORKSPACE ${WORKSPACE:=/home/worker}
+
+CORES=$(nproc || grep -c ^processor /proc/cpuinfo || sysctl -n hw.ncpu)
+
+set -v
+
+# Configure and build rust.
+OPTIONS="--enable-llvm-static-stdcpp --disable-docs"
+OPTIONS+="--enable-debuginfo"
+OPTIONS+="--release-channel=stable"
+x32="i686-unknown-linux-gnu"
+x64="x86_64-unknown-linux-gnu"
+arm="arm-linux-androideabi"
+
+mkdir -p ${WORKSPACE}/rust-build
+pushd ${WORKSPACE}/rust-build
+${WORKSPACE}/rust/configure --prefix=${WORKSPACE}/rustc \
+ --target=${x64},${x32} ${OPTIONS}
+make -j ${CORES}
+make dist
+make install
+popd
diff --git a/testing/docker/rust-build/build_rust_mac.sh b/testing/docker/rust-build/build_rust_mac.sh
new file mode 100644
index 000000000..a6d44f6dd
--- /dev/null
+++ b/testing/docker/rust-build/build_rust_mac.sh
@@ -0,0 +1,36 @@
+#!/bin/bash -vex
+
+set -e
+
+: WORKSPACE ${WORKSPACE:=$PWD}
+: TOOLTOOL ${TOOLTOOL:=python $WORKSPACE/tooltool.py}
+
+CORES=$(nproc || grep -c ^processor /proc/cpuinfo || sysctl -n hw.ncpu)
+echo Building on $CORES cpus...
+
+OPTIONS="--enable-debuginfo --disable-docs"
+TARGETS="x86_64-apple-darwin,i686-apple-darwin"
+
+PREFIX=${WORKSPACE}/rustc
+
+set -v
+
+mkdir -p ${WORKSPACE}/gecko-rust-mac
+pushd ${WORKSPACE}/gecko-rust-mac
+
+export MACOSX_DEPLOYMENT_TARGET=10.7
+${WORKSPACE}/rust/configure --prefix=${PREFIX} --target=${TARGETS} ${OPTIONS}
+make -j ${CORES}
+
+rm -rf ${PREFIX}
+mkdir ${PREFIX}
+make dist
+make install
+popd
+
+# Package the toolchain for upload.
+pushd ${WORKSPACE}
+rustc/bin/rustc --version
+tar cvjf rustc.tar.bz2 rustc/*
+${TOOLTOOL} add --visibility=public --unpack rustc.tar.bz2
+popd
diff --git a/testing/docker/rust-build/fetch_cargo.sh b/testing/docker/rust-build/fetch_cargo.sh
new file mode 100644
index 000000000..c0fdb65d3
--- /dev/null
+++ b/testing/docker/rust-build/fetch_cargo.sh
@@ -0,0 +1,21 @@
+#!/bin/bash -vex
+
+set -x -e
+
+# Inputs, with defaults
+
+: REPOSITORY ${REPOSITORY:=https://github.com/rust-lang/cargo}
+: BRANCH ${BRANCH:=master}
+
+: WORKSPACE ${WORKSPACE:=/home/worker}
+
+set -v
+
+# Check out rust sources
+SRCDIR=${WORKSPACE}/cargo
+git clone --recursive $REPOSITORY -b $BRANCH ${SRCDIR}
+
+# Report version
+VERSION=$(git -C ${SRCDIR} describe --tags --dirty)
+COMMIT=$(git -C ${SRCDIR} rev-parse HEAD)
+echo "cargo ${VERSION} (commit ${COMMIT})" | tee cargo-version
diff --git a/testing/docker/rust-build/fetch_rust.sh b/testing/docker/rust-build/fetch_rust.sh
new file mode 100644
index 000000000..69a0d9bd9
--- /dev/null
+++ b/testing/docker/rust-build/fetch_rust.sh
@@ -0,0 +1,20 @@
+#!/bin/bash -vex
+
+set -x -e
+
+# Inputs, with defaults
+
+: RUST_REPOSITORY ${RUST_REPOSITORY:=https://github.com/rust-lang/rust}
+: RUST_BRANCH ${RUST_BRANCH:=stable}
+
+: WORKSPACE ${WORKSPACE:=/home/worker}
+
+set -v
+
+# Check out rust sources
+git clone $RUST_REPOSITORY -b $RUST_BRANCH ${WORKSPACE}/rust
+
+# Report version
+VERSION=$(git -C ${WORKSPACE}/rust describe --tags --dirty)
+COMMIT=$(git -C ${WORKSPACE}/rust rev-parse HEAD)
+echo "rust ${VERSION} (commit ${COMMIT})" | tee rust-version
diff --git a/testing/docker/rust-build/package_rust.sh b/testing/docker/rust-build/package_rust.sh
new file mode 100644
index 000000000..743aec2fb
--- /dev/null
+++ b/testing/docker/rust-build/package_rust.sh
@@ -0,0 +1,13 @@
+#!/bin/bash -vex
+
+set -x -e
+
+: WORKSPACE ${WORKSPACE:=/home/worker}
+
+set -v
+
+# Package the toolchain for upload.
+pushd ${WORKSPACE}
+tar cvJf rustc.tar.xz rustc/*
+/build/tooltool.py add --visibility=public --unpack rustc.tar.xz
+popd
diff --git a/testing/docker/rust-build/repack_rust.py b/testing/docker/rust-build/repack_rust.py
new file mode 100644
index 000000000..e0a5e89c5
--- /dev/null
+++ b/testing/docker/rust-build/repack_rust.py
@@ -0,0 +1,177 @@
+#!/bin/env python
+'''
+This script downloads and repacks official rust language builds
+with the necessary tool and target support for the Firefox
+build environment.
+'''
+
+import os.path
+import requests
+import subprocess
+import toml
+
+def fetch_file(url):
+ '''Download a file from the given url if it's not already present.'''
+ filename = os.path.basename(url)
+ if os.path.exists(filename):
+ return
+ r = requests.get(url, stream=True)
+ r.raise_for_status()
+ with open(filename, 'wb') as fd:
+ for chunk in r.iter_content(4096):
+ fd.write(chunk)
+
+def fetch(url):
+ '''Download and verify a package url.'''
+ base = os.path.basename(url)
+ print('Fetching %s...' % base)
+ fetch_file(url + '.asc')
+ fetch_file(url)
+ fetch_file(url + '.sha256')
+ fetch_file(url + '.asc.sha256')
+ print('Verifying %s...' % base)
+ subprocess.check_call(['shasum', '-c', base + '.sha256'])
+ subprocess.check_call(['shasum', '-c', base + '.asc.sha256'])
+ subprocess.check_call(['gpg', '--verify', base + '.asc', base])
+ subprocess.check_call(['keybase', 'pgp', 'verify',
+ '-d', base + '.asc',
+ '-i', base,
+ ])
+
+def install(filename, target):
+ '''Run a package's installer script against the given target directory.'''
+ print(' Unpacking %s...' % filename)
+ subprocess.check_call(['tar', 'xf', filename])
+ basename = filename.split('.tar')[0]
+ print(' Installing %s...' % basename)
+ install_cmd = [os.path.join(basename, 'install.sh')]
+ install_cmd += ['--prefix=' + os.path.abspath(target)]
+ install_cmd += ['--disable-ldconfig']
+ subprocess.check_call(install_cmd)
+ print(' Cleaning %s...' % basename)
+ subprocess.check_call(['rm', '-rf', basename])
+
+def package(manifest, pkg, target):
+ '''Pull out the package dict for a particular package and target
+ from the given manifest.'''
+ version = manifest['pkg'][pkg]['version']
+ info = manifest['pkg'][pkg]['target'][target]
+ return (version, info)
+
+def fetch_package(manifest, pkg, host):
+ version, info = package(manifest, pkg, host)
+ print('%s %s\n %s\n %s' % (pkg, version, info['url'], info['hash']))
+ if not info['available']:
+ print('%s marked unavailable for %s' % (pkg, host))
+ raise AssertionError
+ fetch(info['url'])
+ return info
+
+def fetch_std(manifest, targets):
+ stds = []
+ for target in targets:
+ info = fetch_package(manifest, 'rust-std', target)
+ stds.append(info)
+ return stds
+
+def tar_for_host(host):
+ if 'linux' in host:
+ tar_options = 'cJf'
+ tar_ext = '.tar.xz'
+ else:
+ tar_options = 'cjf'
+ tar_ext = '.tar.bz2'
+ return tar_options, tar_ext
+
+def repack(host, targets, channel='stable', suffix=''):
+ print("Repacking rust for %s..." % host)
+ url = 'https://static.rust-lang.org/dist/channel-rust-' + channel + '.toml'
+ req = requests.get(url)
+ req.raise_for_status()
+ manifest = toml.loads(req.content)
+ if manifest['manifest-version'] != '2':
+ print('ERROR: unrecognized manifest version %s.' % manifest['manifest-version'])
+ return
+ print('Using manifest for rust %s as of %s.' % (channel, manifest['date']))
+ print('Fetching packages...')
+ rustc = fetch_package(manifest, 'rustc', host)
+ cargo = fetch_package(manifest, 'cargo', host)
+ stds = fetch_std(manifest, targets)
+ print('Installing packages...')
+ tar_basename = 'rustc-' + host
+ if suffix:
+ tar_basename += '-' + suffix
+ tar_basename += '-repack'
+ install_dir = 'rustc'
+ subprocess.check_call(['rm', '-rf', install_dir])
+ install(os.path.basename(rustc['url']), install_dir)
+ install(os.path.basename(cargo['url']), install_dir)
+ for std in stds:
+ install(os.path.basename(std['url']), install_dir)
+ pass
+ print('Tarring %s...' % tar_basename)
+ tar_options, tar_ext = tar_for_host(host)
+ subprocess.check_call(['tar', tar_options, tar_basename + tar_ext, install_dir])
+ subprocess.check_call(['rm', '-rf', install_dir])
+
+def repack_cargo(host, channel='nightly'):
+ print("Repacking cargo for %s..." % host)
+ # Cargo doesn't seem to have a .toml manifest.
+ base_url = 'https://static.rust-lang.org/cargo-dist/'
+ req = requests.get(os.path.join(base_url, 'channel-cargo-' + channel))
+ req.raise_for_status()
+ file = ''
+ for line in req.iter_lines():
+ if line.find(host) != -1:
+ file = line.strip()
+ if not file:
+ print('No manifest entry for %s!' % host)
+ return
+ manifest = {
+ 'date': req.headers['Last-Modified'],
+ 'pkg': {
+ 'cargo': {
+ 'version': channel,
+ 'target': {
+ host: {
+ 'url': os.path.join(base_url, file),
+ 'hash': None,
+ 'available': True,
+ },
+ },
+ },
+ },
+ }
+ print('Using manifest for cargo %s.' % channel)
+ print('Fetching packages...')
+ cargo = fetch_package(manifest, 'cargo', host)
+ print('Installing packages...')
+ install_dir = 'cargo'
+ subprocess.check_call(['rm', '-rf', install_dir])
+ install(os.path.basename(cargo['url']), install_dir)
+ tar_basename = 'cargo-%s-repack' % host
+ print('Tarring %s...' % tar_basename)
+ tar_options, tar_ext = tar_for_host(host)
+ subprocess.check_call(['tar', tar_options, tar_basename + tar_ext, install_dir])
+ subprocess.check_call(['rm', '-rf', install_dir])
+
+# rust platform triples
+android="armv7-linux-androideabi"
+linux64="x86_64-unknown-linux-gnu"
+linux32="i686-unknown-linux-gnu"
+mac64="x86_64-apple-darwin"
+mac32="i686-apple-darwin"
+win64="x86_64-pc-windows-msvc"
+win32="i686-pc-windows-msvc"
+
+if __name__ == '__main__':
+ repack(mac64, [mac64, mac32])
+ repack(win32, [win32])
+ repack(win64, [win64])
+ repack(linux64, [linux64, linux32])
+ repack(linux64, [linux64, mac64, mac32], suffix='mac-cross')
+ repack(linux64, [linux64, android], suffix='android-cross')
+ repack_cargo(mac64)
+ repack_cargo(win32)
+ repack_cargo(win64)
+ repack_cargo(linux64)
diff --git a/testing/docker/rust-build/task.json b/testing/docker/rust-build/task.json
new file mode 100644
index 000000000..fd1ab872b
--- /dev/null
+++ b/testing/docker/rust-build/task.json
@@ -0,0 +1,37 @@
+{
+ "provisionerId": "aws-provisioner-v1",
+ "workerType": "rustbuild",
+ "created": "{task_created}",
+ "deadline": "{task_deadline}",
+ "payload": {
+ "image": "quay.io/rust/gecko-rust-build",
+ "env": {
+ "RUST_BRANCH": "{rust_branch}"
+ },
+ "artifacts": {
+ "public/rustc.tar.xz": {
+ "path": "/home/worker/rustc.tar.xz",
+ "expires": "{artifacts_expires}",
+ "type": "file"
+ },
+ "public/manifest.tt": {
+ "path": "/home/worker/manifest.tt",
+ "expires": "{artifacts_expires}",
+ "type": "file"
+ }
+ },
+ "features": {
+ "relengAPIProxy": true
+ },
+ "maxRunTime": 6000
+ },
+ "scopes": [
+ "docker-worker:relengapi-proxy:tooltool.upload.public"
+ ],
+ "metadata": {
+ "name": "Rust toolchain build",
+ "description": "Builds the rust toolchain for use in gecko builders.",
+ "owner": "giles@mozilla.com",
+ "source": "https://github.com/rillian/rust-build/"
+ }
+}
diff --git a/testing/docker/rust-build/tcbuild.py b/testing/docker/rust-build/tcbuild.py
new file mode 100644
index 000000000..d55c6f3a7
--- /dev/null
+++ b/testing/docker/rust-build/tcbuild.py
@@ -0,0 +1,206 @@
+#!/bin/env python
+'''
+This script triggers a taskcluster task, waits for it to finish,
+fetches the artifacts, uploads them to tooltool, and updates
+the in-tree tooltool manifests.
+'''
+
+from __future__ import print_function
+
+import requests.packages.urllib3
+requests.packages.urllib3.disable_warnings()
+
+import argparse
+import datetime
+import json
+import os
+import shutil
+import sys
+import taskcluster
+import tempfile
+import time
+import tooltool
+
+def local_file(filename):
+ '''
+ Return a path to a file next to this script.
+ '''
+ return os.path.join(os.path.dirname(__file__), filename)
+
+def read_tc_auth(tc_auth_file):
+ '''
+ Read taskcluster credentials from tc_auth_file and return them as a dict.
+ '''
+ return json.load(open(tc_auth_file, 'rb'))
+
+def fill_template_dict(d, keys):
+ for key, val in d.items():
+ if isinstance(val, basestring) and '{' in val:
+ d[key] = val.format(**keys)
+ elif isinstance(val, dict):
+ fill_template_dict(val, keys)
+
+def fill_template(template_file, keys):
+ '''
+ Take the file object template_file, parse it as JSON, and
+ interpolate (using str.template) its keys using keys.
+ '''
+ template = json.load(template_file)
+ fill_template_dict(template, keys)
+ return template
+
+def spawn_task(queue, args):
+ '''
+ Spawn a Taskcluster task in queue using args.
+ '''
+ task_id = taskcluster.utils.slugId()
+ with open(local_file('task.json'), 'rb') as template:
+ keys = vars(args)
+ now = datetime.datetime.utcnow()
+ keys['task_created'] = now.isoformat() + 'Z'
+ keys['task_deadline'] = (now + datetime.timedelta(hours=2)).isoformat() + 'Z'
+ keys['artifacts_expires'] = (now + datetime.timedelta(days=1)).isoformat() + 'Z'
+ payload = fill_template(template, keys)
+ queue.createTask(task_id, payload)
+ print('--- %s task %s submitted ---' % (now, task_id))
+ return task_id
+
+def wait_for_task(queue, task_id, initial_wait=5):
+ '''
+ Wait until queue reports that task task_id is completed, and return
+ its run id.
+
+ Sleep for initial_wait seconds before checking status the first time.
+ Then poll periodically and print a running log of the task status.
+ '''
+ time.sleep(initial_wait)
+ previous_state = None
+ have_ticks = False
+ while True:
+ res = queue.status(task_id)
+ state = res['status']['state']
+ if state != previous_state:
+ now = datetime.datetime.utcnow()
+ if have_ticks:
+ sys.stdout.write('\n')
+ have_ticks = False
+ print('--- %s task %s %s ---' % (now, task_id, state))
+ previous_state = state
+ if state == 'completed':
+ return len(res['status']['runs']) - 1
+ if state in ('failed', 'exception'):
+ raise Exception('Task failed')
+ sys.stdout.write('.')
+ sys.stdout.flush()
+ have_ticks = True
+ time.sleep(10)
+
+def fetch_artifact(queue, task_id, run_id, name, dest_dir):
+ '''
+ Fetch the artifact with name from task_id and run_id in queue,
+ write it to a file in dest_dir, and return the path to the written
+ file.
+ '''
+ url = queue.buildUrl('getArtifact', task_id, run_id, name)
+ fn = os.path.join(dest_dir, os.path.basename(name))
+ print('Fetching %s...' % name)
+ try:
+ r = requests.get(url, stream=True)
+ r.raise_for_status()
+ with open(fn, 'wb') as f:
+ for chunk in r.iter_content(1024):
+ f.write(chunk)
+ except requests.exceptions.HTTPError:
+ print('HTTP Error %d fetching %s' % (r.status_code, name))
+ return None
+ return fn
+
+def make_artifact_dir(task_id, run_id):
+ prefix = 'tc-artifacts.%s.%d.' % (task_id, run_id)
+ print('making artifact dir %s' % prefix)
+ return tempfile.mkdtemp(prefix=prefix)
+
+def fetch_artifacts(queue, task_id, run_id):
+ '''
+ Fetch all artifacts from task_id and run_id in queue, write them to
+ temporary files, and yield the path to each.
+ '''
+ try:
+ tempdir = make_artifact_dir(task_id, run_id)
+ res = queue.listArtifacts(task_id, run_id)
+ for a in res['artifacts']:
+ # Skip logs
+ if a['name'].startswith('public/logs'):
+ continue
+ # Skip interfaces
+ if a['name'].startswith('private/docker-worker'):
+ continue
+ yield fetch_artifact(queue, task_id, run_id, a['name'], tempdir)
+ finally:
+ if os.path.isdir(tempdir):
+ #shutil.rmtree(tempdir)
+ print('Artifacts downloaded to %s' % tempdir)
+ pass
+
+def upload_to_tooltool(tooltool_auth, task_id, artifact):
+ '''
+ Upload artifact to tooltool using tooltool_auth as the authentication token.
+ Return the path to the generated tooltool manifest.
+ '''
+ try:
+ oldcwd = os.getcwd()
+ os.chdir(os.path.dirname(artifact))
+ manifest = artifact + '.manifest'
+ tooltool.main([
+ 'tooltool.py',
+ 'add',
+ '--visibility=public',
+ '-m', manifest,
+ artifact
+ ])
+ tooltool.main([
+ 'tooltool.py',
+ 'upload',
+ '-m', manifest,
+ '--authentication-file', tooltool_auth,
+ '--message', 'Built from taskcluster task {}'.format(task_id),
+ ])
+ return manifest
+ finally:
+ os.chdir(oldcwd)
+
+def update_manifest(artifact, manifest, local_gecko_clone):
+ platform = linux
+ manifest_dir = os.path.join(local_gecko_clone,
+ 'testing', 'config', 'tooltool-manifests')
+ platform_dir = [p for p in os.listdir(manifest_dir)
+ if p.startswith(platform)][0]
+ tree_manifest = os.path.join(manifest_dir, platform_dir, 'releng.manifest')
+ print('%s -> %s' % (manifest, tree_manifest))
+ shutil.copyfile(manifest, tree_manifest)
+
+def main():
+ parser = argparse.ArgumentParser(description='Build and upload binaries')
+ parser.add_argument('taskcluster_auth', help='Path to a file containing Taskcluster client ID and authentication token as a JSON file in the form {"clientId": "...", "accessToken": "..."}')
+ parser.add_argument('--tooltool-auth', help='Path to a file containing a tooltool authentication token valid for uploading files')
+ parser.add_argument('--local-gecko-clone', help='Path to a local Gecko clone whose tooltool manifests will be updated with the newly-built binaries')
+ parser.add_argument('--rust-branch', default='stable',
+ help='Revision of the rust repository to use')
+ parser.add_argument('--task', help='Use an existing task')
+
+ args = parser.parse_args()
+ tc_auth = read_tc_auth(args.taskcluster_auth)
+ queue = taskcluster.Queue({'credentials': tc_auth})
+ if args.task:
+ task_id, initial_wait = args.task, 0
+ else:
+ task_id, initial_wait = spawn_task(queue, args), 25
+ run_id = wait_for_task(queue, task_id, initial_wait)
+ for artifact in fetch_artifacts(queue, task_id, run_id):
+ if args.tooltool_auth:
+ manifest = upload_to_tooltool(args.tooltool_auth, task_id, artifact)
+ if args.local_gecko_clone:
+ update_manifest(artifact, manifest, args.local_gecko_clone)
+
+if __name__ == '__main__':
+ main()
diff --git a/testing/docker/rust-build/upload_rust.sh b/testing/docker/rust-build/upload_rust.sh
new file mode 100644
index 000000000..d3a7b634e
--- /dev/null
+++ b/testing/docker/rust-build/upload_rust.sh
@@ -0,0 +1,22 @@
+#!/bin/bash -vex
+
+set -x -e
+
+: WORKSPACE ${WORKSPACE:=/home/worker}
+
+set -v
+
+# Upload artifacts packaged by the build script.
+pushd ${WORKSPACE}
+if test -n "$TASK_ID"; then
+ # If we're running on task cluster, use the upload-capable tunnel.
+ TOOLTOOL_OPTS="--url=http://relengapi/tooltool/"
+ MESSAGE="Taskcluster upload ${TASK_ID}/${RUN_ID} $0"
+else
+ MESSAGE="Rust toolchain build for gecko"
+fi
+if test -r rust-version; then
+ MESSAGE="$MESSAGE $(cat rust-version)"
+fi
+/build/tooltool.py upload ${TOOLTOOL_OPTS} --message="${MESSAGE}"
+popd