def cm(self, pid='pid', deps=(), revision=None, author_email='*****@*****.**', commit_timestamp=None, message_lines=('message', 'lines'), roll_candidate=False): spec = package_pb2.Package( api_version=2, project_id=pid, canonical_repo_url='https://git.example.com/%s.git' % pid, ) for commit in deps: pid = commit.spec.project_id spec.deps[pid].url = commit.spec.canonical_repo_url spec.deps[pid].revision = commit.revision if revision is None: revision = hashlib.sha1(struct.pack('!Q', self.cm_counter)).hexdigest() self.cm_counter += 1 if commit_timestamp is None: commit_timestamp = self.cm_timestamp self.cm_timestamp += 60 * (int(revision[:2], 16) + 1) return CommitMetadata(revision, author_email, commit_timestamp, message_lines, spec, roll_candidate)
def test_cyclic_dependency(self): repos = self._repo_setup({ 'a': [], 'b': ['a'], }) config_file = os.path.join(repos['a']['root'], 'infra', 'config', 'recipes.cfg') package.ProtoFile(config_file).write( package_pb2.Package( api_version=1, project_id='a', recipes_path='', deps=[ package_pb2.DepSpec( project_id='b', url=repos['b']['root'], branch='master', revision=repos['b']['revision'], ), ], )) self._commit_in_repo(repos['a']) with self.assertRaises(RecipeRollError) as raises: self._run_roll(repos['b'], expect_updates=True) self.assertRegexpMatches(raises.exception.stderr, 'CyclicDependencyError')
def test_commit_metadata(self, git): git.side_effect = multi(*([ self.g(['init', 'dir']), self.g(['-C', 'dir', 'ls-remote', 'repo', 'revision'], 'a'*40), ] + self.g_metadata_calls())) result = fetch.GitBackend('dir', 'repo').commit_metadata('revision') self.assertEqual(result, fetch.CommitMetadata( revision = 'a'*40, author_email = '*****@*****.**', commit_timestamp = 1492131405, message_lines = ('hello', 'world'), spec = package_pb2.Package(api_version=2), roll_candidate = True, )) self.assertMultiDone(git)
def repo_setup(self, repo_deps, remote_fake_engine=False): """Creates a set of repos with recipes.cfg reflecting requested dependencies. In order to avoid a topsort, we require that repo names are in alphebetical dependency order -- i.e. later names depend on earlier ones. Normally all repos are created with a dependency on recipe_engine which is a file:// url to the actual recipe_engine repo that this test is running in. If `remote_fake_engine` is True, then it will insert a dependency on the git url with a revision of `deadbeef`. This is useful for testing to make sure that override dependencies actually work correctly. """ repos = {} for k in sorted(repo_deps): deps = { 'recipe_engine': package_pb2.DepSpec(url="file://" + ROOT_DIR), } if remote_fake_engine: deps['recipe_engine'] = package_pb2.DepSpec( branch='master', revision='deadbeefdeadbeefdeadbeefdeadbeefdeadbeef', url= 'https://chromium.googlesource.com/infra/luci/recipes-py.git', ) for d in repo_deps[k]: deps[d] = package_pb2.DepSpec( url=repos[d]['root'], branch='master', revision=repos[d]['revision'], ) repos[k] = self.create_repo( k, package_pb2.Package( api_version=2, project_id=k, recipes_path='', deps=deps, )) return repos
def setUp(self): requests_ssl.disable_check() fetch.Backend._GIT_METADATA_CACHE = {} fetch.GitilesBackend._COMMIT_JSON_CACHE = {} self.proto_text = u"""{ "api_version": 2, "project_id": "foo", "recipes_path": "path/to/recipes" }""".lstrip() self.a = 'a'*40 self.a_dat = { 'commit': self.a, 'author': {'email': '*****@*****.**'}, 'committer': {'time': 'Fri Apr 14 00:56:45 2017'}, 'message': 'message', 'tree_diff': [ { 'old_path': 'unrelated', 'new_path': 'unrelated', }, { 'old_path': 'path/to/recipes/foo', 'new_path': 'path/to/recipes/bar', }, ] } self.a_meta = fetch.CommitMetadata( revision = 'a'*40, author_email = '*****@*****.**', commit_timestamp = 1492131405, message_lines = ('message',), spec = package_pb2.Package( api_version = 2, project_id = 'foo', recipes_path = 'path/to/recipes', ), roll_candidate = True, )
def _repo_setup(self, repo_deps): # In order to avoid a topsort, we require that repo names are in # alphebetical dependency order -- i.e. later names depend on earlier # ones. repos = {} for k in sorted(repo_deps): repos[k] = self._create_repo( k, package_pb2.Package( api_version=1, project_id=k, recipes_path='', deps=[ package_pb2.DepSpec( project_id=d, url=repos[d]['root'], branch='master', revision=repos[d]['revision'], ) for d in repo_deps[k] ], )) return repos
def test_updates(self, requests_get): sha_a = 'a'*40 sha_b = 'b'*40 log_json = { 'log': [ { 'commit': sha_b, 'author': {'email': '*****@*****.**'}, 'committer': {'time': 'Fri Apr 14 00:58:45 2017'}, 'message': 'message', 'tree_diff': [ { 'old_path': '/dev/null', 'new_path': 'path/to/recipes/path1/foo', }, ], }, { 'commit': 'def456', 'author': {'email': '*****@*****.**'}, 'committer': {'time': 'Fri Apr 14 00:57:45 2017'}, 'message': 'message', 'tree_diff': [ { 'old_path': '/dev/null', 'new_path': 'path8/foo', }, ], }, { 'commit': sha_a, 'author': {'email': '*****@*****.**'}, 'committer': {'time': 'Fri Apr 14 00:56:45 2017'}, 'message': 'message', 'tree_diff': [ { 'old_path': '/dev/null', 'new_path': 'path/to/recipes/path8/foo', }, { 'old_path': 'path2/foo', 'new_path': '/dev/null', }, ], }, ], } requests_get.side_effect = multi( self.j('repo/+/reva?name-status=1&format=JSON', log_json['log'][2]), self.j('repo/+/revb?name-status=1&format=JSON', log_json['log'][0]), self.j('repo/+log/%s..%s?name-status=1&format=JSON' % (sha_a, sha_b), log_json), self.d('repo/+/%s/%s?format=TEXT' % (sha_a, IRC), self.proto_text), self.d('repo/+/%s/%s?format=TEXT' % ('def456', IRC), self.proto_text), self.d('repo/+/%s/%s?format=TEXT' % (sha_b, IRC), self.proto_text), ) be = fetch.GitilesBackend('dir', 'repo') self.assertEqual(sha_a, be.resolve_refspec('reva')) self.assertEqual(sha_b, be.resolve_refspec('revb')) self.assertEqual( [self.a_meta, fetch.CommitMetadata( revision = 'def456', author_email = '*****@*****.**', commit_timestamp = 1492131465, message_lines = ('message',), spec = package_pb2.Package( api_version = 2, project_id = 'foo', recipes_path = 'path/to/recipes', ), roll_candidate = False, ), fetch.CommitMetadata( revision = sha_b, author_email = '*****@*****.**', commit_timestamp = 1492131525, message_lines = ('message',), spec = package_pb2.Package( api_version = 2, project_id = 'foo', recipes_path = 'path/to/recipes', ), roll_candidate = True, )], be.updates(sha_a, sha_b)) self.assertMultiDone(requests_get)
def setUp(self): autoroll_options = { 'trivial': { 'tbr_emails': ['*****@*****.**', '*****@*****.**'], 'automatic_commit': True, }, 'nontrivial': { 'extra_reviewer_emails': ['*****@*****.**', '*****@*****.**'], 'automatic_commit_dry_run': True, }, 'disable_reason': 'a really good one', } dep1 = { 'url': 'https://dep1.example.com', 'branch': 'master', 'revision': 'a' * 40, 'path_override': 'sub/path', 'repo_type': 'GITILES', } self.raw_v2 = json.dumps( { 'api_version': 2, 'project_id': 'test', 'canonical_repo_url': 'https://canonical.example.com', 'recipes_path': 'foo/bar', 'deps': { 'dep1': dep1, }, 'autoroll_recipe_options': autoroll_options, }, indent=2, sort_keys=True).replace(' \n', '\n') + '\n' self.parsed = package_pb2.Package( api_version=2, project_id='test', canonical_repo_url='https://canonical.example.com', recipes_path='foo/bar', deps={ 'dep1': package_pb2.DepSpec( url='https://dep1.example.com', branch='master', revision='a' * 40, path_override='sub/path', repo_type=package_pb2.DepSpec.GITILES, ), }, autoroll_recipe_options=package_pb2.AutorollRecipeOptions( trivial=package_pb2.AutorollRecipeOptions.TrivialOptions( tbr_emails=['*****@*****.**', '*****@*****.**'], automatic_commit=True, ), nontrivial=package_pb2.AutorollRecipeOptions.NontrivialOptions( extra_reviewer_emails=[ '*****@*****.**', '*****@*****.**' ], automatic_commit_dry_run=True, ), disable_reason='a really good one', ), )