From 7decc31f76335a4fb3bd81cfbce8bd9632f56402 Mon Sep 17 00:00:00 2001 From: Mike Hommey Date: Thu, 20 Jul 2017 17:52:56 +0900 Subject: [PATCH] Bug 1383996 - Add an argument to `mach artifact toolchain` to store a manifest for chain-of-trust validation. r=gps Chain of trust validation will require to know what the inputs for a given build are, and mach artifact toolchain fetches such inputs. So we make it output a manifest that the chain of trust validation process will be able to use and correlate with other information, such as the one from bug 1383993. At the same time, we make the produced manifest contain information about tooltool-downloaded packages, which will allow to track the progress in the migration from tooltool to TC artifacts. --HG-- extra : rebase_source : 5b3fc32a9fd641cc7edc57865d2b60aaa6ffcbed --- python/mozbuild/mozbuild/mach_commands.py | 26 ++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/python/mozbuild/mozbuild/mach_commands.py b/python/mozbuild/mozbuild/mach_commands.py index 8cd2fb447c86..5f294e32e6e3 100644 --- a/python/mozbuild/mozbuild/mach_commands.py +++ b/python/mozbuild/mozbuild/mach_commands.py @@ -7,6 +7,7 @@ from __future__ import absolute_import, print_function, unicode_literals import argparse import collections import errno +import hashlib import itertools import json import logging @@ -38,6 +39,7 @@ from mozbuild.base import ( MozconfigLoadException, ObjdirMismatchException, ) +from mozbuild.util import ensureParentDir from mozbuild.backend import ( backends, @@ -1691,6 +1693,8 @@ class PackageFrontend(MachCommandBase): help='Do not unpack any downloaded file') @CommandArgument('--retry', type=int, default=0, help='Number of times to retry failed downloads') + @CommandArgument('--artifact-manifest', metavar='FILE', + help='Store a manifest about the downloaded taskcluster artifacts') @CommandArgument('files', nargs='*', help='A list of files to download, in the form path@task-id, in ' 'addition to the files listed in the tooltool manifest.') @@ -1698,7 +1702,7 @@ class PackageFrontend(MachCommandBase): skip_cache=False, from_build=(), tooltool_manifest=None, authentication_file=None, tooltool_url=None, no_unpack=False, retry=None, - files=()): + artifact_manifest=None, files=()): '''Download, cache and install pre-built toolchains. ''' from mozbuild.artifacts import ArtifactCache @@ -1916,6 +1920,8 @@ class PackageFrontend(MachCommandBase): 'Failed to download {name}') return 1 + artifacts = {} if artifact_manifest else None + for record in downloaded: local = os.path.join(os.getcwd(), record.basename) if os.path.exists(local): @@ -1928,6 +1934,19 @@ class PackageFrontend(MachCommandBase): os.link(record.filename, local) except Exception: shutil.copy(record.filename, local) + # Keep a sha256 of each downloaded file, for the chain-of-trust + # validation. + if artifact_manifest is not None: + with open(local) as fh: + h = hashlib.sha256() + while True: + data = fh.read(1024 * 1024) + if not data: + break + h.update(data) + artifacts[record.url] = { + 'sha256': h.hexdigest(), + } if record.unpack and not no_unpack: unpack_file(local, record.setup) os.unlink(local) @@ -1937,6 +1956,11 @@ class PackageFrontend(MachCommandBase): if files: return 1 + if artifacts: + ensureParentDir(artifact_manifest) + with open(artifact_manifest, 'w') as fh: + json.dump(artifacts, fh, indent=4, sort_keys=True) + return 0