def _git_release(self): os.makedirs(self.working_dir, exist_ok=True) with chdir(self.working_dir): run_command("{cli_tool} clone {project_name}".format(cli_tool=self.cli_tool, project_name=self.project_name)) with chdir(self.package_workdir): run_command("{cli_tool} fork".format(cli_tool=self.cli_tool)) run_command("git fetch {username}".format(username=self.username)) self.new_branch_name = "release-branch-{timestamp}".format( timestamp=int(datetime.datetime.utcnow().timestamp())) run_command("git checkout -b {new_branch_name} {username}/{branch}".format( new_branch_name=self.new_branch_name, username=self.username, branch=self.git_branches[0])) # Mead builds need to be in the git_root. Other builders are agnostic. with chdir(self.git_root): self.builder.tgz() self.builder.copy_extra_sources() if self.test: self.builder._setup_test_specfile() self._git_sync_files(self.package_workdir) self._git_upload_sources(self.package_workdir) self.no_build = True self.git_branches = self.git_branches[:1] self._git_user_confirm_commit(self.package_workdir)
def _git_upload_sources(self, project_checkout): chain_file = find_mead_chain_file(self.builder.rpmbuild_gitcopy) with open(chain_file, 'r') as f: template = Template(f.read()) ref = self.builder.build_tag if self.test: ref = self.builder.git_commit_id values = { 'mead_scm': self.mead_scm, 'git_ref': ref, # Each property on its own line with a few leading spaces to indicate # that it's a continuation 'maven_properties': "\n ".join(self.builder.maven_properties), 'maven_options': " ".join(self.builder.maven_args), } rendered_chain = template.safe_substitute(values) with chdir(project_checkout): with open("mead.chain", "w") as f: f.write(rendered_chain) cmd = "git add mead.chain" if self.dry_run: self.print_dry_run_warning(cmd) info_out("Chain file contents:\n%s" % rendered_chain) else: run_command(cmd)
def _git_release(self): getoutput("mkdir -p %s" % self.working_dir) with chdir(self.working_dir): run_command("%s clone %s" % (self.cli_tool, self.project_name)) with chdir(self.package_workdir): run_command("%s switch-branch %s" % (self.cli_tool, self.git_branches[0])) # Mead builds need to be in the git_root. Other builders are agnostic. with chdir(self.git_root): self.builder.tgz() if self.test: self.builder._setup_test_specfile() self._git_sync_files(self.package_workdir) self._git_upload_sources(self.package_workdir) self._git_user_confirm_commit(self.package_workdir)
def run_git_archive(self, relative_git_dir, prefix, commit, dest_tar, subdir): # command to generate a git-archive git_archive_cmd = 'git archive --format=tar --prefix=%s/ %s:%s --output=%s' % ( prefix, commit, relative_git_dir, dest_tar) with chdir(subdir) as p: run_command(git_archive_cmd) # Run git-archive separately if --debug was specified. # This allows us to detect failure early. # On git < 1.7.4-rc0, `git archive ... commit:./` fails! debug('git-archive fails if relative dir is not in git tree', '%s > /dev/null' % git_archive_cmd)
def _sync_mead_scm(self): cmd = "git push %s %s" % (self.push_url, self.builder.build_tag) if self.dry_run: self.print_dry_run_warning(cmd) return with chdir(self.git_root): info_out("Syncing local repo with %s" % self.push_url) try: run_command(cmd) except RunCommandException as e: if "rejected" in e.output: if self._ask_yes_no("The remote rejected a push. Force push? [y/n] ", False): run_command("git push --force %s %s" % (self.mead_scm, self.builder.build_tag)) else: error_out("Could not sync with %s" % self.mead_scm) raise
def _git_release(self): getoutput("mkdir -p %s" % self.package_workdir) # Mead builds need to be in the git_root. Other builders are agnostic. with chdir(self.git_root): self.builder.tgz() if self.test: self.builder._setup_test_specfile() debug("Searching for source files to build") files_to_copy = self._list_files_to_copy() self._sync_files(files_to_copy, self.package_workdir) debug("would build with specfile: {0} and sources at: {1}".format(self.builder.spec_file, self.package_workdir)) debug("build branches: {0}".format(self.git_branches)) for branch in self.git_branches: self.build_in_mock(branch)
def _git_release(self): getoutput("mkdir -p %s" % self.package_workdir) # Mead builds need to be in the git_root. Other builders are agnostic. with chdir(self.git_root): self.builder.tgz() if self.test: self.builder._setup_test_specfile() debug("Searching for source files to build") files_to_copy = self._list_files_to_copy() self._sync_files(files_to_copy, self.package_workdir) debug("would build with specfile: {0} and sources at: {1}".format( self.builder.spec_file, self.package_workdir)) debug("build branches: {0}".format(self.git_branches)) for branch in self.git_branches: self.build_in_mock(branch)
def tgz(self): destination_file = os.path.join(self.rpmbuild_basedir, self.tgz_filename) formatted_properties = ["-D%s" % x for x in self.maven_properties] run_command("git clone --no-hardlinks %s %s" % (find_git_root(), self.maven_clone_dir)) with chdir(self.maven_clone_dir): run_command("git checkout %s" % self.git_commit_id) try: info_out("Running Maven build...") # We always want to deploy to a tito controlled location during local builds local_properties = formatted_properties + [ "-DaltDeploymentRepository=local-output::default::file://%s" % self.deploy_dir] run_command("mvn %s %s deploy" % ( " ".join(self.maven_args), " ".join(local_properties))) except RunCommandException as e: error_out("Maven build failed! %s" % e.output) self._create_build_dirs() full_path = self._find_tarball() if full_path: fh = gzip.open(full_path, 'rb') fixed_tar = os.path.join(os.path.splitext(full_path)[0]) fixed_tar_fh = open(fixed_tar, 'wb') timestamp = get_commit_timestamp(self.git_commit_id) try: tarfixer = TarFixer(fh, fixed_tar_fh, timestamp, self.git_commit_id, maven_built=True) tarfixer.fix() finally: fixed_tar_fh.close() # It's a pity we can't use Python's gzip, but it doesn't offer an equivalent of -n run_command("gzip -n -c < %s > %s" % (fixed_tar, destination_file)) else: warn_out([ "No Maven generated tarball found.", "Please set up the assembly plugin in your pom.xml to generate a .tar.gz"]) full_path = os.path.join(self.rpmbuild_sourcedir, self.tgz_filename) create_tgz(self.git_root, self.tgz_dir, self.git_commit_id, self.relative_project_dir, full_path) print("Creating %s from git tag: %s..." % (self.tgz_filename, self.build_tag)) shutil.copy(full_path, destination_file) debug("Copying git source to: %s" % self.rpmbuild_gitcopy) shutil.copy(destination_file, self.rpmbuild_gitcopy) # Extract the source so we can get at the spec file, etc. with chdir(self.rpmbuild_gitcopy): run_command("tar --strip-components=1 -xvf %s" % os.path.join(self.rpmbuild_gitcopy, self.tgz_filename)) if self.local_build: artifacts = {} all_artifacts = [] all_artifacts_with_path = [] for directory, unused, filenames in os.walk(self.deploy_dir): for f in filenames: artifacts.setdefault(os.path.splitext(f)[1], []).append(f) dir_artifacts_with_path = [os.path.join(directory, f) for f in filenames] # Place the Maven artifacts in the SOURCES directory for rpmbuild to use for artifact in dir_artifacts_with_path: shutil.copy(artifact, self.rpmbuild_sourcedir) dir_artifacts_with_path = map(lambda x: os.path.relpath(x, self.deploy_dir), dir_artifacts_with_path) all_artifacts_with_path.extend(dir_artifacts_with_path) all_artifacts.extend([os.path.basename(f) for f in filenames]) cheetah_input = { 'name': self.project_name, 'version': self.spec_version, 'release': self.spec_release, 'epoch': None, # TODO: May need to support this at some point 'artifacts': artifacts, 'all_artifacts': all_artifacts, 'all_artifacts_with_path': all_artifacts_with_path, } debug("Cheetah input: %s" % cheetah_input) render_cheetah(find_cheetah_template_file(self.start_dir), self.rpmbuild_gitcopy, cheetah_input) self.spec_file_name = find_spec_file(self.rpmbuild_gitcopy) else: self.spec_file_name = find_cheetah_template_file(self.rpmbuild_gitcopy) # NOTE: The spec file we actually use is the one exported by git # archive into the temp build directory. This is done so we can # modify the version/release on the fly when building test rpms # that use a git SHA1 for their version. self.spec_file = os.path.join(self.rpmbuild_gitcopy, self.spec_file_name) info_out("Wrote: %s" % destination_file) self.sources.append(destination_file) self.artifacts.append(destination_file) self.ran_tgz = True
def __init__(self, name=None, tag=None, build_dir=None, config=None, user_config=None, args=None, **kwargs): """ name - Package name that is being built. version - Version and release being built. tag - The git tag being built. build_dir - Temporary build directory where we can safely work. config - Merged configuration. (global plus package specific) user_config - User configuration from ~/.titorc. args - Optional arguments specific to each builder. Can be passed in explicitly by user on the CLI, or via a release target config entry. Only for things which vary on invocations of the builder, avoid using these if possible. *Given in the format of a dictionary of lists.* """ ConfigObject.__init__(self, config=config) BuilderBase.__init__(self, name=name, build_dir=build_dir, config=config, user_config=user_config, args=args, **kwargs) self.build_tag = tag self.build_version = self._get_build_version() if kwargs and 'options' in kwargs: warn_out("'options' no longer a supported builder constructor argument.") if self.config.has_section("requirements"): if self.config.has_option("requirements", "tito"): if loose_version(self.config.get("requirements", "tito")) > \ loose_version(require('tito')[0].version): error_out([ "tito version %s or later is needed to build this project." % self.config.get("requirements", "tito"), "Your version: %s" % require('tito')[0].version ]) self.display_version = self._get_display_version() with chdir(find_git_root()): self.git_commit_id = get_build_commit(tag=self.build_tag, test=self.test) self.relative_project_dir = get_relative_project_dir( project_name=self.project_name, commit=self.git_commit_id) if self.relative_project_dir is None and self.test: warn_out(".tito/packages/%s doesn't exist " "in git, using current directory" % self.project_name) self.relative_project_dir = get_relative_project_dir_cwd( self.git_root) tgz_base = self._get_tgz_name_and_ver() self.tgz_filename = tgz_base + ".tar.gz" self.tgz_dir = tgz_base self.artifacts = [] # A copy of the git code from commit we're building: self.rpmbuild_gitcopy = os.path.join(self.rpmbuild_sourcedir, self.tgz_dir) # Used to make sure we only modify the spec file for a test build # once. The srpm method may be called multiple times during koji # releases to create the proper disttags, but we only want to modify # the spec file once. self.ran_setup_test_specfile = False # NOTE: These are defined later when/if we actually dump a copy of the # project source at the tag we're building. Only then can we search for # a spec file. self.spec_file_name = None self.spec_file = None # Set to path to srpm once we build one. self.srpm_location = None
def _git_set_user_config(self): fullname, email = get_git_user_info() email = email or "" with chdir(self.package_workdir): run_command("git config user.name '{0}'".format(fullname)) run_command("git config user.email '{0}'".format(email))