def main(): option_parser = optparse.OptionParser() option_parser.add_option( '--mode', default='dev', help='switch indicating how to archive build (dev is only valid value)' ) option_parser.add_option('--target', default='Release', help='build target to archive (Debug or Release)') option_parser.add_option( '--arch', default=archive_utils.BuildArch(), help='specify that target architecure of the build') option_parser.add_option('--src-dir', default='src', help='path to the top-level sources directory') option_parser.add_option('--build-dir', help='ignored') option_parser.add_option('--extra-archive-paths', default='', help='comma-separated lists of paths containing ' 'files named FILES, SYMBOLS and TESTS. These ' 'files contain lists of extra files to be ' 'that will be archived. The paths are relative ' 'to the directory given in --src-dir.') option_parser.add_option('--build-number', type='int', help='The build number of the builder running ' 'this script. we use it as the name of build ' 'archive directory') option_parser.add_option('--dry-run', action='store_true', help='Avoid making changes, for testing') option_parser.add_option('--ignore', default=[], action='append', help='Files to ignore') option_parser.add_option('--archive_host', default=archive_utils.Config.archive_host) option_parser.add_option('--build-name', default=None, help="Name to use for build directory instead of " "the slave build name") option_parser.add_option('--staging-dir', help='Directory to use for staging the archives. ' 'Default behavior is to automatically detect ' 'slave\'s build directory.') chromium_utils.AddPropertiesOptions(option_parser) options, args = option_parser.parse_args() if args: raise archive_utils.StagingError('Unknown arguments: %s' % args) if not options.ignore: # Independent of any other configuration, these exes and any symbol files # derived from them (i.e., any filename starting with these strings) will # not be archived or uploaded, typically because they're not built for the # current distributon. options.ignore = archive_utils.Config.exes_to_skip_entirely if options.mode == 'official': option_parser.error('Official mode is not supported here') elif options.mode == 'dev': options.dirs = { # Built files are stored here, in a subdir. named for the build version. 'www_dir_base': archive_utils.Config.www_dir_base + 'snapshots', # Symbols are stored here, in a subdirectory named for the build version. 'symbol_dir_base': archive_utils.Config.www_dir_base + 'snapshots', } else: option_parser.error('Invalid options mode %s' % options.mode) if options.build_number is not None: s = StagerByBuildNumber(options) else: s = StagerByChromiumRevision(options) return s.ArchiveBuild()
def ArchiveBuild(self): """Zips build files and uploads them, their symbols, and a change log.""" result = 0 if self._build_revision is None: raise archive_utils.StagingError('No build revision was provided') print 'Staging in %s' % self._staging_dir arch = archive_utils.BuildArch() fparser = archive_utils.FilesCfgParser(self._files_file, self.options.mode, arch) files_list = fparser.ParseLegacyList() self._archive_files = archive_utils.ExpandWildcards( self._build_dir, files_list) archives_list = fparser.ParseArchiveLists() # Check files and revision numbers. all_files_list = self._archive_files + [ item['filename'] for sublist in archives_list.values() for item in sublist ] all_files_list.append(self._version_file) not_found = archive_utils.VerifyFiles(all_files_list, self._build_dir, self.options.ignore) not_found_optional = [] for bad_fn in not_found[:]: if fparser.IsOptional(bad_fn): not_found_optional.append(bad_fn) not_found.remove(bad_fn) # Remove it from all file lists so we don't try to process it. if bad_fn in self._archive_files: self._archive_files.remove(bad_fn) for archive_list in archives_list.values(): archive_list[:] = [ x for x in archive_list if bad_fn != x['filename'] ] # TODO(mmoss): Now that we can declare files optional in FILES.cfg, should # we only allow not_found_optional, and fail on any leftover not_found # files? print 'last change: %d' % self._build_revision previous_revision = self.GetLastBuildRevision() if self._build_revision <= previous_revision: # If there have been no changes, report it but don't raise an exception. # Someone might have pushed the "force build" button. print 'No changes since last build (r%d <= r%d)' % ( self._build_revision, previous_revision) return 0 print 'build name: %s' % self._build_name archive_name = 'chrome-%s.zip' % chromium_utils.PlatformName() archive_file = self.CreateArchiveFile(archive_name, self._archive_files)[1] # Handle any custom archives. # TODO(mmoss): Largely copied from stage_build.py. Maybe refactor more of # this into archive_utils.py. archive_files = [archive_file] for archive_name in archives_list: if fparser.IsDirectArchive(archives_list[archive_name]): fileobj = archives_list[archive_name][0] # Copy the file to the path specified in archive_name, which might be # different than the dirname or basename in 'filename' (allowed by # 'direct_archive'). stage_subdir = os.path.dirname(archive_name) stage_fn = os.path.basename(archive_name) chromium_utils.MaybeMakeDirectory( os.path.join(self._staging_dir, stage_subdir)) print 'chromium_utils.CopyFileToDir(%s, %s, dest_fn=%s)' % ( os.path.join(self._build_dir, fileobj['filename']), os.path.join(self._staging_dir, stage_subdir), stage_fn) if not self.options.dry_run: chromium_utils.CopyFileToDir( os.path.join(self._build_dir, fileobj['filename']), os.path.join(self._staging_dir, stage_subdir), dest_fn=stage_fn) archive_files.append( os.path.join(self._staging_dir, archive_name)) else: custom_archive = self.CreateArchiveFile( archive_name, [f['filename'] for f in archives_list[archive_name]])[1] print 'Adding %s to be archived.' % (custom_archive) archive_files.append(custom_archive) # Generate a change log or an error message if no previous revision. changelog_path = os.path.join(self._staging_dir, 'changelog.xml') self._GenerateChangeLog(previous_revision, changelog_path) # Generate a revisions file which contains the Chromium/WebKit/V8's # revision information. self.GenerateRevisionFile() www_dir = os.path.join(self._www_dir_base, str(self._build_revision)) gs_bucket = self.options.factory_properties.get('gs_bucket', None) gs_acl = self.options.factory_properties.get('gs_acl', None) gs_base = None if gs_bucket: gs_base = '/'.join( [gs_bucket, self._build_name, str(self._build_revision)]) self._UploadBuild(www_dir, changelog_path, self.revisions_path, archive_files, gs_base, gs_acl) # Archive Linux packages (if any -- only created for Chrome builds). if chromium_utils.IsLinux(): linux_packages = (glob.glob( os.path.join(self._build_dir, '*-r%s_*.deb' % self._chromium_revision))) linux_packages.extend( glob.glob( os.path.join(self._build_dir, '*-%s.*.rpm' % self._chromium_revision))) for package_file in linux_packages: print 'SshCopyFiles(%s, %s, %s)' % ( package_file, self.options.archive_host, www_dir) if not self.options.dry_run: print 'SshMakeDirectory(%s, %s)' % (self.options.archive_host, www_dir) self.MySshMakeDirectory(self.options.archive_host, www_dir, gs_base) for package_file in linux_packages: self.MyMakeWorldReadable(package_file, gs_base) self.MySshCopyFiles(package_file, self.options.archive_host, www_dir, gs_base, gs_acl=gs_acl) # Cleanup archived packages, otherwise they keep accumlating since # they have different filenames with each build. os.unlink(package_file) self.UploadTests(www_dir, gs_base, gs_acl) if not self.options.dry_run: # Save the current build revision locally so we can compute a changelog # next time self.SaveBuildRevisionToSpecifiedFile(self.last_change_file) # Record the latest revision in the developer archive directory. latest_file_path = os.path.join(self._www_dir_base, 'LATEST') if chromium_utils.IsWindows(): print 'Saving revision to %s' % latest_file_path if gs_base: MyCopyFileToGS(self.last_change_file, gs_base, '..', mimetype='text/plain', gs_acl=gs_acl) if not gs_base or self._dual_upload: self.SaveBuildRevisionToSpecifiedFile(latest_file_path) elif chromium_utils.IsLinux() or chromium_utils.IsMac(): # Files are created umask 077 by default, so make it world-readable # before pushing to web server. self.MyMakeWorldReadable(self.last_change_file, gs_base) print 'Saving revision to %s:%s' % (self.options.archive_host, latest_file_path) self.MySshCopyFiles(self.last_change_file, self.options.archive_host, latest_file_path, gs_base, '..', mimetype='text/plain', gs_acl=gs_acl) else: raise NotImplementedError( 'Platform "%s" is not currently supported.' % sys.platform) if len(not_found_optional): sys.stderr.write('\n\nINFO: Optional File(s) not found: %s\n' % ', '.join(not_found_optional)) if len(not_found): sys.stderr.write('\n\nWARNING: File(s) not found: %s\n' % ', '.join(not_found)) return result