Beispiel #1
0
    def _build(self, branch):
        """ Submit a Fedora build from current directory. """
        target_param = ""
        scratch_param = ""
        build_target = self._get_build_target_for_branch(branch)
        if build_target:
            target_param = "--target %s" % build_target
        if self.scratch:
            scratch_param = "--scratch"

        build_cmd = "%s build --nowait %s %s" % (self.cli_tool, scratch_param, target_param)

        if self.dry_run:
            self.print_dry_run_warning(build_cmd)
            return

        info_out("Submitting build: %s" % build_cmd)
        (status, output) = getstatusoutput(build_cmd)
        if status > 0:
            if "already been built" in output:
                warn_out("Build has been submitted previously, continuing...")
            else:
                error_out([
                    "Unable to submit build."
                    "  Status code: %s\n" % status,
                    "  Output: %s\n" % output,
                ])

        # Print the task ID and URL:
        for line in extract_task_info(output):
            print(line)
Beispiel #2
0
    def _build_in_mock(self):
        if not self.speedup:
            print("Initializing mock...")
            run_command("mock %s -r %s --init" % (self.mock_cmd_args, self.mock_tag))
        else:
            print("Skipping mock --init due to speedup option.")

        print("Installing deps in mock...")
        run_command("mock %s -r %s %s" % (
            self.mock_cmd_args, self.mock_tag, self.srpm_location))
        print("Building RPMs in mock...")
        run_command('mock %s -r %s --rebuild %s' %
                (self.mock_cmd_args, self.mock_tag, self.srpm_location))
        mock_output_dir = os.path.join(self.rpmbuild_dir, "mockoutput")
        run_command("mock %s -r %s --copyout /builddir/build/RPMS/ %s" %
                (self.mock_cmd_args, self.mock_tag, mock_output_dir))

        # Copy everything mock wrote out to /tmp/tito:
        files = os.listdir(mock_output_dir)
        run_command("cp -v %s/*.rpm %s" %
                (mock_output_dir, self.rpmbuild_basedir))
        print
        info_out("Wrote:")
        for rpm in files:
            rpm_path = os.path.join(self.rpmbuild_basedir, rpm)
            print("  %s" % rpm_path)
            self.artifacts.append(rpm_path)
        print
Beispiel #3
0
    def _bump_version(self, release=False, zstream=False):
        """
        Bump up the package version in the spec file.

        Set release to True to bump the package release instead.

        Checks for the keep version option and if found, won't actually
        bump the version or release.
        """
        old_version = get_latest_tagged_version(self.project_name)
        if old_version is None:
            old_version = "untagged"
        if not self.keep_version:
            version_regex = re.compile("^(version:\s*)(.+)$", re.IGNORECASE)
            release_regex = re.compile("^(release:\s*)(.+)$", re.IGNORECASE)

            in_f = open(self.spec_file, 'r')
            out_f = open(self.spec_file + ".new", 'w')

            for line in in_f.readlines():
                version_match = re.match(version_regex, line)
                release_match = re.match(release_regex, line)

                if version_match and not zstream and not release:
                    current_version = version_match.group(2)
                    if hasattr(self, '_use_version'):
                        updated_content = self._use_version
                    else:
                        updated_content = increase_version(current_version)

                    line = "".join([version_match.group(1), updated_content, "\n"])

                elif release_match:
                    current_release = release_match.group(2)
                    if hasattr(self, '_use_release'):
                        updated_content = self._use_release
                    elif release:
                        updated_content = increase_version(current_release)
                    elif zstream:
                        updated_content = increase_zstream(current_release)
                    else:
                        updated_content = reset_release(current_release)

                    line = "".join([release_match.group(1), updated_content, "\n"])

                out_f.write(line)

            in_f.close()
            out_f.close()
            shutil.move(self.spec_file + ".new", self.spec_file)

        new_version = get_spec_version_and_release(self.full_project_dir,
                self.spec_file_name)
        if new_version.strip() == "":
            msg = "Error getting bumped package version, try: \n"
            msg = msg + "  'rpm -q --specfile %s'" % self.spec_file
            error_out(msg)
        info_out("Tagging new version of %s: %s -> %s" % (self.project_name,
            old_version, new_version))
        return new_version
Beispiel #4
0
    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)
Beispiel #5
0
    def run(self, options):
        """
        Perform the actions requested of the builder.

        NOTE: this method may do nothing if the user requested no build actions
        be performed. (i.e. only release tagging, etc)
        """
        info_out("Building package [%s]" % (self.build_tag))
        self.no_cleanup = options.no_cleanup

        # Reset list of artifacts on each call to run().
        self.artifacts = []

        try:
            try:
                if options.tgz:
                    self.tgz()
                if options.srpm:
                    self.srpm()
                if options.rpm:
                    # TODO: not protected anymore
                    self.rpm()
                    self._auto_install()
            except KeyboardInterrupt:
                print("Interrupted, cleaning up...")
        finally:
            self.cleanup()

        return self.artifacts
Beispiel #6
0
    def main(self, argv):
        # DO NOT CALL BaseCliModule.main(self)
        # we are initializing tito to work in this module and
        # calling main will result in a configuration error.
        (self.options, self.args) = self.parser.parse_args(argv)
        should_commit = False

        rel_eng_dir = os.path.join(find_git_root(), '.tito')
        print("Creating tito metadata in: %s" % rel_eng_dir)

        propsfile = os.path.join(rel_eng_dir, TITO_PROPS)
        if not os.path.exists(propsfile):
            if not os.path.exists(rel_eng_dir):
                getoutput("mkdir -p %s" % rel_eng_dir)
                print("   - created %s" % rel_eng_dir)

            # write out tito.props
            out_f = open(propsfile, 'w')
            out_f.write("[buildconfig]\n")
            out_f.write("builder = %s\n" % 'tito.builder.Builder')
            out_f.write(
                "tagger = %s\n" % 'tito.tagger.VersionTagger')
            out_f.write("changelog_do_not_remove_cherrypick = 0\n")
            out_f.write("changelog_format = %s (%ae)\n")
            out_f.close()
            print("   - wrote %s" % TITO_PROPS)

            getoutput('git add %s' % propsfile)
            should_commit = True

        # prep the packages metadata directory
        pkg_dir = os.path.join(rel_eng_dir, "packages")
        readme = os.path.join(pkg_dir, '.readme')

        if not os.path.exists(readme):
            if not os.path.exists(pkg_dir):
                getoutput("mkdir -p %s" % pkg_dir)
                print("   - created %s" % pkg_dir)

            # write out readme file explaining what pkg_dir is for
            readme = os.path.join(pkg_dir, '.readme')
            out_f = open(readme, 'w')
            out_f.write("the .tito/packages directory contains metadata files\n")
            out_f.write("named after their packages. Each file has the latest tagged\n")
            out_f.write("version and the project's relative directory.\n")
            out_f.close()
            print("   - wrote %s" % readme)

            getoutput('git add %s' % readme)
            should_commit = True

        if should_commit:
            getoutput('git commit -m "Initialized to use tito. "')
            print("   - committed to git")

        info_out("Done!")
        return []
Beispiel #7
0
    def _submit(self, srpm_location, project):
        cmd_submit = "/usr/bin/%s build %s %s %s" % \
                     (self.cli_tool, self.copr_options, project, srpm_location)
        if self.dry_run:
            self.print_dry_run_warning(cmd_submit)
            return

        info_out("Submiting build into %s." % self.NAME)
        self._run_command(cmd_submit)
Beispiel #8
0
    def _submit(self, srpm_location):
        cmd_submit = "/usr/bin/%s build %s %s" % \
                     (self.cli_tool, self.releaser_config.get(self.target, "project_name"), srpm_location)
        if self.dry_run:
            self.print_dry_run_warning(cmd_submit)
            return

        info_out("Submiting build into %s." % self.NAME)
        self._run_command(cmd_submit)
Beispiel #9
0
    def _update_package_metadata(self, new_version):
        """
        We track package metadata in the .tito/packages/ directory. Each
        file here stores the latest package version (for the git branch you
        are on) as well as the relative path to the project's code. (from the
        git root)
        """
        self._clear_package_metadata()

        suffix = ""
        # If global config specifies a tag suffix, use it:
        if self.config.has_option(BUILDCONFIG_SECTION, "tag_suffix"):
            suffix = self.config.get(BUILDCONFIG_SECTION, "tag_suffix")

        new_version_w_suffix = "%s%s" % (new_version, suffix)
        # Write out our package metadata:
        metadata_file = os.path.join(self.rel_eng_dir, "packages",
                self.project_name)

        with open(metadata_file, 'w') as f:
            f.write("%s %s\n" % (new_version_w_suffix, self.relative_project_dir))

        # Git add it (in case it's a new file):
        run_command("git add %s" % metadata_file)
        run_command("git add %s" % os.path.join(self.full_project_dir,
            self.spec_file_name))

        fmt = ('Automatic commit of package '
               '[%(name)s] %(release_type)s [%(version)s].')
        if self.config.has_option(BUILDCONFIG_SECTION, "tag_commit_message_format"):
            fmt = self.config.get(BUILDCONFIG_SECTION, "tag_commit_message_format")
        try:
            msg = fmt % {
                'name': self.project_name,
                'release_type': self.release_type(),
                'version': new_version_w_suffix,
            }
        except KeyError:
            exc = sys.exc_info()[1]
            raise TitoException('Unknown placeholder %s in tag_commit_message_format'
                                % exc)

        run_command('git commit -m {0} -m {1} -m {2}'.format(
            quote(msg), quote("Created by command:"), quote(" ".join(sys.argv[:]))))

        tag_msg = "Tagging package [%s] version [%s] in directory [%s]." % \
                (self.project_name, new_version_w_suffix,
                        self.relative_project_dir)

        new_tag = self._get_new_tag(new_version)
        run_command('git tag -m "%s" %s' % (tag_msg, new_tag))
        print
        info_out("Created tag: %s" % new_tag)
        print("   View: git show HEAD")
        print("   Undo: tito tag -u")
        print("   Push: git push origin && git push origin %s" % new_tag)
 def normalize_tarball(self, path):
     destination_file = os.path.join(self.rpmbuild_sourcedir, path)
     if not path.endswith('%s.tar.gz' % self.display_version):
         basename = os.path.basename(path.split('.tar.gz')[0])
         fixed_name = '%s-%s.tar.gz' % (basename, self.display_version)
         destination_file = os.path.join(self.rpmbuild_sourcedir, fixed_name)
         subprocess.check_call('mv %s %s' % (path, destination_file), shell=True)
     subprocess.check_call("cp %s %s/" % (destination_file, self.rpmbuild_basedir), shell=True)
     info_out('Wrote: %s/%s' % (self.rpmbuild_basedir, os.path.basename(destination_file)))
     self.tarballs_from_script.append(destination_file)
     return os.path.join(os.getcwd(), destination_file)
Beispiel #11
0
    def tgz(self):
        """
        Create the .tar.gz required to build this package.

        Returns full path to the created tarball.
        """
        self._setup_sources()

        run_command("cp %s/%s %s/" %
                (self.rpmbuild_sourcedir, self.tgz_filename,
                    self.rpmbuild_basedir))

        self.ran_tgz = True
        full_path = os.path.join(self.rpmbuild_basedir, self.tgz_filename)
        info_out("Wrote: %s" % full_path)
        self.sources.append(full_path)
        self.artifacts.append(full_path)
        return full_path
Beispiel #12
0
    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
Beispiel #13
0
    def _update_package_metadata(self, new_version):
        """
        We track package metadata in the .tito/packages/ directory. Each
        file here stores the latest package version (for the git branch you
        are on) as well as the relative path to the project's code. (from the
        git root)
        """
        self._clear_package_metadata()

        suffix = ""
        # If global config specifies a tag suffix, use it:
        if self.config.has_option(BUILDCONFIG_SECTION, "tag_suffix"):
            suffix = self.config.get(BUILDCONFIG_SECTION, "tag_suffix")

        new_version_w_suffix = "%s%s" % (new_version, suffix)
        # Write out our package metadata:
        metadata_file = os.path.join(self.rel_eng_dir, "packages",
                self.project_name)

        with open(metadata_file, 'w') as f:
            f.write("%s %s\n" % (new_version_w_suffix, self.relative_project_dir))

        # Git add it (in case it's a new file):
        run_command("git add %s" % metadata_file)
        run_command("git add %s" % os.path.join(self.full_project_dir,
            self.spec_file_name))

        run_command('git commit -m "Automatic commit of package ' +
                '[%s] %s [%s]."' % (self.project_name, self.release_type(),
                    new_version_w_suffix))

        tag_msg = "Tagging package [%s] version [%s] in directory [%s]." % \
                (self.project_name, new_version_w_suffix,
                        self.relative_project_dir)

        new_tag = self._get_new_tag(new_version)
        run_command('git tag -m "%s" %s' % (tag_msg, new_tag))
        print
        info_out("Created tag: %s" % new_tag)
        print("   View: git show HEAD")
        print("   Undo: tito tag -u")
        print("   Push: git push origin && git push origin %s" % new_tag)
Beispiel #14
0
    def rpm(self):
        """ Build an RPM. """
        self._create_build_dirs()
        if not self.ran_tgz:
            self.tgz()

        define_dist = ""
        if self.dist:
            define_dist = "--define 'dist %s'" % self.dist

        rpmbuild_options = self.rpmbuild_options + self._scl_to_rpmbuild_option()

        cmd = ('rpmbuild --define "_source_filedigest_algorithm md5"  '
            '--define "_binary_filedigest_algorithm md5" %s %s %s --clean '
            '-ba %s' % (rpmbuild_options,
                self._get_rpmbuild_dir_options(), define_dist, self.spec_file))
        debug(cmd)
        try:
            output = run_command_print(cmd)
        except (KeyboardInterrupt, SystemExit):
            print("")
            exit(1)
        except RunCommandException:
            err = sys.exc_info()[1]
            msg = str(err)
            if re.search('Failed build dependencies', err.output):
                cmd = "dnf builddep %s" if package_manager() == "dnf" else "yum-builddep %s"
                msg = "Please run '%s' as root." % \
                    cmd % find_spec_file(self.relative_project_dir)
            error_out('%s' % msg)
        except Exception:
            err = sys.exc_info()[1]
            error_out('%s' % str(err))
        files_written = find_wrote_in_rpmbuild_output(output)
        if len(files_written) < 2:
            error_out("Error parsing rpmbuild output")
        self.srpm_location = files_written[0]
        self.artifacts.extend(files_written)

        print
        info_out("Successfully built: %s" % ' '.join(files_written))
Beispiel #15
0
    def _build(self, branch):
        """ Submit a Mead build from current directory. """
        target_param = ""
        build_target = self._get_build_target_for_branch(branch)
        if build_target:
            target_param = "--target=%s" % build_target

        build_cmd = [self.cli_tool, "maven-chain", "--nowait"]

        if self.brew_target:
            build_cmd.append("--target=%s" % self.brew_target)

        build_cmd.append("--ini=%s" %
                         (os.path.join(self.package_workdir, "mead.chain")))
        build_cmd.append(target_param)

        if self.scratch:
            build_cmd.append("--scratch")

        build_cmd = " ".join(build_cmd)

        if self.dry_run:
            self.print_dry_run_warning(build_cmd)
            return

        info_out("Submitting build: %s" % build_cmd)
        (status, output) = getstatusoutput(build_cmd)
        if status > 0:
            if "already been built" in output:
                warn_out("Build has been submitted previously, continuing...")
            else:
                error_out([
                    "Unable to submit build.",
                    "  Status code: %s\n" % status,
                    "  Output: %s\n" % output,
                ])

        # Print the task ID and URL:
        for line in extract_task_info(output):
            print(line)
Beispiel #16
0
    def rpm(self):
        """ Build an RPM. """
        self._create_build_dirs()
        if not self.ran_tgz:
            self.tgz()

        define_dist = ""
        if self.dist:
            define_dist = "--define 'dist %s'" % self.dist

        rpmbuild_options = self.rpmbuild_options + self._scl_to_rpmbuild_option()

        cmd = ('rpmbuild --define "_source_filedigest_algorithm md5"  '
            '--define "_binary_filedigest_algorithm md5" %s %s %s %s '
            '-ba %s' % (rpmbuild_options,
                self._get_rpmbuild_dir_options(), define_dist, self._get_clean_option(), self.spec_file))
        debug(cmd)
        try:
            output = run_command_print(cmd)
        except (KeyboardInterrupt, SystemExit):
            print("")
            exit(1)
        except RunCommandException:
            err = sys.exc_info()[1]
            msg = str(err)
            if re.search('Failed build dependencies', err.output):
                cmd = self.package_manager.builddep(find_spec_file(self.relative_project_dir))
                msg = "Please run '%s' as root." % cmd
            error_out('%s' % msg)
        except Exception:
            err = sys.exc_info()[1]
            error_out('%s' % str(err))
        files_written = find_wrote_in_rpmbuild_output(output)
        if len(files_written) < 2:
            error_out("Error parsing rpmbuild output")
        self.srpm_location = files_written[0]
        self.artifacts.extend(files_written)

        print
        info_out("Successfully built: %s" % ' '.join(files_written))
Beispiel #17
0
    def _undo(self):
        """
        Undo the most recent tag.

        Tag commit must be the most recent commit, and the tag must not
        exist in the remote git repo, otherwise we report and error out.
        """
        tag = self._get_tag_for_version(get_latest_tagged_version(self.project_name))
        info_out("Undoing tag: %s" % tag)
        if not tag_exists_locally(tag):
            raise TitoException(
                "Cannot undo tag that does not exist locally.")
        if not self.offline and tag_exists_remotely(tag):
            raise TitoException("Cannot undo tag that has been pushed.")

        # Tag must be the most recent commit.
        if not head_points_to_tag(tag):
            raise TitoException("Cannot undo if tag is not the most recent commit.")

        # Everything looks good:
        print
        undo_tag(tag)
Beispiel #18
0
    def _undo(self):
        """
        Undo the most recent tag.

        Tag commit must be the most recent commit, and the tag must not
        exist in the remote git repo, otherwise we report and error out.
        """
        tag = self._get_tag_for_version(get_latest_tagged_version(self.project_name))
        info_out("Undoing tag: %s" % tag)
        if not tag_exists_locally(tag):
            raise TitoException(
                "Cannot undo tag that does not exist locally.")
        if not self.offline and tag_exists_remotely(tag):
            raise TitoException("Cannot undo tag that has been pushed.")

        # Tag must be the most recent commit.
        if not head_points_to_tag(tag):
            raise TitoException("Cannot undo if tag is not the most recent commit.")

        # Everything looks good:
        print
        undo_tag(tag)
Beispiel #19
0
    def _build(self, branch):
        """ Submit a Mead build from current directory. """
        target_param = ""
        build_target = self._get_build_target_for_branch(branch)
        if build_target:
            target_param = "--target=%s" % build_target

        build_cmd = [self.cli_tool, "maven-chain", "--nowait"]

        if self.brew_target:
            build_cmd.append("--target=%s" % self.brew_target)

        build_cmd.append("--ini=%s" % (os.path.join(self.package_workdir, "mead.chain")))
        build_cmd.append(target_param)

        if self.scratch:
            build_cmd.append("--scratch")

        build_cmd = " ".join(build_cmd)

        if self.dry_run:
            self.print_dry_run_warning(build_cmd)
            return

        info_out("Submitting build: %s" % build_cmd)
        (status, output) = getstatusoutput(build_cmd)
        if status > 0:
            if "already been built" in output:
                warn_out("Build has been submitted previously, continuing...")
            else:
                error_out([
                    "Unable to submit build.",
                    "  Status code: %s\n" % status,
                    "  Output: %s\n" % output,
                ])

        # Print the task ID and URL:
        for line in extract_task_info(output):
            print(line)
Beispiel #20
0
    def _fetch_from_brew(self):
        brew_nvr = "%s.%s" % (self.build_tag, self.dist_tag)
        debug("Brew NVR: %s" % brew_nvr)
        os.chdir(self.rpmbuild_dir)
        run_command("brew download-build %s" % brew_nvr)

        # Wipe out the src rpm for now:
        run_command("rm *.src.rpm")

        # Copy everything brew downloaded out to /tmp/tito:
        files = os.listdir(self.rpmbuild_dir)
        run_command("cp -v %s/*.rpm %s" %
                (self.rpmbuild_dir, self.rpmbuild_basedir))
        print
        info_out("Wrote:")
        for rpm in files:
            # Just incase anything slips into the build dir:
            if not rpm.endswith(".rpm"):
                continue
            rpm_path = os.path.join(self.rpmbuild_basedir, rpm)
            print("  %s" % rpm_path)
            self.artifacts.append(rpm_path)
        print
Beispiel #21
0
    def _fetch_from_brew(self):
        brew_nvr = "%s.%s" % (self.build_tag, self.dist_tag)
        debug("Brew NVR: %s" % brew_nvr)
        os.chdir(self.rpmbuild_dir)
        run_command("brew download-build %s" % brew_nvr)

        # Wipe out the src rpm for now:
        run_command("rm *.src.rpm")

        # Copy everything brew downloaded out to /tmp/tito:
        files = os.listdir(self.rpmbuild_dir)
        run_command("cp -v %s/*.rpm %s" %
                (self.rpmbuild_dir, self.rpmbuild_basedir))
        print
        info_out("Wrote:")
        for rpm in files:
            # Just incase anything slips into the build dir:
            if not rpm.endswith(".rpm"):
                continue
            rpm_path = os.path.join(self.rpmbuild_basedir, rpm)
            print("  %s" % rpm_path)
            self.artifacts.append(rpm_path)
        print
Beispiel #22
0
    def _submit_build(self, executable, koji_opts, tag, srpm_location):
        """ Copy srpm to remote destination and submit it to Copr """
        cmd = self.releaser_config.get(self.target, "upload_command")

        if self.srpm_submitted:
            srpm_location = self.srpm_submitted
        srpm_base_name = os.path.basename(srpm_location)

        # e.g. "scp %(srpm)s my.web.com:public_html/my_srpm/"
        cmd_upload = cmd % {'srpm': srpm_location}
        cmd_submit = "/usr/bin/copr-cli build %s %s%s" % (self.releaser_config.get(self.target, "project_name"),
            self.remote_location, srpm_base_name)

        if self.dry_run:
            self.print_dry_run_warning(cmd_upload)
            self.print_dry_run_warning(cmd_submit)
            return
        # TODO: no error handling when run_command fails:
        if not self.srpm_submitted:
            print("Uploading src.rpm.")
            print(run_command(cmd_upload))
            self.srpm_submitted = srpm_location
        info_out("Submiting build into %s." % self.NAME)
        print(run_command(cmd_submit))
Beispiel #23
0
    def _git_user_confirm_commit(self, project_checkout):
        """ Prompt user if they wish to proceed with commit. """
        print("")
        text = "Running 'git diff' in: %s" % project_checkout
        print("#" * len(text))
        print(text)
        print("#" * len(text))
        print("")

        main_branch = self.git_branches[0]

        os.chdir(project_checkout)

        # Newer versions of git don't seem to want --cached here? Try both:
        (unused, diff_output) = getstatusoutput("git diff --cached")
        if diff_output.strip() == "":
            debug("git diff --cached returned nothing, falling back to git diff.")
            (unused, diff_output) = getstatusoutput("git diff")

        if diff_output.strip() == "":
            print("No changes in main branch, skipping commit for: %s" % main_branch)
        else:
            print(diff_output)
            print("")
            print("##### Please review the above diff #####")
            if not self._ask_yes_no("Do you wish to proceed with commit? [y/n] "):
                print("Fine, you're on your own!")
                self.cleanup()
                sys.exit(1)

            print("Proceeding with commit.")
            commit_msg_file = self._confirm_commit_msg(diff_output)
            cmd = '%s commit -F %s' % (self.cli_tool,
                    commit_msg_file)
            debug("git commit command: %s" % cmd)
            print
            if self.dry_run:
                self.print_dry_run_warning(cmd)
            else:
                print("Proceeding with commit.")
                os.chdir(self.package_workdir)
                run_command(cmd)

            os.unlink(commit_msg_file)

        cmd = self._push_command()
        if self.dry_run:
            self.print_dry_run_warning(cmd)
        else:
            # Push
            print(cmd)
            try:
                run_command(cmd)
            except RunCommandException as e:
                error_out("`%s` failed with: %s" % (cmd, e.output))

        if not self.no_build:
            self._build(main_branch)

        for branch in self.git_branches[1:]:
            info_out("Merging branch: '%s' -> '%s'" % (main_branch, branch))
            run_command("%s switch-branch %s" % (self.cli_tool, branch))
            self._merge(main_branch)

            cmd = "git push origin %s:%s" % (branch, branch)
            if self.dry_run:
                self.print_dry_run_warning(cmd)
            else:
                print(cmd)
                try:
                    run_command(cmd)
                except RunCommandException as e:
                    error_out("`%s` failed with: %s" % (cmd, e.output))

            if not self.no_build:
                self._build(branch)

            print
Beispiel #24
0
 def prune_other_versions(self, temp_dir):
     if self.keepold:
         info_out("YumRepoReleaserKeepOld: skip prune_other_versions")
     else:
         info_out("YumRepoReleaserKeepOld: running prune_other_versions")
         super(YumRepoReleaserKeepOld, self).prune_other_versions(temp_dir)
Beispiel #25
0
    def _update_package_metadata(self, new_version):
        """
        We track package metadata in the .tito/packages/ directory. Each
        file here stores the latest package version (for the git branch you
        are on) as well as the relative path to the project's code. (from the
        git root)
        """
        self._clear_package_metadata()

        new_version_w_suffix = self._get_suffixed_version(new_version)
        # Write out our package metadata:
        metadata_file = os.path.join(self.rel_eng_dir, "packages",
                                     self.project_name)

        with open(metadata_file, 'w') as f:
            f.write("%s %s\n" %
                    (new_version_w_suffix, self.relative_project_dir))

        # Git add it (in case it's a new file):
        run_command("git add %s" % metadata_file)
        run_command("git add %s" %
                    os.path.join(self.full_project_dir, self.spec_file_name))

        fmt = ('Automatic commit of package '
               '[%(name)s] %(release_type)s [%(version)s].')
        if self.config.has_option(BUILDCONFIG_SECTION,
                                  "tag_commit_message_format"):
            fmt = self.config.get(BUILDCONFIG_SECTION,
                                  "tag_commit_message_format")
        new_version_w_suffix = self._get_suffixed_version(new_version)
        try:
            msg = fmt % {
                'name': self.project_name,
                'release_type': self.release_type(),
                'version': new_version_w_suffix,
            }
        except KeyError:
            exc = sys.exc_info()[1]
            raise TitoException(
                'Unknown placeholder %s in tag_commit_message_format' % exc)

        run_command('git commit -m {0} -m {1} -m {2}'.format(
            quote(msg), quote("Created by command:"),
            quote(" ".join(sys.argv[:]))))

        new_tag = self._get_new_tag(new_version)
        tag_msg = "Tagging package [%s] version [%s] in directory [%s]." % \
                (self.project_name, new_tag,
                        self.relative_project_dir)

        # Optionally gpg sign the tag
        sign_tag = ""
        if self.config.has_option(BUILDCONFIG_SECTION, "sign_tag"):
            if self.config.getboolean(BUILDCONFIG_SECTION, "sign_tag"):
                sign_tag = "-s "

        run_command('git tag %s -m "%s" %s' % (sign_tag, tag_msg, new_tag))
        print
        info_out("Created tag: %s" % new_tag)
        print("   View: git show HEAD")
        print("   Undo: tito tag -u")
        print("   Push: git push --follow-tags origin")
Beispiel #26
0
    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
Beispiel #27
0
    def _git_user_confirm_commit(self, project_checkout):
        """ Prompt user if they wish to proceed with commit. """
        print("")
        text = "Running 'git diff' in: %s" % project_checkout
        print("#" * len(text))
        print(text)
        print("#" * len(text))
        print("")

        main_branch = self.git_branches[0]

        os.chdir(project_checkout)

        # Newer versions of git don't seem to want --cached here? Try both:
        (unused, diff_output) = getstatusoutput("git diff --cached")
        if diff_output.strip() == "":
            debug("git diff --cached returned nothing, falling back to git diff.")
            (unused, diff_output) = getstatusoutput("git diff")

        if diff_output.strip() == "":
            print("No changes in main branch, skipping commit for: %s" % main_branch)
        else:
            print(diff_output)
            print("")
            print("##### Please review the above diff #####")
            if not self._ask_yes_no("Do you wish to proceed with commit? [y/n] "):
                print("Fine, you're on your own!")
                self.cleanup()
                sys.exit(1)

            print("Proceeding with commit.")
            commit_msg_file = self._confirm_commit_msg(diff_output)
            cmd = '%s commit -F %s' % (self.cli_tool,
                    commit_msg_file)
            debug("git commit command: %s" % cmd)
            print
            if self.dry_run:
                self.print_dry_run_warning(cmd)
            else:
                print("Proceeding with commit.")
                os.chdir(self.package_workdir)
                run_command(cmd)

            os.unlink(commit_msg_file)

        cmd = "%s push" % self.cli_tool
        if self.dry_run:
            self.print_dry_run_warning(cmd)
        else:
            # Push
            print(cmd)
            try:
                run_command(cmd)
            except RunCommandException as e:
                error_out("`%s` failed with: %s" % (cmd, e.output))

        if not self.no_build:
            self._build(main_branch)

        for branch in self.git_branches[1:]:
            info_out("Merging branch: '%s' -> '%s'" % (main_branch, branch))
            run_command("%s switch-branch %s" % (self.cli_tool, branch))
            self._merge(main_branch)

            cmd = "git push origin %s:%s" % (branch, branch)
            if self.dry_run:
                self.print_dry_run_warning(cmd)
            else:
                print(cmd)
                try:
                    run_command(cmd)
                except RunCommandException as e:
                    error_out("`%s` failed with: %s" % (cmd, e.output))

            if not self.no_build:
                self._build(branch)

            print
Beispiel #28
0
    def _bump_version(self, release=False, zstream=False):
        """
        Bump up the package version in the spec file.

        Set release to True to bump the package release instead.

        Checks for the keep version option and if found, won't actually
        bump the version or release.
        """
        old_version = get_latest_tagged_version(self.project_name)
        if old_version is None:
            old_version = "untagged"
        if not self.keep_version:
            version_regex = re.compile("^(version:\s*)(.+)$", re.IGNORECASE)
            release_regex = re.compile("^(release:\s*)(.+)$", re.IGNORECASE)

            in_f = open(self.spec_file, 'r')
            out_f = open(self.spec_file + ".new", 'w')

            for line in in_f.readlines():
                if release:
                    match = re.match(release_regex, line)
                    if match:
                        line = "".join(
                            (match.group(1), increase_version(match.group(2)),
                             "\n"))
                elif zstream:
                    match = re.match(release_regex, line)
                    if match:
                        line = "".join(
                            (match.group(1), increase_zstream(match.group(2)),
                             "\n"))
                elif hasattr(self, '_use_version'):
                    match = re.match(version_regex, line)
                    if match:
                        line = "".join(
                            (match.group(1), self._use_version, "\n"))

                    match = re.match(release_regex, line)
                    if match:
                        line = "".join((match.group(1),
                                        reset_release(match.group(2)), "\n"))
                else:
                    match = re.match(version_regex, line)
                    if match:
                        line = "".join(
                            (match.group(1), increase_version(match.group(2)),
                             "\n"))

                    match = re.match(release_regex, line)
                    if match:
                        line = "".join((match.group(1),
                                        reset_release(match.group(2)), "\n"))

                out_f.write(line)

            in_f.close()
            out_f.close()
            shutil.move(self.spec_file + ".new", self.spec_file)

        new_version = get_spec_version_and_release(self.full_project_dir,
                                                   self.spec_file_name)
        if new_version.strip() == "":
            msg = "Error getting bumped package version, try: \n"
            msg = msg + "  'rpm -q --specfile %s'" % self.spec_file
            error_out(msg)
        info_out("Tagging new version of %s: %s -> %s" %
                 (self.project_name, old_version, new_version))
        return new_version
Beispiel #29
0
    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