Exemple #1
0
  def test_pull_bom(self):
    input_dir = self.test_root
    scm = BomSourceCodeManager(self.options, input_dir, bom=self.golden_bom)
    for repo_name in ALL_STANDARD_TEST_BOM_REPO_NAMES:
      repository = scm.make_repository_spec(repo_name)
      self.assertFalse(os.path.exists(repository.git_dir))
      scm.ensure_local_repository(repository)
      self.assertTrue(os.path.exists(repository.git_dir))

      git_dir = repository.git_dir
      spec = scm.git.determine_git_repository_spec(git_dir)
      self.assertEqual(repository.name, spec.name)
      self.assertEqual(repository.git_dir, spec.git_dir)
      self.assertEqual(repository.origin, spec.origin)
      self.assertIsNone(spec.upstream_or_none())

      repo_name = repository.name
      at_commit = scm.git.query_local_repository_commit_id(git_dir)
      self.assertEqual(
          self.repo_commit_map[repo_name]['ORIGIN'], repository.origin)
      self.assertEqual(
          self.repo_commit_map[repo_name][PATCH_BRANCH], at_commit)

      summary = scm.git.collect_repository_summary(git_dir)
      semver = SemanticVersion.make(BASE_VERSION_TAG)
      expect_version = semver.next(
          SemanticVersion.PATCH_INDEX).to_version()
      self.assertEqual(expect_version, summary.version)
Exemple #2
0
  def test_pull_bom(self):
    input_dir = self.test_root
    scm = BomSourceCodeManager(self.options, input_dir, bom=self.golden_bom)
    for repo_name in ALL_STANDARD_TEST_BOM_REPO_NAMES:
      repository = scm.make_repository_spec(repo_name)
      self.assertFalse(os.path.exists(repository.git_dir))
      scm.ensure_local_repository(repository)
      self.assertTrue(os.path.exists(repository.git_dir))

      git_dir = repository.git_dir
      spec = scm.git.determine_git_repository_spec(git_dir)
      self.assertEquals(repository.name, spec.name)
      self.assertEquals(repository.git_dir, spec.git_dir)
      self.assertEquals(repository.origin, spec.origin)
      self.assertIsNone(spec.upstream_or_none())

      repo_name = repository.name
      at_commit = scm.git.query_local_repository_commit_id(git_dir)
      self.assertEquals(
          self.repo_commit_map[repo_name]['ORIGIN'], repository.origin)
      self.assertEquals(
          self.repo_commit_map[repo_name][PATCH_BRANCH], at_commit)

      summary = scm.git.collect_repository_summary(git_dir)
      semver = SemanticVersion.make(BASE_VERSION_TAG)
      expect_version = semver.next(
          SemanticVersion.PATCH_INDEX).to_version()
      self.assertEquals(expect_version, summary.version)
Exemple #3
0
  def __init__(self, factory, options, **kwargs):
    super(PublishSpinnakerCommand, self).__init__(factory, options, **kwargs)
    check_options_set(options, [
        'spinnaker_version',
        'spinnaker_release_alias',
        'bom_version',
        'changelog_gist_url',
        'github_owner',
        'min_halyard_version'
    ])

    major, minor, _ = self.options.spinnaker_version.split('.')
    self.__branch = 'release-{major}.{minor}.x'.format(
        major=major, minor=minor)

    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)
    if options.only_repositories:
      self.__only_repositories = options.only_repositories.split(',')
    else:
      self.__only_repositories = []

    options_copy.git_branch = self.__branch
    self.__process_scm = BranchSourceCodeManager(
        options_copy, self.get_input_dir())
Exemple #4
0
    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)
Exemple #5
0
 def init_argparser(self, parser, defaults):
   super(PublishSpinCommandFactory, self).init_argparser(
       parser, defaults)
   self.add_argument(
       parser, 'spin_bucket', defaults, None,
       help='The bucket to publish spin binaries to.')
   self.add_argument(
       parser, 'spin_credentials_path', defaults, None,
       help='The credentials to use to authenticate with the bucket.')
   self.add_argument(
       parser, 'spin_version', defaults, None,
       help='The semantic version of the release to publish.')
   # BomSourceCodeManager adds bom_version and bom_path arguments to fetch BOMs.
   BomSourceCodeManager.add_parser_args(parser, defaults)
Exemple #6
0
  def init_argparser(self, parser, defaults):
    """Adds command-specific arguments."""
    super(BuildSpinCommandFactory, self).init_argparser(parser, defaults)

    self.add_argument(
        parser, 'build_number', defaults, DEFAULT_BUILD_NUMBER,
        help='The the build number to use when building spin.')
    self.add_argument(
        parser, 'spin_bucket', defaults, None,
        help='The bucket to publish spin binaries to.')
    self.add_argument(
        parser, 'spin_credentials_path', defaults, None,
        help='The credentials to use to authenticate with the bucket.')
    # BomSourceCodeManager adds bom_version and bom_path arguments to fetch BOMs.
    BomSourceCodeManager.add_parser_args(parser, defaults)
Exemple #7
0
  def init_argparser(self, parser, defaults):
    """Adds command-specific arguments."""
    super(BuildSpinCommandFactory, self).init_argparser(parser, defaults)

    self.add_argument(
        parser, 'build_number', defaults, DEFAULT_BUILD_NUMBER,
        help='The the build number to use when building spin.')
    self.add_argument(
        parser, 'spin_bucket', defaults, None,
        help='The bucket to publish spin binaries to.')
    self.add_argument(
        parser, 'spin_credentials_path', defaults, None,
        help='The credentials to use to authenticate with the bucket.')
    # BomSourceCodeManager adds bom_version and bom_path arguments to fetch BOMs.
    BomSourceCodeManager.add_parser_args(parser, defaults)
Exemple #8
0
 def init_argparser(self, parser, defaults):
   GitRunner.add_parser_args(parser, defaults)
   GitRunner.add_publishing_parser_args(parser, defaults)
   super(PublishSpinCommandFactory, self).init_argparser(
       parser, defaults)
   self.add_argument(
       parser, 'spin_bucket', defaults, None,
       help='The bucket to publish spin binaries to.')
   self.add_argument(
       parser, 'spin_credentials_path', defaults, None,
       help='The credentials to use to authenticate with the bucket.')
   self.add_argument(
       parser, 'spin_version', defaults, None,
       help='The semantic version of the release to publish.')
   # BomSourceCodeManager adds bom_version and bom_path arguments to fetch BOMs.
   BomSourceCodeManager.add_parser_args(parser, defaults)
    def __init__(self, factory, options, **kwargs):
        super(PublishSpinnakerCommand, self).__init__(factory, options,
                                                      **kwargs)
        check_options_set(
            options,
            [
                "spinnaker_version",
                "spinnaker_release_alias",
                "bom_version",
                "changelog_gist_url",
                "github_owner",
                "min_halyard_version",
            ],
        )

        major, minor, _ = self.options.spinnaker_version.split(".")
        self.__branch = "release-{major}.{minor}.x".format(major=major,
                                                           minor=minor)

        options_copy = copy.copy(options)
        self.__bom_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)
        if options.only_repositories:
            self.__only_repositories = options.only_repositories.split(",")
        else:
            self.__only_repositories = []

        options_copy.git_branch = self.__branch
        self.__branch_scm = BranchSourceCodeManager(options_copy,
                                                    self.get_input_dir())
Exemple #10
0
 def __init__(self, factory, options, **kwargs):
   super(BuildSpinCommand, self).__init__(
     factory, options, source_repository_names=['spin'], **kwargs)
   self.__gcs_uploader = SpinGcsUploader(options)
   self.__build_version = None  # recorded after build
   bom_contents = BomSourceCodeManager.load_bom(options)
   gate_entry = bom_contents.get('services', {}).get('gate', {})
   if not gate_entry:
     raise_and_log_error(
         ConfigError('No gate service entry found in bom {}'.format(bom_contents)))
   self.__gate_version = gate_entry['version']
Exemple #11
0
 def __init__(self, factory, options, **kwargs):
   super(BuildSpinCommand, self).__init__(
     factory, options, source_repository_names=SPIN_REPOSITORY_NAMES, **kwargs)
   options_copy = copy.copy(options)
   self.__gcs_uploader = SpinGcsUploader(options)
   self.__scm = BranchSourceCodeManager(options_copy, self.get_input_dir())
   self.__build_version = None  # recorded after build
   bom_contents = BomSourceCodeManager.load_bom(options)
   gate_entry = bom_contents.get('services', {}).get('gate', {})
   if not gate_entry:
     raise_and_log_error(
         ConfigError('No gate service entry found in bom {}'.format(bom_contents)))
   self.__gate_version = gate_entry['version']
Exemple #12
0
  def __init__(self, factory, options, **kwargs):
    options_copy = copy.copy(options)
    options_copy.git_branch = 'master'
    options_copy.github_hostname = 'github.com'
    super(PublishSpinCommand, self).__init__(factory, options_copy, **kwargs)

    check_options_set(options, ['spin_version']) # Ensure we have a version to promote.
    bom_contents = BomSourceCodeManager.load_bom(options_copy)
    gate_entry = bom_contents.get('services', {}).get('gate', {})
    if not gate_entry:
      raise_and_log_error(
          ConfigError('No gate service entry found in bom {}'.format(bom_contents)))

    self.__spinnaker_version = options.bom_version or bom_contents['version']
    self.__gate_version = gate_entry['version']
    self.__stable_version = None # Set after promote_spin.
    self.__no_changes = False # Set after promote_spin.
    self.__scm = BranchSourceCodeManager(options_copy, self.get_input_dir())
    self.__gcs_uploader = SpinGcsUploader(options)
Exemple #13
0
  def __init__(self, factory, options, **kwargs):
    options_copy = copy.copy(options)
    options_copy.git_branch = 'master'
    options_copy.github_hostname = 'github.com'
    super(PublishSpinCommand, self).__init__(factory, options_copy, **kwargs)

    check_options_set(options, ['spin_version']) # Ensure we have a version to promote.
    bom_contents = BomSourceCodeManager.load_bom(options_copy)
    gate_entry = bom_contents.get('services', {}).get('gate', {})
    if not gate_entry:
      raise_and_log_error(
          ConfigError('No gate service entry found in bom {}'.format(bom_contents)))

    self.__spinnaker_version = options.bom_version or bom_contents['version']
    self.__gate_version = gate_entry['version']
    self.__stable_version = None # Set after promote_spin.
    self.__no_changes = False # Set after promote_spin.
    self.__scm = BranchSourceCodeManager(options_copy, self.get_input_dir())
    self.__gcs_uploader = SpinGcsUploader(options)
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', 'spinnaker_release_alias', '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)
        if options.only_repositories:
            self.__only_repositories = options.only_repositories.split(',')
        else:
            self.__only_repositories = []

    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.
        names_to_push = set([])
        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':
                    added = self.__branch_and_tag_repository(
                        repository, branch)
                    if added:
                        names_to_push.add(name)
                else:
                    self.__push_branch_and_maybe_tag_repository(
                        repository, branch, name in names_to_push)

    def __already_have_tag(self, repository, tag):
        """Determine if we already have the tag in the repository."""
        git_dir = repository.git_dir
        existing_commit = self.__git.query_commit_at_tag(git_dir, tag)
        if not existing_commit:
            return False
        want_commit = self.__git.query_local_repository_commit_id(git_dir)
        if want_commit == existing_commit:
            logging.debug('Already have "%s" at %s', tag, want_commit)
            return True

        raise_and_log_error(
            ConfigError(
                '"{tag}" already exists in "{repo}" at commit {have}, not {want}'
                .format(tag=tag,
                        repo=git_dir,
                        have=existing_commit,
                        want=want_commit)))

    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
        if self.__already_have_tag(repository, tag):
            return False

        self.__git.check_run(repository.git_dir, 'tag ' + tag)
        return True

    def __push_branch_and_maybe_tag_repository(self, repository, branch,
                                               also_tag):
        """Push the branch and verison tag to the origin."""
        tag = 'version-' + self.__scm.determine_repository_version(repository)
        self.__git.push_branch_to_origin(repository.git_dir, branch)
        if also_tag:
            self.__git.push_tag_to_origin(repository.git_dir, tag)
        else:
            logging.info('%s was already tagged with "%s" -- skip',
                         repository.git_dir, tag)

    def _do_command(self):
        """Implements CommandProcessor interface."""
        options = self.options
        spinnaker_version = options.spinnaker_version
        options_copy = copy.copy(options)
        options_copy.git_branch = 'master'  # push to master in spinnaker.github.io
        publish_changelog_command = PublishChangelogFactory().make_command(
            options_copy)
        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)
            urlopen(changelog_gist_url)
        except HTTPError as error:
            logging.error(exception_to_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.safe_dump(bom, default_flow_style=False), bom_path)
        self.__hal.publish_bom_path(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()
Exemple #15
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)