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
This commit is contained in:
parent
c317fba760
commit
edff2c26c2
|
@ -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
|
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.
|
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
|
When Zuul runs jobs for a proposed change, it normally checks
|
||||||
out the branch associated with that change on every project
|
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
|
branch tip or tag), then that ref is normally checked out. This
|
||||||
attribute is used to override that behavior and indicate that
|
attribute is used to override that behavior and indicate that
|
||||||
this job should, regardless of the branch for the queue item,
|
this job should, regardless of the branch for the queue item,
|
||||||
use the indicated branch instead. This can be used, for
|
use the indicated ref (i.e., branch or tag) instead. This can
|
||||||
example, to run a previous version of the software (from a
|
be used, for example, to run a previous version of the software
|
||||||
stable maintenance branch) under test even if the change being
|
(from a stable maintenance branch) under test even if the change
|
||||||
tested applies to a different branch (this is only likely to be
|
being tested applies to a different branch (this is only likely
|
||||||
useful if there is some cross-branch interaction with some
|
to be useful if there is some cross-branch interaction with some
|
||||||
component of the system being tested). See also the
|
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
|
attribute to apply this behavior to a subset of a job's
|
||||||
projects.
|
projects.
|
||||||
|
|
||||||
|
@ -915,7 +915,7 @@ Here is an example of two job definitions:
|
||||||
|
|
||||||
The name of the required project.
|
The name of the required project.
|
||||||
|
|
||||||
.. attr:: override-branch
|
.. attr:: override-checkout
|
||||||
|
|
||||||
When Zuul runs jobs for a proposed change, it normally checks
|
When Zuul runs jobs for a proposed change, it normally checks
|
||||||
out the branch associated with that change on every project
|
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.
|
branch tip or tag), then that ref is normally checked out.
|
||||||
This attribute is used to override that behavior and indicate
|
This attribute is used to override that behavior and indicate
|
||||||
that this job should, regardless of the branch for the queue
|
that this job should, regardless of the branch for the queue
|
||||||
item, use the indicated branch instead, for only this
|
item, use the indicated ref (i.e., branch or tag) instead,
|
||||||
project. See also the :attr:`job.override-branch` attribute
|
for only this project. See also the
|
||||||
to apply the same behavior to all projects in a job.
|
:attr:`job.override-checkout` attribute to apply the same
|
||||||
|
behavior to all projects in a job.
|
||||||
|
|
||||||
.. attr:: vars
|
.. attr:: vars
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
- job:
|
- job:
|
||||||
name: integration
|
name: integration
|
||||||
branches: master
|
branches: master
|
||||||
override-branch: stable/havana
|
override-checkout: stable/havana
|
||||||
required-projects:
|
required-projects:
|
||||||
- org/project1
|
- org/project1
|
||||||
run: playbooks/integration.yaml
|
run: playbooks/integration.yaml
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
|
|
||||||
- job:
|
- job:
|
||||||
name: integration
|
name: integration
|
||||||
override-branch: stable/havana
|
override-checkout: stable/havana
|
||||||
required-projects:
|
required-projects:
|
||||||
- org/project1
|
- org/project1
|
||||||
run: playbooks/integration.yaml
|
run: playbooks/integration.yaml
|
||||||
|
|
|
@ -44,7 +44,7 @@
|
||||||
- org/project2
|
- org/project2
|
||||||
- org/project3
|
- org/project3
|
||||||
- name: org/project4
|
- name: org/project4
|
||||||
override-branch: master
|
override-checkout: master
|
||||||
- org/project5
|
- org/project5
|
||||||
- org/project6
|
- org/project6
|
||||||
run: playbooks/integration.yaml
|
run: playbooks/integration.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
|
|
@ -13,7 +13,7 @@
|
||||||
- job:
|
- job:
|
||||||
name: integration
|
name: integration
|
||||||
branches: master
|
branches: master
|
||||||
override-branch: stable/havana
|
override-checkout: stable/havana
|
||||||
required-projects:
|
required-projects:
|
||||||
- org/project1
|
- org/project1
|
||||||
run: playbooks/integration.yaml
|
run: playbooks/integration.yaml
|
||||||
|
|
|
@ -378,6 +378,32 @@ class TestExecutorRepos(ZuulTestCase):
|
||||||
|
|
||||||
self.assertBuildStates(states, projects)
|
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):
|
class TestAnsibleJob(ZuulTestCase):
|
||||||
tenant_config_file = 'config/ansible/main.yaml'
|
tenant_config_file = 'config/ansible/main.yaml'
|
||||||
|
|
|
@ -417,7 +417,8 @@ class JobParser(object):
|
||||||
role = vs.Any(zuul_role, galaxy_role)
|
role = vs.Any(zuul_role, galaxy_role)
|
||||||
|
|
||||||
job_project = {vs.Required('name'): str,
|
job_project = {vs.Required('name'): str,
|
||||||
'override-branch': str}
|
'override-branch': str,
|
||||||
|
'override-checkout': str}
|
||||||
|
|
||||||
secret = {vs.Required('name'): str,
|
secret = {vs.Required('name'): str,
|
||||||
vs.Required('secret'): str}
|
vs.Required('secret'): str}
|
||||||
|
@ -452,6 +453,7 @@ class JobParser(object):
|
||||||
'dependencies': to_list(str),
|
'dependencies': to_list(str),
|
||||||
'allowed-projects': to_list(str),
|
'allowed-projects': to_list(str),
|
||||||
'override-branch': str,
|
'override-branch': str,
|
||||||
|
'override-checkout': str,
|
||||||
'description': str,
|
'description': str,
|
||||||
'post-review': bool}
|
'post-review': bool}
|
||||||
|
|
||||||
|
@ -474,6 +476,7 @@ class JobParser(object):
|
||||||
'failure-url',
|
'failure-url',
|
||||||
'success-url',
|
'success-url',
|
||||||
'override-branch',
|
'override-branch',
|
||||||
|
'override-checkout',
|
||||||
]
|
]
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
@ -633,14 +636,18 @@ class JobParser(object):
|
||||||
if isinstance(project, dict):
|
if isinstance(project, dict):
|
||||||
project_name = project['name']
|
project_name = project['name']
|
||||||
project_override_branch = project.get('override-branch')
|
project_override_branch = project.get('override-branch')
|
||||||
|
project_override_checkout = project.get(
|
||||||
|
'override-checkout')
|
||||||
else:
|
else:
|
||||||
project_name = project
|
project_name = project
|
||||||
project_override_branch = None
|
project_override_branch = None
|
||||||
|
project_override_checkout = None
|
||||||
(trusted, project) = tenant.getProject(project_name)
|
(trusted, project) = tenant.getProject(project_name)
|
||||||
if project is None:
|
if project is None:
|
||||||
raise Exception("Unknown project %s" % (project_name,))
|
raise Exception("Unknown project %s" % (project_name,))
|
||||||
job_project = model.JobProject(project_name,
|
job_project = model.JobProject(project_name,
|
||||||
project_override_branch)
|
project_override_branch,
|
||||||
|
project_override_checkout)
|
||||||
new_projects[project_name] = job_project
|
new_projects[project_name] = job_project
|
||||||
job.required_projects = new_projects
|
job.required_projects = new_projects
|
||||||
|
|
||||||
|
|
|
@ -196,6 +196,7 @@ class ExecutorClient(object):
|
||||||
else:
|
else:
|
||||||
params['branch'] = None
|
params['branch'] = None
|
||||||
params['override_branch'] = job.override_branch
|
params['override_branch'] = job.override_branch
|
||||||
|
params['override_checkout'] = job.override_checkout
|
||||||
params['repo_state'] = item.current_build_set.repo_state
|
params['repo_state'] = item.current_build_set.repo_state
|
||||||
|
|
||||||
if job.name != 'noop':
|
if job.name != 'noop':
|
||||||
|
@ -216,7 +217,8 @@ class ExecutorClient(object):
|
||||||
projects = set()
|
projects = set()
|
||||||
required_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_config = item.layout.project_configs.get(
|
||||||
project.canonical_name, None)
|
project.canonical_name, None)
|
||||||
if project_config:
|
if project_config:
|
||||||
|
@ -228,6 +230,7 @@ class ExecutorClient(object):
|
||||||
name=project.name,
|
name=project.name,
|
||||||
canonical_name=project.canonical_name,
|
canonical_name=project.canonical_name,
|
||||||
override_branch=override_branch,
|
override_branch=override_branch,
|
||||||
|
override_checkout=override_checkout,
|
||||||
default_branch=project_default_branch)
|
default_branch=project_default_branch)
|
||||||
|
|
||||||
if job.required_projects:
|
if job.required_projects:
|
||||||
|
@ -239,7 +242,8 @@ class ExecutorClient(object):
|
||||||
(job_project.project_name,))
|
(job_project.project_name,))
|
||||||
params['projects'].append(
|
params['projects'].append(
|
||||||
make_project_dict(project,
|
make_project_dict(project,
|
||||||
job_project.override_branch))
|
job_project.override_branch,
|
||||||
|
job_project.override_checkout))
|
||||||
projects.add(project)
|
projects.add(project)
|
||||||
required_projects.add(project)
|
required_projects.add(project)
|
||||||
for change in dependent_changes:
|
for change in dependent_changes:
|
||||||
|
|
|
@ -681,7 +681,9 @@ class AnsibleJob(object):
|
||||||
ref,
|
ref,
|
||||||
args['branch'],
|
args['branch'],
|
||||||
args['override_branch'],
|
args['override_branch'],
|
||||||
|
args['override_checkout'],
|
||||||
project['override_branch'],
|
project['override_branch'],
|
||||||
|
project['override_checkout'],
|
||||||
project['default_branch'])
|
project['default_branch'])
|
||||||
|
|
||||||
# Delete the origin remote from each repo we set up since
|
# Delete the origin remote from each repo we set up since
|
||||||
|
@ -757,22 +759,32 @@ class AnsibleJob(object):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def checkoutBranch(self, repo, project_name, ref, zuul_branch,
|
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):
|
project_default_branch):
|
||||||
branches = repo.getBranches()
|
branches = repo.getBranches()
|
||||||
|
refs = [r.name for r in repo.getRefs()]
|
||||||
if project_override_branch in branches:
|
if project_override_branch in branches:
|
||||||
self.log.info("Checking out %s project override branch %s",
|
self.log.info("Checking out %s project override branch %s",
|
||||||
project_name, project_override_branch)
|
project_name, project_override_branch)
|
||||||
repo.checkoutLocalBranch(project_override_branch)
|
repo.checkout(project_override_branch)
|
||||||
elif job_branch in branches:
|
if project_override_checkout in refs:
|
||||||
self.log.info("Checking out %s job branch %s",
|
self.log.info("Checking out %s project override ref %s",
|
||||||
project_name, job_branch)
|
project_name, project_override_checkout)
|
||||||
repo.checkoutLocalBranch(job_branch)
|
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/'):
|
elif ref and ref.startswith('refs/heads/'):
|
||||||
b = ref[len('refs/heads/'):]
|
b = ref[len('refs/heads/'):]
|
||||||
self.log.info("Checking out %s branch ref %s",
|
self.log.info("Checking out %s branch ref %s",
|
||||||
project_name, b)
|
project_name, b)
|
||||||
repo.checkoutLocalBranch(b)
|
repo.checkout(b)
|
||||||
elif ref and ref.startswith('refs/tags/'):
|
elif ref and ref.startswith('refs/tags/'):
|
||||||
t = ref[len('refs/tags/'):]
|
t = ref[len('refs/tags/'):]
|
||||||
self.log.info("Checking out %s tag ref %s",
|
self.log.info("Checking out %s tag ref %s",
|
||||||
|
@ -781,11 +793,11 @@ class AnsibleJob(object):
|
||||||
elif zuul_branch and zuul_branch in branches:
|
elif zuul_branch and zuul_branch in branches:
|
||||||
self.log.info("Checking out %s zuul branch %s",
|
self.log.info("Checking out %s zuul branch %s",
|
||||||
project_name, zuul_branch)
|
project_name, zuul_branch)
|
||||||
repo.checkoutLocalBranch(zuul_branch)
|
repo.checkout(zuul_branch)
|
||||||
elif project_default_branch in branches:
|
elif project_default_branch in branches:
|
||||||
self.log.info("Checking out %s project default branch %s",
|
self.log.info("Checking out %s project default branch %s",
|
||||||
project_name, project_default_branch)
|
project_name, project_default_branch)
|
||||||
repo.checkoutLocalBranch(project_default_branch)
|
repo.checkout(project_default_branch)
|
||||||
else:
|
else:
|
||||||
raise ExecutorError("Project %s does not have the "
|
raise ExecutorError("Project %s does not have the "
|
||||||
"default branch %s" %
|
"default branch %s" %
|
||||||
|
|
|
@ -176,6 +176,8 @@ class Repo(object):
|
||||||
return branch in origin.refs
|
return branch in origin.refs
|
||||||
|
|
||||||
def getBranches(self):
|
def getBranches(self):
|
||||||
|
# TODO(jeblair): deprecate with override-branch; replaced by
|
||||||
|
# getRefs().
|
||||||
repo = self.createRepoObject()
|
repo = self.createRepoObject()
|
||||||
return [x.name for x in repo.heads]
|
return [x.name for x in repo.heads]
|
||||||
|
|
||||||
|
@ -386,7 +388,7 @@ class Merger(object):
|
||||||
self.log.info("Checking out %s/%s branch %s",
|
self.log.info("Checking out %s/%s branch %s",
|
||||||
connection_name, project_name, branch)
|
connection_name, project_name, branch)
|
||||||
repo = self.getRepo(connection_name, project_name)
|
repo = self.getRepo(connection_name, project_name)
|
||||||
repo.checkoutLocalBranch(branch)
|
repo.checkout(branch)
|
||||||
|
|
||||||
def _saveRepoState(self, connection_name, project_name, repo,
|
def _saveRepoState(self, connection_name, project_name, repo,
|
||||||
repo_state, recent):
|
repo_state, recent):
|
||||||
|
|
|
@ -845,6 +845,7 @@ class Job(object):
|
||||||
required_projects={},
|
required_projects={},
|
||||||
allowed_projects=None,
|
allowed_projects=None,
|
||||||
override_branch=None,
|
override_branch=None,
|
||||||
|
override_checkout=None,
|
||||||
post_review=None,
|
post_review=None,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -1073,9 +1074,11 @@ class Job(object):
|
||||||
class JobProject(object):
|
class JobProject(object):
|
||||||
""" A reference to a project from a job. """
|
""" 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.project_name = project_name
|
||||||
self.override_branch = override_branch
|
self.override_branch = override_branch
|
||||||
|
self.override_checkout = override_checkout
|
||||||
|
|
||||||
|
|
||||||
class JobList(object):
|
class JobList(object):
|
||||||
|
|
Loading…
Reference in New Issue