Beispiel #1
0
    def add_fetch_parser_args(parser, defaults):
        """Public method for adding standard "fetch" related arguments.

    This is intended to be used by other commands wanting to be consistent.
    """
        add_argument = FetchSourceCommandFactory.add_argument
        GitRunner.add_git_parser_args(parser, defaults, pull=True)
        add_argument(
            parser,
            'fetch_bom_version',
            defaults,
            None,
            help='Pull this BOM version rather than --git_branch.'
            ' This requires halyard is installed to retrieve the BOM.')
        add_argument(
            parser,
            'fetch_bom_path',
            defaults,
            None,
            help='Pull versions from this BOM rather than --git_branch.')
        add_argument(parser,
                     'git_refresh',
                     defaults,
                     None,
                     help='Refresh existing source from this branch.')
Beispiel #2
0
def make_default_options():
    """Helper function for creating default options for runner."""
    parser = argparse.ArgumentParser()
    parser.add_argument('--scratch_dir',
                        default=os.path.join('/tmp',
                                             'gittest.%d' % os.getpid()))
    GitRunner.add_git_parser_args(parser, {})
    return parser.parse_args([])
Beispiel #3
0
    def _do_init_argparser(self, parser, defaults):
        """Adds command-specific arguments."""
        super(PullRequestCommandFactory,
              self)._do_init_argparser(parser, defaults)
        GitRunner.add_git_parser_args(parser, defaults, pull_request=True)

        self.add_argument(parser,
                          'spinnaker_version',
                          defaults,
                          None,
                          required=True,
                          help='The spinnaker version to publish for.')
Beispiel #4
0
 def __init__(self, factory, options, repository, branch_decorator,
              **kwargs):
     super(PullRequestCommandProcessor,
           self).__init__(factory, options, **kwargs)
     self.__repository = repository
     name = repository.name
     self.__named_scratch_dir = os.path.join(options.scratch_dir, name)
     self.__git_dir = os.path.join(options.root_path, name)
     self.__git = GitRunner(options)
     self.__branch_decorator = branch_decorator
     self.__head_branch = '{version}-{decorator}'.format(
         version=options.spinnaker_version,
         decorator=self.__branch_decorator)
Beispiel #5
0
    def setUpClass(cls):
        cls.git = GitRunner(make_default_options())
        cls.base_temp_dir = tempfile.mkdtemp(prefix='git_test')
        cls.git_dir = os.path.join(cls.base_temp_dir, UPSTREAM_USER,
                                   TEST_REPO_NAME)
        os.makedirs(cls.git_dir)

        git_dir = cls.git_dir
        gitify = lambda args: 'git -C "{dir}" {args}'.format(dir=git_dir,
                                                             args=args)
        check_subprocess_sequence([
            gitify('init'), 'touch "{dir}/base_file"'.format(dir=git_dir),
            gitify('add "{dir}/base_file"'.format(dir=git_dir)),
            gitify('commit -a -m "feat(test): added file"'),
            gitify(
                'tag {base_version} HEAD'.format(base_version=VERSION_BASE)),
            gitify(
                'checkout -b {base_branch}'.format(base_branch=BRANCH_BASE)),
            gitify('checkout -b {a_branch}'.format(a_branch=BRANCH_A)),
            'touch "{dir}/a_file"'.format(dir=git_dir),
            gitify('add "{dir}/a_file"'.format(dir=git_dir)),
            gitify('commit -a -m "feat(test): added a_file"'),
            gitify('tag {a_version} HEAD'.format(a_version=VERSION_A)),
            gitify('checkout -b {b_branch}'.format(b_branch=BRANCH_B)),
            'touch "{dir}/b_file"'.format(dir=git_dir),
            gitify('add "{dir}/b_file"'.format(dir=git_dir)),
            gitify('commit -a -m "feat(test): added b_file"'),
            gitify('tag {b_version} HEAD'.format(b_version=VERSION_B))
        ])
Beispiel #6
0
def main():
  """The main command dispatcher."""

  GitRunner.stash_and_clear_auth_env_vars()

  import buildtool.source_commands
  import buildtool.build_commands
  import buildtool.bom_commands
  import buildtool.changelog_commands
  import buildtool.apidocs_commands
  import buildtool.image_commands
  command_modules = [
      buildtool.source_commands,
      buildtool.build_commands,
      buildtool.bom_commands,
      buildtool.changelog_commands,
      buildtool.apidocs_commands,
      buildtool.image_commands
  ]

  options, command_registry = init_options_and_registry(
      sys.argv[1:], command_modules)

  logging.basicConfig(
      format='%(levelname).1s %(asctime)s.%(msecs)03d'
             ' [%(threadName)s.%(process)d] %(message)s',
      datefmt='%H:%M:%S',
      level=STANDARD_LOG_LEVELS[options.log_level])

  logging.debug(
      'Running with options:\n   %s',
      '\n   '.join(yaml.dump(vars(options), default_flow_style=False)
                   .split('\n')))

  factory = command_registry.get(options.command)
  if not factory:
    logging.error('Unknown command "%s"', options.command)
    return -1

  MetricsManager.startup_metrics(options)
  try:
    command = factory.make_command(options)
    command()
  finally:
    MetricsManager.shutdown_metrics()

  return 0
Beispiel #7
0
 def __determine_repo_install_args(self):
     """Determine --spinnaker_dev-github_[owner|user] args for install script."""
     options = self.options
     branch = options.git_branch
     owner = ('spinnaker' if options.github_user in ('default', 'upstream')
              else options.github_user)
     git_dir = os.path.dirname(__file__)
     if not branch:
         branch = GitRunner(options).query_local_repository_branch(git_dir)
     if not owner:
         url = (GitRunner(options).determine_remote_git_repository(
             git_dir).url)
         owner = re.search('github.com/(.+)/spinnaker', url).group(1)
     return [
         '--spinnaker_dev_github_owner', owner,
         '--spinnaker_dev_github_branch', branch
     ]
Beispiel #8
0
    def setUpClass(cls):
        cls.git = GitRunner(make_default_options())
        cls.base_temp_dir = tempfile.mkdtemp(prefix='scm_test')
        origin_root = os.path.join(cls.base_temp_dir, 'origin_repos')

        repository_list = [
            RemoteGitRepository.make_from_url(url) for url in [
                os.path.join(origin_root, SCM_USER, 'RepoOne'),
                os.path.join(origin_root, SCM_USER, 'RepoTwo'),
                os.path.join(origin_root, TEST_USER, 'RepoTest')
            ]
        ]

        cls.TEST_SOURCE_REPOSITORIES = {
            repo.name: repo
            for repo in repository_list
        }

        for repo in repository_list:
            os.makedirs(repo.url)
            base_file = os.path.join(repo.url,
                                     '{name}-base.txt'.format(name=repo.name))
            unique_file = os.path.join(
                repo.url, '{name}-unique.txt'.format(name=repo.name))
            untagged_file = os.path.join(
                repo.url, '{name}-untagged.txt'.format(name=repo.name))

            logging.debug('Initializing repository %s', repo.url)
            git_prefix = 'git -C "{dir}" '.format(dir=repo.url)
            run_git = lambda cmd: git_prefix + cmd

            check_subprocess_sequence([
                # BASE_VERSION
                'touch "{file}"'.format(file=base_file),
                run_git(' init'),
                run_git(
                    'add "{file}"'.format(file=os.path.basename(base_file))),
                run_git('commit -a -m "feat(first): first commit"'),
                run_git('tag {base_version} HEAD'.format(
                    base_version=BASE_VERSION)),

                # Add Unique branch name per repo
                run_git('checkout -b {name}-branch'.format(name=repo.name)),
                'touch "{file}"'.format(file=unique_file),
                run_git(
                    'add "{file}"'.format(file=os.path.basename(unique_file))),
                run_git('commit -a -m "chore(uniq): unique commit"'),

                # Add a common branch name, but without a tag on HEAD
                run_git('checkout master'),
                run_git('checkout -b {branch}'.format(branch=UNTAGGED_BRANCH)),
                'touch "{file}"'.format(file=untagged_file),
                run_git('add "{file}"'.format(
                    file=os.path.basename(untagged_file))),
                run_git('commit -a -m "chore(uniq): untagged commit"'),
                run_git('checkout master')
            ])
Beispiel #9
0
 def test_different_repo(self):
     variants = [
         'http://github.com/user/spinnaker',
         'http://github.com/path/user/spinnaker',
         'http://github.com/user/spinnaker/path',
         'http://github.com/user/spinnaker.github',
         'http://github/user/spinnaker',
         'http://mydomain.com/user/spinnaker', 'path/user/spinnaker'
     ]
     for url in variants[1:]:
         self.assertFalse(GitRunner.is_same_repo(variants[0], url))
Beispiel #10
0
 def test_is_same_repo(self):
     variants = [
         'http://github.com/user/spinnaker',
         'http://github.com/user/spinnaker.git',
         'https://github.com/user/spinnaker',
         'https://github.com/user/spinnaker.git',
         '[email protected]:user/spinnaker.git',
         '[email protected]:user/spinnaker.git'
     ]
     for url in variants:
         self.assertTrue(GitRunner.is_same_repo(variants[0], url))
Beispiel #11
0
    def __init__(self, factory, options, **kwargs):
        source_repos = kwargs.pop('source_repositories', None)
        self.__max_threads = kwargs.pop('max_threads', 64)
        self.__git = kwargs.pop('git', None) or GitRunner(options)
        self.__scm = None

        if options.one_at_a_time:
            logging.debug('Limiting %s to one thread.', factory.name)
            self.__max_threads = 1

        super(RepositoryCommandProcessor,
              self).__init__(factory, options, **kwargs)

        # filter needs the options, so this is after our super init call.
        self.__source_repositories = (self.filter_repositories(source_repos)
                                      if source_repos is not None else None)
Beispiel #12
0
    def setUpClass(cls):
        cls.git = GitRunner(make_default_options())
        cls.base_temp_dir = tempfile.mkdtemp(prefix='git_test')
        cls.git_dir = os.path.join(cls.base_temp_dir, 'commit_message_test')
        os.makedirs(cls.git_dir)

        git_dir = cls.git_dir
        gitify = lambda args: 'git -C "{dir}" {args}'.format(dir=git_dir,
                                                             args=args)
        check_subprocess_sequence([
            gitify('init'), 'touch "{dir}/base_file"'.format(dir=git_dir),
            gitify('add "{dir}/base_file"'.format(dir=git_dir)),
            gitify('commit -a -m "feat(test): added file"'),
            gitify(
                'tag {base_version} HEAD'.format(base_version=VERSION_BASE)),
            gitify('checkout -b {patch_branch}'.format(
                patch_branch=cls.PATCH_BRANCH)),
            'touch "{dir}/patch_file"'.format(dir=git_dir),
            gitify('add "{dir}/patch_file"'.format(dir=git_dir)),
            gitify('commit -a -m "fix(testA): added patch_file"'),
            gitify('checkout -b {minor_branch}'.format(
                minor_branch=cls.MINOR_BRANCH)),
            'touch "{dir}/minor_file"'.format(dir=git_dir),
            gitify('add "{dir}/minor_file"'.format(dir=git_dir)),
            gitify('commit -a -m "chore(testB): added minor_file"'),
            gitify('checkout -b {major_branch}'.format(
                major_branch=cls.MAJOR_BRANCH)),
            'touch "{dir}/major_file"'.format(dir=git_dir),
            gitify('add "{dir}/major_file"'.format(dir=git_dir)),
            gitify('commit -a -m'
                   ' "feat(testC): added major_file\n'
                   '\nInterestingly enough, this is a BREAKING CHANGE.'
                   '"'),
            gitify('checkout -b {merged_branch}'.format(
                merged_branch=cls.MERGED_BRANCH)),
            gitify('reset --hard HEAD~3'),
            gitify('merge --squash HEAD@{1}')
        ])
        env = dict(os.environ)
        if os.path.exists('/bin/true'):
            env['EDITOR'] = '/bin/true'
        elif os.path.exists('/usr/bin/true'):
            env['EDITOR'] = '/usr/bin/true'
        else:
            raise NotImplementedError('platform not supported for this test')
        check_subprocess('git -C "{dir}" commit'.format(dir=git_dir), env=env)
Beispiel #13
0
class PullRequestCommandProcessor(CommandProcessor):
    """Base class for commands that issue pull requests."""
    @property
    def repository(self):
        """The repository to submit the PR to."""
        return self.__repository

    @property
    def git_dir(self):
        """The local repository to push changes from."""
        return self.__git_dir

    @property
    def named_scratch_dir(self):
        """The scratch dir associated with the local repository."""
        return self.__named_scratch_dir

    @property
    def git(self):
        """Return GitRunner"""
        return self.__git

    @property
    def base_branch(self):
        """The branch we are sending the pull request to."""
        return self.options.git_branch

    @property
    def head_branch(self):
        """The branch we are sending the pull request from."""
        return self.__head_branch

    def __init__(self, factory, options, repository, branch_decorator,
                 **kwargs):
        super(PullRequestCommandProcessor,
              self).__init__(factory, options, **kwargs)
        self.__repository = repository
        name = repository.name
        self.__named_scratch_dir = os.path.join(options.scratch_dir, name)
        self.__git_dir = os.path.join(options.root_path, name)
        self.__git = GitRunner(options)
        self.__branch_decorator = branch_decorator
        self.__head_branch = '{version}-{decorator}'.format(
            version=options.spinnaker_version,
            decorator=self.__branch_decorator)

    def _do_get_commit_message(self):
        """Returns the commit message to use for the local repository commit."""
        raise NotImplementedError()

    def _do_add_local_repository_files(self):
        """Returns a list of files we want to push."""
        raise NotImplementedError()

    def _do_command(self):
        """Write changelog to the origin repository. Open PR against upstream."""
        self._ensure_local_repo()

        git_dir = self.git_dir

        self.__git.check_git(git_dir, 'checkout ' + self.base_branch)
        self.__git.delete_local_branch_if_exists(git_dir, self.head_branch)
        files_added = self._do_add_local_repository_files()

        message = self._do_get_commit_message()

        git_commands = [
            # These commands are accomodating to a branch already existing
            # because the branch is on the version, not build. A rejected
            # build for some reason that is re-tried will have the same version
            # so the branch may already exist from the earlier attempt.
            'checkout -b {head}'.format(head=self.head_branch),
            'add {path}'.format(
                path=' '.join([os.path.abspath(path)
                               for path in files_added])),
            'commit -m "{msg}"'.format(msg=message),
            'push origin -f {head}'.format(head=self.head_branch)
        ]
        origin = self.__git.determine_remote_git_repository(git_dir)
        logging.info('Pushing branch %s to %s', self.head_branch, origin.url)
        self.__git.check_git_sequence(git_dir, git_commands)
        if self.options.no_pr:
            logging.warning('--no_pr set; NOT creating a pull request.')
            return

        self.__git.initiate_github_pull_request(git_dir,
                                                message,
                                                head=self.head_branch,
                                                base=self.base_branch)

    def _ensure_local_repo(self):
        """Make sure there's a local repository and fetch one if not."""
        if os.path.exists(self.git_dir):
            return

        options = self.options
        name = self.repository.name
        user = ('spinnaker' if options.github_user in ('default', 'upstream')
                else options.github_user)
        url = 'https://github.com/{user}/{name}'.format(user=user, name=name)
        self.git.clone_repository_to_path(url,
                                          self.git_dir,
                                          upstream_url=self.repository.url,
                                          branch=options.git_branch)
Beispiel #14
0
def make_default_options():
    """Helper function for creating default options for runner."""
    parser = argparse.ArgumentParser()
    GitRunner.add_git_parser_args(parser, {})
    return parser.parse_args([])