From 07f3bd6f8c70d46978ac250403a8cc2b5a2e9175 Mon Sep 17 00:00:00 2001 From: Joseph Schorr Date: Fri, 10 Oct 2014 17:20:07 -0400 Subject: [PATCH] Add a synthetic .git directory containing the commit sha so that 'git rev-parse HEAD' works from inside builds --- endpoints/trigger.py | 45 ++++++++++++++++++++++++++++++++++---- workers/dockerfilebuild.py | 11 ++++++---- 2 files changed, 48 insertions(+), 8 deletions(-) diff --git a/endpoints/trigger.py b/endpoints/trigger.py index c7c47db79..ac3c035ba 100644 --- a/endpoints/trigger.py +++ b/endpoints/trigger.py @@ -3,6 +3,7 @@ import io import os.path import tarfile import base64 +from StringIO import StringIO from github import Github, UnknownObjectException, GithubException from tempfile import SpooledTemporaryFile @@ -297,14 +298,50 @@ class GithubBuildTrigger(BuildTrigger): # Seek to position 0 to make tarfile happy tarball.seek(0) - # Pull out the name of the subdir that GitHub generated + # Pull out the name of the subdir that GitHub generated. with tarfile.open(fileobj=tarball) as archive: - tarball_subdir = archive.getnames()[0] + tarball_subdir = archive.getnames()[0] + tarball_subdir_info = archive.getmember(tarball_subdir) - # Seek to position 0 to make boto multipart happy + # Seek to position 0 to make tarfile happy tarball.seek(0) - dockerfile_id = user_files.store_file(tarball, TARBALL_MIME) + with SpooledTemporaryFile(CHUNK_SIZE) as updated_tarball: + def add_entry(arch, dir_path, base_info, contents=None): + info = tarfile.TarInfo(dir_path) + + info.uid = base_info.uid + info.gid = base_info.gid + info.uname = base_info.uname + info.gname = base_info.gname + info.mode = base_info.mode + info.mtime = base_info.mtime + + info.type = tarfile.REGTYPE if contents else tarfile.DIRTYPE + if contents: + info.size = len(contents) + + arch.addfile(info, fileobj=StringIO(contents) if contents else None) + + with tarfile.open(fileobj=updated_tarball, mode='w|gz') as updated_archive: + # Copy existing members of the tar to the updated archive. + with tarfile.open(fileobj=tarball) as archive: + for tar_info in archive: + if tar_info.isreg(): + updated_archive.addfile(tar_info, archive.extractfile(tar_info.name)) + else: + updated_archive.addfile(tar_info) + + # Add the synthetic .git directory to the tarball, containing the commit_sha. + add_entry(updated_archive, tarball_subdir + '/.git/HEAD', tarball_subdir_info, + contents=commit_sha) + add_entry(updated_archive, tarball_subdir + '/.git/objects/', tarball_subdir_info) + add_entry(updated_archive, tarball_subdir + '/.git/refs/', tarball_subdir_info) + + # Seek to position 0 to make boto multipart happy + updated_tarball.seek(0) + + dockerfile_id = user_files.store_file(updated_tarball, TARBALL_MIME) logger.debug('Successfully prepared job') diff --git a/workers/dockerfilebuild.py b/workers/dockerfilebuild.py index 60b29a109..ceac71587 100644 --- a/workers/dockerfilebuild.py +++ b/workers/dockerfilebuild.py @@ -38,8 +38,7 @@ TIMEOUT_PERIOD_MINUTES = 20 CACHE_EXPIRATION_PERIOD_HOURS = 24 NO_TAGS = [':'] RESERVATION_TIME = (TIMEOUT_PERIOD_MINUTES + 5) * 60 -DOCKER_BASE_URL = None # Set this if you want to use a different docker URL/socket. - +DOCKER_BASE_URL = os.environ.get('DOCKER_HOST', None) def matches_system_error(status_str): """ Returns true if the given status string matches a known system error in the @@ -521,8 +520,12 @@ class DockerfileBuildWorker(Worker): repository_build.uuid) # Lookup and save the version of docker being used. - docker_cl = Client(base_url = DOCKER_BASE_URL) - docker_version = docker_cl.version().get('Version', '') + try: + docker_cl = Client(base_url = DOCKER_BASE_URL) + docker_version = docker_cl.version().get('Version', '') + except ConnectionError as exc: + raise WorkerUnhealthyException(exc.message) + dash = docker_version.find('-') # Strip any -tutum or whatever off of the version.