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