Beispiel #1
0
    def test_maybe_pull_repository_branch(self):
        test_root = os.path.join(self.base_temp_dir, 'pulled_test')
        options = make_default_options()
        options.git_branch = UNTAGGED_BRANCH
        options.build_number = 'maybe_pull_branch_buildnum'
        scm = BranchSourceCodeManager(options, test_root)

        for repository_name, origin in self.ORIGIN_URLS.items():
            repository = scm.make_repository_spec(repository_name,
                                                  origin=origin,
                                                  upstream=None)
            scm.ensure_local_repository(repository)

            git_dir = repository.git_dir
            spec = scm.git.determine_git_repository_spec(git_dir)
            self.assertEqual(repository, spec)

            in_branch = scm.git.query_local_repository_branch(git_dir)
            self.assertEqual(UNTAGGED_BRANCH, in_branch)

            summary = scm.git.collect_repository_summary(git_dir)
            semver = SemanticVersion.make(BASE_VERSION)
            expect_version = semver.next(
                SemanticVersion.MINOR_INDEX).to_version()

            self.assertEqual(expect_version, summary.version)
Beispiel #2
0
    def test_check_repository_commit(self):
        self.options.git_branch = UNTAGGED_BRANCH

        test_root = os.path.join(self.base_temp_dir, 'check_commit_test')
        scm = BranchSourceCodeManager(self.options, test_root)
        repository_name = 'RepoOne'
        origin = self.ORIGIN_URLS[repository_name]
        repository = scm.make_repository_spec(repository_name,
                                              origin=origin,
                                              upstream=None)
        scm.ensure_local_repository(repository)
        scm.check_repository_is_current(repository)

        # Create another repo pinned to this particular commit.
        commit = scm.git.query_local_repository_commit_id(repository.git_dir)
        repository_at_commit = scm.make_repository_spec(repository_name,
                                                        origin=origin,
                                                        upstream=None,
                                                        commit_id=commit)

        # We're at the commit, so this should validate.
        scm.check_repository_is_current(repository_at_commit)

        # Make a change to the repo so commit differs.
        with open(os.path.join(repository.git_dir, 'scrap'), 'w') as stream:
            stream.write('hello')
        scm.git.check_run(repository.git_dir, 'add scrap')
        scm.git.check_run(repository.git_dir, 'commit -a -m "added file"')

        # We're still in the branch, so the branch only repository is still ok,
        # but no longer at the same commit, so the commit-pinned repository is bad.
        scm.check_repository_is_current(repository)
        self.assertRaises(UnexpectedError, scm.check_repository_is_current,
                          repository_at_commit)
  def test_check_repository_branch(self):
    self.options.git_branch = UNTAGGED_BRANCH
    
    test_root = os.path.join(self.base_temp_dir, 'check_branch_test')
    scm = BranchSourceCodeManager(self.options, test_root)
    repository_name = 'RepoOne'
    origin = self.ORIGIN_URLS[repository_name]
    repository = scm.make_repository_spec(repository_name, origin=origin,
                                          upstream=None)
    scm.ensure_local_repository(repository)
    scm.check_repository_is_current(repository)

    scm.git.check_run(repository.git_dir, 'checkout master')
    self.assertRaises(UnexpectedError, scm.check_repository_is_current, repository)
Beispiel #4
0
    def test_pull_repository_fallback_branch(self):
        test_root = os.path.join(self.base_temp_dir, "fallback_test")
        unique_branch = "RepoTwo-branch"
        options = make_default_options()
        options.git_branch = unique_branch
        options.git_fallback_branch = "master"
        options.build_number = "pull_repository_fallback_buildnumber"
        scm = BranchSourceCodeManager(options, test_root)

        for repo_name, origin in self.ORIGIN_URLS.items():
            repository = scm.make_repository_spec(repo_name, origin=origin)
            scm.ensure_local_repository(repository)
            git_dir = repository.git_dir
            want_branch = unique_branch if repository.name == "RepoTwo" else "master"
            in_branch = scm.git.query_local_repository_branch(git_dir)
            self.assertEqual(want_branch, in_branch)
Beispiel #5
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',
        '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())

  def push_branches_and_tags(self, bom):
    """Update the release branches and tags in each of the BOM repositires."""
    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, self.__branch)
          if added:
            names_to_push.add(name)
        else:
          self.__push_branch_and_maybe_tag_repository(
              repository, self.__branch, name in names_to_push)

    additional_repositories = list(SPINNAKER_PROCESS_REPOSITORY_NAMES)
    additional_repositories.extend(SPINNAKER_SHARED_REPOSITORY_NAMES)
    for name in additional_repositories:
      if self.__only_repositories and name not in self.__only_repositories:
        logging.debug('Skipping %s because of --only_repositories', name)
        continue
      repository = self.__process_scm.make_repository_spec(name)
      self.__process_scm.ensure_local_repository(repository)
      if self.__branch_and_tag_repository(repository, self.__branch):
        self.__push_branch_and_maybe_tag_repository(
            repository, self.__branch, True)

  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:
      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()