def _getBaseDirName( self ): myIndex = None if self.getParent(): myIndex = self.getParent().getIndex( self ) + 1 if self.getName() == self.__class__.__name__: baseDirName = '{0}'.format( myIndex ) else: index = myIndex or '' spacer = '_' if myIndex else '' baseDirName = '{0}{1}{2}'.format( index, spacer, make_foldername_from_string( self.getName() ) ) return baseDirName
def __getitem__( self, key ): # first: try to get the value from the overwrite dict val = self.overwrites.get( key ) if val != None: return val # next: try to get it from settings val = self.__settings.get( key, True ) if not val: return "" if self.escape: return make_foldername_from_string( val ) return val
def fetchRepositoryFolder( self, remotePath ): # FIXME Mike abstract cache location path = tempfile.mkdtemp( prefix = 'mom_buildscript-', suffix = make_foldername_from_string( self.getUrl() ) ) if not self.getRevision(): self.setRevision( 'HEAD' ) location = self.getUrl() if remotePath: location += '/' + remotePath cmd = [ self.getCommand(), 'co', '-r', self.getRevision(), location ] runner = RunCommand( cmd, searchPaths = self.getCommandSearchPaths() ) runner.setWorkingDir( path ) runner.run() if runner.getReturnCode() == 0: localPath = os.path.join( path, remotePath ) if os.path.exists( localPath ): return localPath, [ path ] raise ConfigurationError( 'The remote path {0} was not found in the repository at revision {1}'.format( remotePath, self.getRevision() ) )
def __str__( self ): value = '[unresolved string]' try: value = self._asString() except ConfigurationError: # strings may remain unresolved if the script is not really executed: if mApp().getSettings().get( Settings.ScriptRunMode ) != Settings.RunMode_Build: pass else: raise if self.getConvertToFolderName(): value = make_foldername_from_string( value ) if not self.getPattern(): return str( value ) else: try: result = self.getPattern().format( value ) return result except ValueError: raise ConfigurationError( 'The StringResolver "{0}" pattern needs to contain exactly one place holder like this: '\ .format( self.getPattern() ) + '"pattern-{0}"' )
def execute( self, instructions ): """Execute the step""" check_for_nonempty_string( self.getName(), "Cannot execute a step with no name!" ) self.setStatus( Step.Status.Started ) if not self.isEnabled(): self.setStatus( Step.Status.Skipped_Disabled ) return True # (usually) abort if another step has failed for this Instructions object: if not instructions._stepsShouldExecute() and not self.getExecuteOnFailure(): self.setStatus( Step.Status.Skipped_PreviousError ) return True with self.getTimeKeeper(): self._logEnvironment( instructions ) logfileName = '{0}.log'.format( make_foldername_from_string( self.getName() ) ) logfilePath = os.path.join( instructions.getLogDir(), logfileName ) self.setLogfilePath( logfilePath ) self.setResult( Step.Result.Success ) # execute each action associated to this step for phase, actions in self._getPhases(): if not actions: mApp().debugN( self, 3, 'phase "{0}" is empty (no actions registered)'.format( phase ) ) continue mApp().debugN( self, 3, 'phase "{0}" has {1} actions registered, starting execution'.format( phase, len( actions ) ) ) for action in actions: resultText = 'skipped' if self.getResult() != Step.Result.Failure or action.getIgnorePreviousFailure(): result = action.executeAction( self.getLogfilePath() ) resultText = 'successful' if result == 0 else 'failed' if result != 0: self.setResult( Step.Result.Failure ) else: self.setStatus( Step.Status.Skipped_PreviousError ) mApp().debugN( self, 3, '{0}: "{1}" {2}'.format( phase, action.getLogDescription(), resultText ) ) self.setStatus( Step.Status.Finished ) return self.getResult() != Step.Result.Failure
def getInstanceName( self ): '''Instance name can be used if multiple independent SimpleCI instances are running on the same machine (since configuration files are usually loaded by host name).''' name = make_foldername_from_string( self.getName() ) return name
def performBuild( self, buildInfo ): """Start a build process for a new revision. baseDir is the directory where all builds go. To build different revisions and build types under it, subdirectories have to be used.""" buildType = buildInfo.getBuildType().lower() # Under windows we have the problem that paths need to be short, so take only 7 digists of the git hash # this is also done for svn revision numbers, but these should not be so long if sys.platform == 'win32': rev = buildInfo.getRevision()[0:7] else: rev = buildInfo.getRevision() name = make_foldername_from_string( buildInfo.getProjectName() ) # find suitable names for the different build dirs: baseDir = os.path.join( os.getcwd(), 'builds' ) buildRoot = mApp().getSettings().get( Settings.SimpleCIBuildDirectory, required = False ) or baseDir subfolder = make_foldername_from_string( rev ) directory = os.path.normpath( os.path.join( buildRoot, name, buildType, subfolder ) ) # prepare build directory: if os.path.isdir( directory ): mApp().debug( self, 'found remainders of a previous build, nuking it...' ) try: rmtree( directory ) mApp().debug( self, '...that was good!' ) except ( OSError, IOError ) as e: raise ConfigurationError( 'Remnants of a previous build exist at "{0}" and cannot be deleted, bad. Reason: {1}.' .format( directory, e ) ) try: os.makedirs( directory ) except ( OSError, IOError )as e: raise ConfigurationError( 'Cannot create required build directory "{0}"!'.format( directory ) ) mApp().message( self, 'starting build job for project "{0}" at revision {1}.' .format( buildInfo.getProjectName(), rev ) ) with EnvironmentSaver(): os.chdir( directory ) extend_debug_prefix( buildInfo.getProjectName() ) iface = BuildScriptInterface( os.path.abspath( buildInfo.getBuildScript() ) ) runner = iface.executeBuildInfo( buildInfo ) try: with open( 'buildscript.log', 'w' ) as f: text = runner.getStdOutAsString() f.write( text.decode() ) except Exception as e: mApp().message( self, 'Problem! saving the build script output failed during handling an exception! {0}' .format( e ) ) if runner.getReturnCode() != 0: mApp().message( self, 'build failed for project "{0}" at revision {1}'.format( buildInfo.getProjectName(), rev ) ) # FIXME send out email reports on configuration or MOM errors mApp().message( self, 'exit code {0}'.format( runner.getReturnCode() ) ) print( """\ --> ____ _ _ _ _____ _ _ _ --> | __ ) _ _(_) | __| | | ___|_ _(_) | ___ __| | --> | _ \| | | | | |/ _` | | |_ / _` | | |/ _ \/ _` | --> | |_) | |_| | | | (_| | | _| (_| | | | __/ (_| | --> |____/ \__,_|_|_|\__,_| |_| \__,_|_|_|\___|\__,_| --> """ ) return False else: mApp().message( self, 'build succeeded for project "{0}" at revision {1}'.format( buildInfo.getProjectName(), rev ) ) print( """\ --> _ _ _ _ _ --> | |__ _ _(_) |__| | __| |___ _ _ ___ --> | '_ \ || | | / _` | / _` / _ \ ' \/ -_) --> |_.__/\_,_|_|_\__,_| \__,_\___/_||_\___| --> """ ) return True
def testWithConvertToFolderName( self ): name = 'Dummy Test Name' result = make_foldername_from_string( name ) resolver = SettingResolver( Settings.ScriptBuildName, convertToFolderName = True ) mApp().getSettings().set( Settings.ScriptBuildName, name ) self.assertEqual( result, str( resolver ) )