Example #1
0
class PublishSpinnakerCommand(CommandProcessor):
    """"Implements the publish_spinnaker command."""

    # pylint: disable=too-few-public-methods

    def __init__(self, factory, options, **kwargs):
        super(PublishSpinnakerCommand, self).__init__(factory, options,
                                                      **kwargs)
        check_options_set(options, [
            'spinnaker_version', 'bom_version', 'github_owner',
            'min_halyard_version'
        ])

        options_copy = copy.copy(options)
        self.__scm = BomSourceCodeManager(options_copy, self.get_input_dir())
        self.__hal = HalRunner(options)
        self.__git = GitRunner(options)
        self.__hal.check_property('spinnaker.config.input.bucket',
                                  options.halyard_bom_bucket)

    def push_branches_and_tags(self, bom):
        """Update the release branches and tags in each of the BOM repositires."""
        major, minor, _ = self.options.spinnaker_version.split('.')
        branch = 'release-{major}.{minor}.x'.format(major=major, minor=minor)
        logging.info('Tagging each of the BOM service repos')

        # Run in two passes so we dont push anything if we hit a problem
        # in the tagging pass. Since we are spread against multiple repositiories,
        # we cannot do this atomically. The two passes gives us more protection
        # from a partial push due to errors in a repo.
        for which in ['tag', 'push']:
            for name, spec in bom['services'].items():
                if name in ['monitoring-third-party', 'defaultArtifact']:
                    # Ignore this, it is redundant to monitoring-daemon
                    continue
                if spec is None:
                    logging.warning('HAVE bom.services.%s = None', name)
                    continue
                if name == 'monitoring-daemon':
                    name = 'spinnaker-monitoring'
                repository = self.__scm.make_repository_spec(name)
                self.__scm.ensure_local_repository(repository)
                if which == 'tag':
                    self.__branch_and_tag_repository(repository, branch)
                else:
                    self.__push_branch_and_tag_repository(repository, branch)

    def __branch_and_tag_repository(self, repository, branch):
        """Create a branch and/or verison tag in the repository, if needed."""
        source_info = self.__scm.lookup_source_info(repository)
        tag = 'version-' + source_info.summary.version
        self.__git.check_run(repository.git_dir, 'tag ' + tag)

    def __push_branch_and_tag_repository(self, repository, branch):
        """Push the branch and verison tag to the origin."""
        source_info = self.__scm.lookup_source_info(repository)
        tag = 'version-' + source_info.summary.version
        self.__git.push_branch_to_origin(repository.git_dir, branch)
        self.__git.push_tag_to_origin(repository.git_dir, tag)

    def _do_command(self):
        """Implements CommandProcessor interface."""
        options = self.options
        spinnaker_version = options.spinnaker_version
        bom = self.__hal.retrieve_bom_version(self.options.bom_version)
        bom['version'] = spinnaker_version

        self.push_branches_and_tags(bom)
        bom_path = os.path.join(self.get_output_dir(),
                                spinnaker_version + '.yml')
        changelog_base_url = 'https://www.spinnaker.io/%s' % options.github_owner
        changelog_filename = '%s-changelog' % spinnaker_version.replace(
            '.', '-')
        changelog_uri = '%s/community/releases/versions/%s' % (
            changelog_base_url, changelog_filename)

        write_to_path(yaml.dump(bom, default_flow_style=False), bom_path)
        self.__hal.publish_spinnaker_release(spinnaker_version,
                                             options.spinnaker_release_alias,
                                             changelog_uri,
                                             options.min_halyard_version)
class PublishSpinnakerCommand(CommandProcessor):
    """"Implements the publish_spinnaker command."""

    # pylint: disable=too-few-public-methods

    def __init__(self, factory, options, **kwargs):
        super(PublishSpinnakerCommand, self).__init__(factory, options,
                                                      **kwargs)
        check_options_set(options, [
            'spinnaker_version', 'bom_version', 'changelog_gist_url',
            'github_owner', 'min_halyard_version'
        ])

        options_copy = copy.copy(options)
        self.__scm = BomSourceCodeManager(options_copy, self.get_input_dir())
        self.__hal = HalRunner(options)
        self.__git = GitRunner(options)
        self.__hal.check_property('spinnaker.config.input.bucket',
                                  options.halyard_bom_bucket)
        self.__only_repositories = options.only_repositories.split(',')

    def push_branches_and_tags(self, bom):
        """Update the release branches and tags in each of the BOM repositires."""
        major, minor, _ = self.options.spinnaker_version.split('.')
        branch = 'release-{major}.{minor}.x'.format(major=major, minor=minor)
        logging.info('Tagging each of the BOM service repos')

        # Run in two passes so we dont push anything if we hit a problem
        # in the tagging pass. Since we are spread against multiple repositiories,
        # we cannot do this atomically. The two passes gives us more protection
        # from a partial push due to errors in a repo.
        for which in ['tag', 'push']:
            for name, spec in bom['services'].items():
                if name in ['monitoring-third-party', 'defaultArtifact']:
                    # Ignore this, it is redundant to monitoring-daemon
                    continue
                if name == 'monitoring-daemon':
                    name = 'spinnaker-monitoring'
                if self.__only_repositories and name not in self.__only_repositories:
                    logging.debug('Skipping %s because of --only_repositories',
                                  name)
                    continue
                if spec is None:
                    logging.warning('HAVE bom.services.%s = None', name)
                    continue

                repository = self.__scm.make_repository_spec(name)
                self.__scm.ensure_local_repository(repository)
                if which == 'tag':
                    self.__branch_and_tag_repository(repository, branch)
                else:
                    self.__push_branch_and_tag_repository(repository, branch)

    def __branch_and_tag_repository(self, repository, branch):
        """Create a branch and/or verison tag in the repository, if needed."""
        version = self.__scm.determine_repository_version(repository)
        tag = 'version-' + version
        self.__git.check_run(repository.git_dir, 'tag ' + tag)

    def __push_branch_and_tag_repository(self, repository, branch):
        """Push the branch and verison tag to the origin."""
        source_info = self.__scm.lookup_source_info(repository)
        tag = 'version-' + source_info.summary.version
        self.__git.push_branch_to_origin(repository.git_dir, branch)
        self.__git.push_tag_to_origin(repository.git_dir, tag)

    def _do_command(self):
        """Implements CommandProcessor interface."""
        options = self.options
        spinnaker_version = options.spinnaker_version
        publish_changelog_command = PublishChangelogFactory().make_command(
            options)
        changelog_gist_url = options.changelog_gist_url

        # Make sure changelog exists already.
        # If it does not then fail.
        try:
            logging.debug('Verifying changelog ready at %s',
                          changelog_gist_url)
            urllib2.urlopen(changelog_gist_url)
        except urllib2.HTTPError as error:
            logging.error(error.message)
            raise_and_log_error(
                ConfigError(
                    'Changelog gist "{url}" must exist before publising a release.'
                    .format(url=changelog_gist_url),
                    cause='ChangelogMissing'))

        bom = self.__hal.retrieve_bom_version(self.options.bom_version)
        bom['version'] = spinnaker_version
        bom_path = os.path.join(self.get_output_dir(),
                                spinnaker_version + '.yml')
        write_to_path(yaml.dump(bom, default_flow_style=False), bom_path)
        self.push_branches_and_tags(bom)

        self.__hal.publish_spinnaker_release(spinnaker_version,
                                             options.spinnaker_release_alias,
                                             changelog_gist_url,
                                             options.min_halyard_version)

        logging.info('Publishing changelog')
        publish_changelog_command()