diff options
author | James E. Blair <jeblair@redhat.com> | 2017-10-30 14:04:48 -0700 |
---|---|---|
committer | James E. Blair <jeblair@redhat.com> | 2017-10-30 15:00:11 -0700 |
commit | edff2c26c2b411316b0cf32bc635277f3ce811ca (patch) | |
tree | 97c667fb963f862923b3b64e26a7fc5402d2b59b | |
parent | c317fba760f9873792d2427a8d20da0ca327bffb (diff) | |
download | zuul-edff2c26c2b411316b0cf32bc635277f3ce811ca.tar.gz |
Add support for override-checkout, deprecate override-branch
We want to support jobs specifying that they check out a tag
rather than merely a branch. This accidentally worked in Zuul v2
with zuul-cloner, and some jobs have come to rely on the behavior.
There's no reason not to support it, so let's do so.
However, for clarity, change the name of the option to
"override-checkout". This is intended to be intuitive (anything
you can tell git to 'checkout' you can put here), while avoiding
the suggestion that only branches or tags may be checked out.
The old form, "override-branch" is deprecated and will be removed.
Change-Id: Icc2907e72596626e96d2dc9f6ab1c3026f4085ab
-rw-r--r-- | doc/source/user/config.rst | 23 | ||||
-rw-r--r-- | tests/fixtures/layouts/repo-checkout-no-timer-override.yaml | 2 | ||||
-rw-r--r-- | tests/fixtures/layouts/repo-checkout-no-timer.yaml | 2 | ||||
-rw-r--r-- | tests/fixtures/layouts/repo-checkout-six-project.yaml | 2 | ||||
-rw-r--r-- | tests/fixtures/layouts/repo-checkout-tag.yaml | 36 | ||||
-rw-r--r-- | tests/fixtures/layouts/repo-checkout-timer-override.yaml | 2 | ||||
-rwxr-xr-x | tests/unit/test_executor.py | 26 | ||||
-rw-r--r-- | zuul/configloader.py | 11 | ||||
-rw-r--r-- | zuul/executor/client.py | 8 | ||||
-rw-r--r-- | zuul/executor/server.py | 30 | ||||
-rw-r--r-- | zuul/merger/merger.py | 4 | ||||
-rw-r--r-- | zuul/model.py | 5 |
12 files changed, 121 insertions, 30 deletions
diff --git a/doc/source/user/config.rst b/doc/source/user/config.rst index 001993288..fa874a9df 100644 --- a/doc/source/user/config.rst +++ b/doc/source/user/config.rst @@ -744,7 +744,7 @@ Here is an example of two job definitions: If a job has an empty or no nodeset definition, it will still run and may be able to perform actions on the Zuul executor. - .. attr:: override-branch + .. attr:: override-checkout When Zuul runs jobs for a proposed change, it normally checks out the branch associated with that change on every project @@ -752,13 +752,13 @@ Here is an example of two job definitions: branch tip or tag), then that ref is normally checked out. This attribute is used to override that behavior and indicate that this job should, regardless of the branch for the queue item, - use the indicated branch instead. This can be used, for - example, to run a previous version of the software (from a - stable maintenance branch) under test even if the change being - tested applies to a different branch (this is only likely to be - useful if there is some cross-branch interaction with some + use the indicated ref (i.e., branch or tag) instead. This can + be used, for example, to run a previous version of the software + (from a stable maintenance branch) under test even if the change + being tested applies to a different branch (this is only likely + to be useful if there is some cross-branch interaction with some component of the system being tested). See also the - project-specific :attr:`job.required-projects.override-branch` + project-specific :attr:`job.required-projects.override-checkout` attribute to apply this behavior to a subset of a job's projects. @@ -915,7 +915,7 @@ Here is an example of two job definitions: The name of the required project. - .. attr:: override-branch + .. attr:: override-checkout When Zuul runs jobs for a proposed change, it normally checks out the branch associated with that change on every project @@ -923,9 +923,10 @@ Here is an example of two job definitions: branch tip or tag), then that ref is normally checked out. This attribute is used to override that behavior and indicate that this job should, regardless of the branch for the queue - item, use the indicated branch instead, for only this - project. See also the :attr:`job.override-branch` attribute - to apply the same behavior to all projects in a job. + item, use the indicated ref (i.e., branch or tag) instead, + for only this project. See also the + :attr:`job.override-checkout` attribute to apply the same + behavior to all projects in a job. .. attr:: vars diff --git a/tests/fixtures/layouts/repo-checkout-no-timer-override.yaml b/tests/fixtures/layouts/repo-checkout-no-timer-override.yaml index ca4929205..89d2b93e2 100644 --- a/tests/fixtures/layouts/repo-checkout-no-timer-override.yaml +++ b/tests/fixtures/layouts/repo-checkout-no-timer-override.yaml @@ -15,7 +15,7 @@ - job: name: integration branches: master - override-branch: stable/havana + override-checkout: stable/havana required-projects: - org/project1 run: playbooks/integration.yaml diff --git a/tests/fixtures/layouts/repo-checkout-no-timer.yaml b/tests/fixtures/layouts/repo-checkout-no-timer.yaml index 6b8880116..037489739 100644 --- a/tests/fixtures/layouts/repo-checkout-no-timer.yaml +++ b/tests/fixtures/layouts/repo-checkout-no-timer.yaml @@ -14,7 +14,7 @@ - job: name: integration - override-branch: stable/havana + override-checkout: stable/havana required-projects: - org/project1 run: playbooks/integration.yaml diff --git a/tests/fixtures/layouts/repo-checkout-six-project.yaml b/tests/fixtures/layouts/repo-checkout-six-project.yaml index 607961269..48786654b 100644 --- a/tests/fixtures/layouts/repo-checkout-six-project.yaml +++ b/tests/fixtures/layouts/repo-checkout-six-project.yaml @@ -44,7 +44,7 @@ - org/project2 - org/project3 - name: org/project4 - override-branch: master + override-checkout: master - org/project5 - org/project6 run: playbooks/integration.yaml diff --git a/tests/fixtures/layouts/repo-checkout-tag.yaml b/tests/fixtures/layouts/repo-checkout-tag.yaml new file mode 100644 index 000000000..3f1af1ceb --- /dev/null +++ b/tests/fixtures/layouts/repo-checkout-tag.yaml @@ -0,0 +1,36 @@ +- pipeline: + name: check + manager: independent + trigger: + gerrit: + - event: patchset-created + success: + gerrit: + Verified: 1 + failure: + gerrit: + Verified: -1 + +- job: + name: base + parent: null + +- job: + name: integration + required-projects: + - org/project1 + - name: org/project2 + override-checkout: test-tag + run: playbooks/integration.yaml + +- project: + name: org/project1 + check: + jobs: + - integration + +- project: + name: org/project2 + check: + jobs: + - integration diff --git a/tests/fixtures/layouts/repo-checkout-timer-override.yaml b/tests/fixtures/layouts/repo-checkout-timer-override.yaml index af5bd3c45..4aacfee53 100644 --- a/tests/fixtures/layouts/repo-checkout-timer-override.yaml +++ b/tests/fixtures/layouts/repo-checkout-timer-override.yaml @@ -13,7 +13,7 @@ - job: name: integration branches: master - override-branch: stable/havana + override-checkout: stable/havana required-projects: - org/project1 run: playbooks/integration.yaml diff --git a/tests/unit/test_executor.py b/tests/unit/test_executor.py index f051ec446..5d276636d 100755 --- a/tests/unit/test_executor.py +++ b/tests/unit/test_executor.py @@ -378,6 +378,32 @@ class TestExecutorRepos(ZuulTestCase): self.assertBuildStates(states, projects) + @simple_layout('layouts/repo-checkout-tag.yaml') + def test_tag_checkout(self): + self.executor_server.hold_jobs_in_build = True + p1 = "review.example.com/org/project1" + p2 = "review.example.com/org/project2" + projects = [p1, p2] + upstream = self.getUpstreamRepos(projects) + + self.create_branch('org/project2', 'stable/havana') + files = {'README': 'tagged readme'} + self.addCommitToRepo('org/project2', 'tagged commit', + files, branch='stable/havana', tag='test-tag') + + A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A') + self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1)) + self.waitUntilSettled() + + states = [ + {p1: dict(present=[A], branch='master'), + p2: dict(commit=str(upstream[p2].commit('test-tag')), + absent=[A]), + }, + ] + + self.assertBuildStates(states, projects) + class TestAnsibleJob(ZuulTestCase): tenant_config_file = 'config/ansible/main.yaml' diff --git a/zuul/configloader.py b/zuul/configloader.py index 6737c7b2d..99f10f6b3 100644 --- a/zuul/configloader.py +++ b/zuul/configloader.py @@ -417,7 +417,8 @@ class JobParser(object): role = vs.Any(zuul_role, galaxy_role) job_project = {vs.Required('name'): str, - 'override-branch': str} + 'override-branch': str, + 'override-checkout': str} secret = {vs.Required('name'): str, vs.Required('secret'): str} @@ -452,6 +453,7 @@ class JobParser(object): 'dependencies': to_list(str), 'allowed-projects': to_list(str), 'override-branch': str, + 'override-checkout': str, 'description': str, 'post-review': bool} @@ -474,6 +476,7 @@ class JobParser(object): 'failure-url', 'success-url', 'override-branch', + 'override-checkout', ] @staticmethod @@ -633,14 +636,18 @@ class JobParser(object): if isinstance(project, dict): project_name = project['name'] project_override_branch = project.get('override-branch') + project_override_checkout = project.get( + 'override-checkout') else: project_name = project project_override_branch = None + project_override_checkout = None (trusted, project) = tenant.getProject(project_name) if project is None: raise Exception("Unknown project %s" % (project_name,)) job_project = model.JobProject(project_name, - project_override_branch) + project_override_branch, + project_override_checkout) new_projects[project_name] = job_project job.required_projects = new_projects diff --git a/zuul/executor/client.py b/zuul/executor/client.py index cfd652a38..fba472f56 100644 --- a/zuul/executor/client.py +++ b/zuul/executor/client.py @@ -196,6 +196,7 @@ class ExecutorClient(object): else: params['branch'] = None params['override_branch'] = job.override_branch + params['override_checkout'] = job.override_checkout params['repo_state'] = item.current_build_set.repo_state if job.name != 'noop': @@ -216,7 +217,8 @@ class ExecutorClient(object): projects = set() required_projects = set() - def make_project_dict(project, override_branch=None): + def make_project_dict(project, override_branch=None, + override_checkout=None): project_config = item.layout.project_configs.get( project.canonical_name, None) if project_config: @@ -228,6 +230,7 @@ class ExecutorClient(object): name=project.name, canonical_name=project.canonical_name, override_branch=override_branch, + override_checkout=override_checkout, default_branch=project_default_branch) if job.required_projects: @@ -239,7 +242,8 @@ class ExecutorClient(object): (job_project.project_name,)) params['projects'].append( make_project_dict(project, - job_project.override_branch)) + job_project.override_branch, + job_project.override_checkout)) projects.add(project) required_projects.add(project) for change in dependent_changes: diff --git a/zuul/executor/server.py b/zuul/executor/server.py index d72d1eec3..7bcd71c67 100644 --- a/zuul/executor/server.py +++ b/zuul/executor/server.py @@ -681,7 +681,9 @@ class AnsibleJob(object): ref, args['branch'], args['override_branch'], + args['override_checkout'], project['override_branch'], + project['override_checkout'], project['default_branch']) # Delete the origin remote from each repo we set up since @@ -757,22 +759,32 @@ class AnsibleJob(object): return True def checkoutBranch(self, repo, project_name, ref, zuul_branch, - job_branch, project_override_branch, + job_override_branch, job_override_checkout, + project_override_branch, project_override_checkout, project_default_branch): branches = repo.getBranches() + refs = [r.name for r in repo.getRefs()] if project_override_branch in branches: self.log.info("Checking out %s project override branch %s", project_name, project_override_branch) - repo.checkoutLocalBranch(project_override_branch) - elif job_branch in branches: - self.log.info("Checking out %s job branch %s", - project_name, job_branch) - repo.checkoutLocalBranch(job_branch) + repo.checkout(project_override_branch) + if project_override_checkout in refs: + self.log.info("Checking out %s project override ref %s", + project_name, project_override_checkout) + repo.checkout(project_override_checkout) + elif job_override_branch in branches: + self.log.info("Checking out %s job override branch %s", + project_name, job_override_branch) + repo.checkout(job_override_branch) + elif job_override_checkout in refs: + self.log.info("Checking out %s job override ref %s", + project_name, job_override_checkout) + repo.checkout(job_override_checkout) elif ref and ref.startswith('refs/heads/'): b = ref[len('refs/heads/'):] self.log.info("Checking out %s branch ref %s", project_name, b) - repo.checkoutLocalBranch(b) + repo.checkout(b) elif ref and ref.startswith('refs/tags/'): t = ref[len('refs/tags/'):] self.log.info("Checking out %s tag ref %s", @@ -781,11 +793,11 @@ class AnsibleJob(object): elif zuul_branch and zuul_branch in branches: self.log.info("Checking out %s zuul branch %s", project_name, zuul_branch) - repo.checkoutLocalBranch(zuul_branch) + repo.checkout(zuul_branch) elif project_default_branch in branches: self.log.info("Checking out %s project default branch %s", project_name, project_default_branch) - repo.checkoutLocalBranch(project_default_branch) + repo.checkout(project_default_branch) else: raise ExecutorError("Project %s does not have the " "default branch %s" % diff --git a/zuul/merger/merger.py b/zuul/merger/merger.py index 035d1d007..06ec4b2b9 100644 --- a/zuul/merger/merger.py +++ b/zuul/merger/merger.py @@ -176,6 +176,8 @@ class Repo(object): return branch in origin.refs def getBranches(self): + # TODO(jeblair): deprecate with override-branch; replaced by + # getRefs(). repo = self.createRepoObject() return [x.name for x in repo.heads] @@ -386,7 +388,7 @@ class Merger(object): self.log.info("Checking out %s/%s branch %s", connection_name, project_name, branch) repo = self.getRepo(connection_name, project_name) - repo.checkoutLocalBranch(branch) + repo.checkout(branch) def _saveRepoState(self, connection_name, project_name, repo, repo_state, recent): diff --git a/zuul/model.py b/zuul/model.py index cf63f6400..b027c534f 100644 --- a/zuul/model.py +++ b/zuul/model.py @@ -845,6 +845,7 @@ class Job(object): required_projects={}, allowed_projects=None, override_branch=None, + override_checkout=None, post_review=None, ) @@ -1073,9 +1074,11 @@ class Job(object): class JobProject(object): """ A reference to a project from a job. """ - def __init__(self, project_name, override_branch=None): + def __init__(self, project_name, override_branch=None, + override_checkout=None): self.project_name = project_name self.override_branch = override_branch + self.override_checkout = override_checkout class JobList(object): |