Merge "Cloner: use zuul_url always when project set"
This commit is contained in:
commit
0ad7e6434b
|
@ -262,6 +262,25 @@ class FakeChange(object):
|
|||
"comment": "This is a comment"}
|
||||
return event
|
||||
|
||||
def getRefUpdatedEvent(self):
|
||||
path = os.path.join(self.upstream_root, self.project)
|
||||
repo = git.Repo(path)
|
||||
oldrev = repo.heads[self.branch].commit.hexsha
|
||||
|
||||
event = {
|
||||
"type": "ref-updated",
|
||||
"submitter": {
|
||||
"name": "User Name",
|
||||
},
|
||||
"refUpdate": {
|
||||
"oldRev": oldrev,
|
||||
"newRev": self.patchsets[-1]['revision'],
|
||||
"refName": self.branch,
|
||||
"project": self.project,
|
||||
}
|
||||
}
|
||||
return event
|
||||
|
||||
def addApproval(self, category, value, username='reviewer_john',
|
||||
granted_on=None, message=''):
|
||||
if not granted_on:
|
||||
|
|
|
@ -30,6 +30,13 @@ pipelines:
|
|||
gerrit:
|
||||
verified: -2
|
||||
|
||||
- name: post
|
||||
manager: IndependentPipelineManager
|
||||
trigger:
|
||||
gerrit:
|
||||
- event: ref-updated
|
||||
ref: ^(?!refs/).*$
|
||||
|
||||
projects:
|
||||
- name: org/project
|
||||
check:
|
||||
|
@ -42,6 +49,8 @@ projects:
|
|||
- integration
|
||||
gate:
|
||||
- integration
|
||||
post:
|
||||
- postjob
|
||||
|
||||
- name: org/project2
|
||||
check:
|
||||
|
|
|
@ -108,11 +108,34 @@ class TestCloner(ZuulTestCase):
|
|||
'be correct' % (project, number))
|
||||
|
||||
work = self.getWorkspaceRepos(projects)
|
||||
upstream_repo_path = os.path.join(self.upstream_root, 'org/project1')
|
||||
self.assertEquals(
|
||||
# project1 is the zuul_project so the origin should be set to the
|
||||
# zuul_url since that is the most up to date.
|
||||
cache_repo_path = os.path.join(cache_root, 'org/project1')
|
||||
self.assertNotEqual(
|
||||
work['org/project1'].remotes.origin.url,
|
||||
cache_repo_path,
|
||||
'workspace repo origin should not be the cache'
|
||||
)
|
||||
zuul_url_repo_path = os.path.join(self.git_root, 'org/project1')
|
||||
self.assertEqual(
|
||||
work['org/project1'].remotes.origin.url,
|
||||
zuul_url_repo_path,
|
||||
'workspace repo origin should be the zuul url'
|
||||
)
|
||||
|
||||
# project2 is not the zuul_project so the origin should be set
|
||||
# to upstream since that is the best we can do
|
||||
cache_repo_path = os.path.join(cache_root, 'org/project2')
|
||||
self.assertNotEqual(
|
||||
work['org/project2'].remotes.origin.url,
|
||||
cache_repo_path,
|
||||
'workspace repo origin should not be the cache'
|
||||
)
|
||||
upstream_repo_path = os.path.join(self.upstream_root, 'org/project2')
|
||||
self.assertEqual(
|
||||
work['org/project2'].remotes.origin.url,
|
||||
upstream_repo_path,
|
||||
'workspace repo origin should be upstream, not cache'
|
||||
'workspace repo origin should be the upstream url'
|
||||
)
|
||||
|
||||
self.worker.hold_jobs_in_build = False
|
||||
|
@ -656,55 +679,76 @@ class TestCloner(ZuulTestCase):
|
|||
self.waitUntilSettled()
|
||||
|
||||
def test_post_checkout(self):
|
||||
project = "org/project"
|
||||
path = os.path.join(self.upstream_root, project)
|
||||
repo = git.Repo(path)
|
||||
repo.head.reference = repo.heads['master']
|
||||
commits = []
|
||||
for i in range(0, 3):
|
||||
commits.append(self.create_commit(project))
|
||||
newRev = commits[1]
|
||||
self.worker.hold_jobs_in_build = True
|
||||
project = "org/project1"
|
||||
|
||||
A = self.fake_gerrit.addFakeChange(project, 'master', 'A')
|
||||
event = A.getRefUpdatedEvent()
|
||||
A.setMerged()
|
||||
self.fake_gerrit.addEvent(event)
|
||||
self.waitUntilSettled()
|
||||
|
||||
build = self.builds[0]
|
||||
state = {'org/project1': build.parameters['ZUUL_COMMIT']}
|
||||
|
||||
build.release()
|
||||
self.waitUntilSettled()
|
||||
|
||||
cloner = zuul.lib.cloner.Cloner(
|
||||
git_base_url=self.upstream_root,
|
||||
projects=[project],
|
||||
workspace=self.workspace_root,
|
||||
zuul_project='org/project',
|
||||
zuul_branch=None,
|
||||
zuul_ref='master',
|
||||
zuul_project=build.parameters.get('ZUUL_PROJECT', None),
|
||||
zuul_branch=build.parameters.get('ZUUL_BRANCH', None),
|
||||
zuul_ref=build.parameters.get('ZUUL_REF', None),
|
||||
zuul_newrev=build.parameters.get('ZUUL_NEWREV', None),
|
||||
zuul_url=self.git_root,
|
||||
zuul_newrev=newRev,
|
||||
)
|
||||
cloner.execute()
|
||||
repos = self.getWorkspaceRepos([project])
|
||||
cloned_sha = repos[project].rev_parse('HEAD').hexsha
|
||||
self.assertEqual(newRev, cloned_sha)
|
||||
work = self.getWorkspaceRepos([project])
|
||||
self.assertEquals(state[project],
|
||||
str(work[project].commit('HEAD')),
|
||||
'Project %s commit for build %s should '
|
||||
'be correct' % (project, 0))
|
||||
shutil.rmtree(self.workspace_root)
|
||||
|
||||
def test_post_and_master_checkout(self):
|
||||
project = "org/project1"
|
||||
master_project = "org/project2"
|
||||
path = os.path.join(self.upstream_root, project)
|
||||
repo = git.Repo(path)
|
||||
repo.head.reference = repo.heads['master']
|
||||
commits = []
|
||||
for i in range(0, 3):
|
||||
commits.append(self.create_commit(project))
|
||||
newRev = commits[1]
|
||||
self.worker.hold_jobs_in_build = True
|
||||
projects = ["org/project1", "org/project2"]
|
||||
|
||||
A = self.fake_gerrit.addFakeChange(projects[0], 'master', 'A')
|
||||
event = A.getRefUpdatedEvent()
|
||||
A.setMerged()
|
||||
self.fake_gerrit.addEvent(event)
|
||||
self.waitUntilSettled()
|
||||
|
||||
build = self.builds[0]
|
||||
upstream = self.getUpstreamRepos(projects)
|
||||
state = {'org/project1':
|
||||
build.parameters['ZUUL_COMMIT'],
|
||||
'org/project2':
|
||||
str(upstream['org/project2'].commit('master')),
|
||||
}
|
||||
|
||||
build.release()
|
||||
self.waitUntilSettled()
|
||||
|
||||
cloner = zuul.lib.cloner.Cloner(
|
||||
git_base_url=self.upstream_root,
|
||||
projects=[project, master_project],
|
||||
projects=projects,
|
||||
workspace=self.workspace_root,
|
||||
zuul_project='org/project1',
|
||||
zuul_branch=None,
|
||||
zuul_ref='master',
|
||||
zuul_project=build.parameters.get('ZUUL_PROJECT', None),
|
||||
zuul_branch=build.parameters.get('ZUUL_BRANCH', None),
|
||||
zuul_ref=build.parameters.get('ZUUL_REF', None),
|
||||
zuul_newrev=build.parameters.get('ZUUL_NEWREV', None),
|
||||
zuul_url=self.git_root,
|
||||
zuul_newrev=newRev
|
||||
)
|
||||
cloner.execute()
|
||||
repos = self.getWorkspaceRepos([project, master_project])
|
||||
cloned_sha = repos[project].rev_parse('HEAD').hexsha
|
||||
self.assertEqual(newRev, cloned_sha)
|
||||
self.assertEqual(
|
||||
repos[master_project].rev_parse('HEAD').hexsha,
|
||||
repos[master_project].rev_parse('master').hexsha)
|
||||
work = self.getWorkspaceRepos(projects)
|
||||
|
||||
for project in projects:
|
||||
self.assertEquals(state[project],
|
||||
str(work[project].commit('HEAD')),
|
||||
'Project %s commit for build %s should '
|
||||
'be correct' % (project, 0))
|
||||
shutil.rmtree(self.workspace_root)
|
||||
|
|
|
@ -46,6 +46,8 @@ class Cloner(object):
|
|||
self.zuul_branch = zuul_branch or ''
|
||||
self.zuul_ref = zuul_ref or ''
|
||||
self.zuul_url = zuul_url
|
||||
self.zuul_project = zuul_project
|
||||
|
||||
self.project_branches = project_branches or {}
|
||||
self.project_revisions = {}
|
||||
|
||||
|
@ -77,7 +79,18 @@ class Cloner(object):
|
|||
def cloneUpstream(self, project, dest):
|
||||
# Check for a cached git repo first
|
||||
git_cache = '%s/%s' % (self.cache_dir, project)
|
||||
git_upstream = '%s/%s' % (self.git_url, project)
|
||||
|
||||
# Then, if we are cloning the repo for the zuul_project, then
|
||||
# set its origin to be the zuul merger, as it is guaranteed to
|
||||
# be correct and up to date even if mirrors haven't updated
|
||||
# yet. Otherwise, we can not be sure about the state of the
|
||||
# project, so our best chance to get the most current state is
|
||||
# by setting origin to the git_url.
|
||||
if (self.zuul_url and project == self.zuul_project):
|
||||
git_upstream = '%s/%s' % (self.zuul_url, project)
|
||||
else:
|
||||
git_upstream = '%s/%s' % (self.git_url, project)
|
||||
|
||||
repo_is_cloned = os.path.exists(os.path.join(dest, '.git'))
|
||||
if (self.cache_dir and
|
||||
os.path.exists(git_cache) and
|
||||
|
@ -104,23 +117,35 @@ class Cloner(object):
|
|||
|
||||
return repo
|
||||
|
||||
def fetchFromZuul(self, repo, project, ref):
|
||||
zuul_remote = '%s/%s' % (self.zuul_url, project)
|
||||
def fetchRef(self, repo, project, ref):
|
||||
# If we are fetching a zuul ref, the only place to get it is
|
||||
# from the zuul merger (and it is guaranteed to be correct).
|
||||
# Otherwise, the only way we can be certain that the ref
|
||||
# (which, since it is not a zuul ref, is a branch or tag) is
|
||||
# correct is in the case that it matches zuul_project. If
|
||||
# neither of those two conditions are met, we are most likely
|
||||
# to get the correct state from the git_url.
|
||||
if (ref.startswith('refs/zuul') or
|
||||
project == self.zuul_project):
|
||||
|
||||
remote = '%s/%s' % (self.zuul_url, project)
|
||||
else:
|
||||
remote = '%s/%s' % (self.git_url, project)
|
||||
|
||||
try:
|
||||
repo.fetchFrom(zuul_remote, ref)
|
||||
self.log.debug("Fetched ref %s from %s", ref, project)
|
||||
repo.fetchFrom(remote, ref)
|
||||
self.log.debug("Fetched ref %s from %s", ref, remote)
|
||||
return True
|
||||
except ValueError:
|
||||
self.log.debug("Project %s in Zuul does not have ref %s",
|
||||
project, ref)
|
||||
self.log.debug("Repo %s does not have ref %s",
|
||||
remote, ref)
|
||||
return False
|
||||
except GitCommandError as error:
|
||||
# Bail out if fetch fails due to infrastructure reasons
|
||||
if error.stderr.startswith('fatal: unable to access'):
|
||||
raise
|
||||
self.log.debug("Project %s in Zuul does not have ref %s",
|
||||
project, ref)
|
||||
self.log.debug("Repo %s does not have ref %s",
|
||||
remote, ref)
|
||||
return False
|
||||
|
||||
def prepareRepo(self, project, dest):
|
||||
|
@ -192,7 +217,7 @@ class Cloner(object):
|
|||
self.log.info("Attempting to check out revision %s for "
|
||||
"project %s", indicated_revision, project)
|
||||
try:
|
||||
self.fetchFromZuul(repo, project, self.zuul_ref)
|
||||
self.fetchRef(repo, project, self.zuul_ref)
|
||||
commit = repo.checkout(indicated_revision)
|
||||
except (ValueError, GitCommandError):
|
||||
raise exceptions.RevNotFound(project, indicated_revision)
|
||||
|
@ -201,10 +226,10 @@ class Cloner(object):
|
|||
# If we have a non empty zuul_ref to use, use it. Otherwise we fall
|
||||
# back to checking out the branch.
|
||||
elif ((override_zuul_ref and
|
||||
self.fetchFromZuul(repo, project, override_zuul_ref)) or
|
||||
self.fetchRef(repo, project, override_zuul_ref)) or
|
||||
(fallback_zuul_ref and
|
||||
fallback_zuul_ref != override_zuul_ref and
|
||||
self.fetchFromZuul(repo, project, fallback_zuul_ref))):
|
||||
self.fetchRef(repo, project, fallback_zuul_ref))):
|
||||
# Work around a bug in GitPython which can not parse FETCH_HEAD
|
||||
gitcmd = git.Git(dest)
|
||||
fetch_head = gitcmd.rev_parse('FETCH_HEAD')
|
||||
|
|
Loading…
Reference in New Issue