Commit 43ec6c05 authored by Ben Cooksley's avatar Ben Cooksley

Prepare to introduce support for workspace capturing (eg: for failed builds) to assist in debugging

parent b97d79dc
import os
import sys
import tarfile
import tempfile
import argparse
from helperslib import BuildSpecs, BuildSystem, CommonUtils, EnvironmentHandler, Packages
# Parse the command line arguments we've been given
parser = argparse.ArgumentParser(description='Utility to capture a build workspace for later use.')
parser.add_argument('--environment', type=str, required=True)
arguments = parser.parse_args()
# Create a temporary file, then open the file as a tar archive for writing
# We don't want it to be deleted as storePackage will move the archive into it's cache
archiveFile = tempfile.NamedTemporaryFile(delete=False)
archive = fileobj=archiveFile, mode='w' )
# Now determine the path we should be archiving
# We assume we are being run from the root of the Workspace, so the current working directory is good enough for our purposes here
pathToArchive = os.getcwd()
# Add all the files which need to be in the archive into the archive
# We want to capture the tree as it is inside the install directory and don't want any trailing slashes in the archive as this isn't standards compliant
# Therefore we list everything in the install directory and add each of those to the archive, rather than adding the whole install directory
filesToInclude = os.listdir( pathToArchive )
for filename in filesToInclude:
fullPath = os.path.join(pathToArchive, filename)
archive.add( fullPath, arcname=filename, recursive=True )
# Close the archive, which will write it out to disk, finishing what we need to do here
# This is also necessary on Windows to allow for storePackage to move it to it's final home
# Initialize the archive manager
ourArchive = Packages.Archive( arguments.environment, 'Workspaces', usingCache = False )
# Determine which SCM revision we are storing
# This will be embedded into the package metadata which might help someone doing some debugging
# GIT_COMMIT is set by Jenkins Git plugin, so we can rely on that for most of our builds
scmRevision = ''
if os.getenv('GIT_COMMIT') != '':
scmRevision = os.getenv('GIT_COMMIT')
# Determine the package name
# For this we take the job name and transform spaces into underscores
package = os.getenv('JOB_NAME').replace(' ', '_')
# Add the package to the archive
ourArchive.storePackage( package,, scmRevision )
# All done!
......@@ -14,10 +14,13 @@ def nameForProject( product, project, branchGroup ):
class Archive(object):
# Sets up an archive for use, to allow for retrieving and uploading new resources to the archive
# A local cache of the archive will be managed to improve performance
def __init__( self, name, platform, cachingNeeded = True ):
# Save the name of this archive and the platform we're on for later use = name
self.platform = platform
def __init__( self, name, platform, usingCache = True ):
# Save the name of this archive, the platform we're on and whether a local cache should be used for later use = name
self.platform = platform
self.usingCache = usingCache
# Set an empty manifest up for safety later on
self.serverManifest = {}
# Load our configuration
configFileLocation = os.path.join( CommonUtils.scriptsBaseDirectory(), 'archive-configs', name + '.yaml' )
......@@ -25,8 +28,13 @@ class Archive(object):
# Parse the YAML file
self.config = yaml.load( configFile )
# Are we using a local cache?
# If not, then retrieval of packages won't be possible so nothing further needs to be done
if not self.usingCache:
# Does our local cache exist?
if not os.path.isdir( self.cacheLocation() ) and cachingNeeded:
if not os.path.isdir( self.cacheLocation() ):
# Create it
os.makedirs( self.cacheLocation() )
......@@ -81,6 +89,7 @@ class Archive(object):
needToDownload = True
# Does the archive contain what we are after?
# It will never contain it if the use of a local cache has been disabled
if package not in self.serverManifest:
# There is nothing for us to fetch - the server will just yield a 404
# So let's bow out gracefully here
......@@ -164,6 +173,10 @@ class Archive(object):
# We're all done with the remote server now, so disconnect
# If we have no local cache, then we have nothing further to do
if not self.usingCache:
# Finally, we publish the archive and metadata into our local cache
localContentsPath = os.path.join(self.cacheLocation(), contentsFilename)
shutil.move( archiveFileToInclude, localContentsPath )
......@@ -15,6 +15,6 @@ arguments = parser.parse_args()
# Initialize the archive manager and ask it to publish the package
# This will also cause the Manifest for the Archive to be regenerated
ourArchive = Packages.Archive( arguments.environment, arguments.platform, cachingNeeded = False )
ourArchive = Packages.Archive( arguments.environment, arguments.platform, usingCache = False )
ourArchive.publishPackage( arguments.package )
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment