Merge "Use username from node information if available" into feature/zuulv3
diff --git a/doc/source/user/config.rst b/doc/source/user/config.rst
index fa874a9..3ea20ab 100644
--- a/doc/source/user/config.rst
+++ b/doc/source/user/config.rst
@@ -658,8 +658,17 @@
* In the case of a job variant defined within a
:ref:`project-template`, if no branch specifier appears, the
- implied branch specifier for the :ref:`project` definition which
- uses the project-template will be used.
+ implied branch containing the project-template definition is
+ used as an implied branch specifier. This means that
+ definitions of the same project-template on different branches
+ may run different jobs.
+
+ When that project-template is used by a :ref:`project`
+ definition within a :term:`untrusted-project`, the branch
+ containing that project definition is combined with the branch
+ specifier of the project-template. This means it is possible
+ for a project to use a template on one branch, but not on
+ another.
This allows for the very simple and expected workflow where if a
project defines a job on the ``master`` branch with no branch
diff --git a/tests/fixtures/config/branch-templates/git/project-config/zuul.yaml b/tests/fixtures/config/branch-templates/git/project-config/zuul.yaml
new file mode 100644
index 0000000..ce08877
--- /dev/null
+++ b/tests/fixtures/config/branch-templates/git/project-config/zuul.yaml
@@ -0,0 +1,26 @@
+- pipeline:
+ name: check
+ manager: independent
+ trigger:
+ gerrit:
+ - event: patchset-created
+ success:
+ gerrit:
+ Verified: 1
+ failure:
+ gerrit:
+ Verified: -1
+
+- job:
+ name: base
+ parent: null
+
+- project:
+ name: project-config
+ check:
+ jobs: []
+
+- project:
+ name: puppet-integration
+ check:
+ jobs: []
diff --git a/tests/fixtures/config/branch-templates/git/puppet-integration/.zuul.yaml b/tests/fixtures/config/branch-templates/git/puppet-integration/.zuul.yaml
new file mode 100644
index 0000000..dfea632
--- /dev/null
+++ b/tests/fixtures/config/branch-templates/git/puppet-integration/.zuul.yaml
@@ -0,0 +1,25 @@
+- job:
+ name: puppet-unit-base
+ run: playbooks/run-unit-tests.yaml
+
+- job:
+ name: puppet-unit-3.8
+ parent: puppet-unit-base
+ branches: ^(stable/(newton|ocata)).*$
+ vars:
+ puppet_gem_version: 3.8
+
+- job:
+ name: puppet-something
+ run: playbooks/run-unit-tests.yaml
+
+- project-template:
+ name: puppet-unit
+ check:
+ jobs:
+ - puppet-unit-3.8
+
+- project:
+ name: puppet-integration
+ templates:
+ - puppet-unit
diff --git a/tests/fixtures/config/branch-templates/git/puppet-integration/README b/tests/fixtures/config/branch-templates/git/puppet-integration/README
new file mode 100644
index 0000000..9daeafb
--- /dev/null
+++ b/tests/fixtures/config/branch-templates/git/puppet-integration/README
@@ -0,0 +1 @@
+test
diff --git a/tests/fixtures/config/branch-templates/git/puppet-integration/playbooks/run-unit-tests.yaml b/tests/fixtures/config/branch-templates/git/puppet-integration/playbooks/run-unit-tests.yaml
new file mode 100644
index 0000000..f679dce
--- /dev/null
+++ b/tests/fixtures/config/branch-templates/git/puppet-integration/playbooks/run-unit-tests.yaml
@@ -0,0 +1,2 @@
+- hosts: all
+ tasks: []
diff --git a/tests/fixtures/config/branch-templates/git/puppet-tripleo/.zuul.yaml b/tests/fixtures/config/branch-templates/git/puppet-tripleo/.zuul.yaml
new file mode 100644
index 0000000..4be8146
--- /dev/null
+++ b/tests/fixtures/config/branch-templates/git/puppet-tripleo/.zuul.yaml
@@ -0,0 +1,4 @@
+- project:
+ name: puppet-tripleo
+ templates:
+ - puppet-unit
diff --git a/tests/fixtures/config/branch-templates/git/puppet-tripleo/README b/tests/fixtures/config/branch-templates/git/puppet-tripleo/README
new file mode 100644
index 0000000..9daeafb
--- /dev/null
+++ b/tests/fixtures/config/branch-templates/git/puppet-tripleo/README
@@ -0,0 +1 @@
+test
diff --git a/tests/fixtures/config/branch-templates/main.yaml b/tests/fixtures/config/branch-templates/main.yaml
new file mode 100644
index 0000000..f7677a3
--- /dev/null
+++ b/tests/fixtures/config/branch-templates/main.yaml
@@ -0,0 +1,9 @@
+- tenant:
+ name: tenant-one
+ source:
+ gerrit:
+ config-projects:
+ - project-config
+ untrusted-projects:
+ - puppet-integration
+ - puppet-tripleo
diff --git a/tests/unit/test_v3.py b/tests/unit/test_v3.py
index c04604d..e2da808 100755
--- a/tests/unit/test_v3.py
+++ b/tests/unit/test_v3.py
@@ -157,6 +157,115 @@
self.assertIn('Unable to modify final job', A.messages[0])
+class TestBranchTemplates(ZuulTestCase):
+ tenant_config_file = 'config/branch-templates/main.yaml'
+
+ def test_template_removal_from_branch(self):
+ # Test that a template can be removed from one branch but not
+ # another.
+ # This creates a new branch with a copy of the config in master
+ self.create_branch('puppet-integration', 'stable/newton')
+ self.create_branch('puppet-integration', 'stable/ocata')
+ self.create_branch('puppet-tripleo', 'stable/newton')
+ self.create_branch('puppet-tripleo', 'stable/ocata')
+ self.fake_gerrit.addEvent(
+ self.fake_gerrit.getFakeBranchCreatedEvent(
+ 'puppet-integration', 'stable/newton'))
+ self.fake_gerrit.addEvent(
+ self.fake_gerrit.getFakeBranchCreatedEvent(
+ 'puppet-integration', 'stable/ocata'))
+ self.fake_gerrit.addEvent(
+ self.fake_gerrit.getFakeBranchCreatedEvent(
+ 'puppet-tripleo', 'stable/newton'))
+ self.fake_gerrit.addEvent(
+ self.fake_gerrit.getFakeBranchCreatedEvent(
+ 'puppet-tripleo', 'stable/ocata'))
+ self.waitUntilSettled()
+
+ in_repo_conf = textwrap.dedent(
+ """
+ - project:
+ name: puppet-tripleo
+ check:
+ jobs:
+ - puppet-something
+ """)
+
+ file_dict = {'.zuul.yaml': in_repo_conf}
+ A = self.fake_gerrit.addFakeChange('puppet-tripleo', 'stable/newton',
+ 'A', files=file_dict)
+ self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
+ self.waitUntilSettled()
+ self.assertHistory([
+ dict(name='puppet-something', result='SUCCESS', changes='1,1')])
+
+ def test_template_change_on_branch(self):
+ # Test that the contents of a template can be changed on one
+ # branch without affecting another.
+
+ # This creates a new branch with a copy of the config in master
+ self.create_branch('puppet-integration', 'stable/newton')
+ self.create_branch('puppet-integration', 'stable/ocata')
+ self.create_branch('puppet-tripleo', 'stable/newton')
+ self.create_branch('puppet-tripleo', 'stable/ocata')
+ self.fake_gerrit.addEvent(
+ self.fake_gerrit.getFakeBranchCreatedEvent(
+ 'puppet-integration', 'stable/newton'))
+ self.fake_gerrit.addEvent(
+ self.fake_gerrit.getFakeBranchCreatedEvent(
+ 'puppet-integration', 'stable/ocata'))
+ self.fake_gerrit.addEvent(
+ self.fake_gerrit.getFakeBranchCreatedEvent(
+ 'puppet-tripleo', 'stable/newton'))
+ self.fake_gerrit.addEvent(
+ self.fake_gerrit.getFakeBranchCreatedEvent(
+ 'puppet-tripleo', 'stable/ocata'))
+ self.waitUntilSettled()
+
+ in_repo_conf = textwrap.dedent("""
+ - job:
+ name: puppet-unit-base
+ run: playbooks/run-unit-tests.yaml
+
+ - job:
+ name: puppet-unit-3.8
+ parent: puppet-unit-base
+ branches: ^(stable/(newton|ocata)).*$
+ vars:
+ puppet_gem_version: 3.8
+
+ - job:
+ name: puppet-something
+ run: playbooks/run-unit-tests.yaml
+
+ - project-template:
+ name: puppet-unit
+ check:
+ jobs:
+ - puppet-something
+
+ - project:
+ name: puppet-integration
+ templates:
+ - puppet-unit
+ """)
+
+ file_dict = {'.zuul.yaml': in_repo_conf}
+ A = self.fake_gerrit.addFakeChange('puppet-integration',
+ 'stable/newton',
+ 'A', files=file_dict)
+ B = self.fake_gerrit.addFakeChange('puppet-tripleo',
+ 'stable/newton',
+ 'B')
+ B.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
+ B.subject, A.data['id'])
+ self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
+ self.waitUntilSettled()
+ self.assertHistory([
+ dict(name='puppet-something', result='SUCCESS',
+ changes='1,1 2,1')])
+
+
class TestBranchVariants(ZuulTestCase):
tenant_config_file = 'config/branch-variants/main.yaml'
diff --git a/zuul/model.py b/zuul/model.py
index 8044d93..081d165 100644
--- a/zuul/model.py
+++ b/zuul/model.py
@@ -949,6 +949,28 @@
matchers.append(change_matcher.BranchMatcher(branch))
self.branch_matcher = change_matcher.MatchAny(matchers)
+ def getSimpleBranchMatcher(self):
+ # If the job has a simple branch matcher, return it; otherwise None.
+ if not self.branch_matcher:
+ return None
+ m = self.branch_matcher
+ if not isinstance(m, change_matcher.AbstractMatcherCollection):
+ return None
+ if len(m.matchers) != 1:
+ return None
+ m = m.matchers[0]
+ if not isinstance(m, change_matcher.BranchMatcher):
+ return None
+ return m._regex
+
+ def addBranchMatcher(self, branch):
+ # Add a branch matcher that combines as a boolean *and* with
+ # existing branch matchers, if any.
+ matchers = [change_matcher.BranchMatcher(branch)]
+ if self.branch_matcher:
+ matchers.append(self.branch_matcher)
+ self.branch_matcher = change_matcher.MatchAll(matchers)
+
def updateVariables(self, other_vars):
v = copy.deepcopy(self.variables)
Job._deepUpdate(v, other_vars)
@@ -1098,9 +1120,26 @@
for jobname, jobs in other.jobs.items():
joblist = self.jobs.setdefault(jobname, [])
for job in jobs:
- if not job.branch_matcher and implied_branch:
- job = job.copy()
- job.setBranchMatcher([implied_branch])
+ if implied_branch:
+ # If setting an implied branch and the current
+ # branch matcher is a simple match for a different
+ # branch, then simply do not add this job. If it
+ # is absent, set it to the implied branch.
+ # Otherwise, combine it with the implied branch to
+ # ensure that it still only affects this branch
+ # (whatever else it may do).
+ simple_branch = job.getSimpleBranchMatcher()
+ if simple_branch and simple_branch != implied_branch:
+ # Job is for a different branch, don't add it.
+ continue
+ if not simple_branch:
+ # The branch matcher could be complex, or
+ # missing. Add our implied matcher.
+ job = job.copy()
+ job.addBranchMatcher(implied_branch)
+ # Otherwise we have a simple branch matcher which
+ # is the same as our implied branch, the job can
+ # be added as-is.
if job not in joblist:
joblist.append(job)
diff --git a/zuul/web/static/README b/zuul/web/static/README
index 487c3ee..f17ea5f 100644
--- a/zuul/web/static/README
+++ b/zuul/web/static/README
@@ -5,6 +5,35 @@
* /static/js/jquery.graphite.min.js
* /static/bootstrap/css/bootstrap.min.css
+
+Use python2-rjsmin or another js minifier:
+```
+DEST_DIR=/var/www/html/static/
+mkdir -p $DEST_DIR/js
+echo "Fetching angular..."
+curl -L --silent https://ajax.googleapis.com/ajax/libs/angularjs/1.5.6/angular.min.js > $DEST_DIR/js/angular.min.js
+
+echo "Fetching jquery..."
+curl -L --silent http://code.jquery.com/jquery.min.js > $DEST_DIR/js/jquery.min.js
+
+echo "Fetching jquery-visibility..."
+curl -L --silent https://raw.githubusercontent.com/mathiasbynens/jquery-visibility/master/jquery-visibility.js > $DEST_DIR/js/jquery-visibility.js
+python2 -mrjsmin < $DEST_DIR/js/jquery-visibility.js > $DEST_DIR/js/jquery-visibility.min.js
+
+echo "Fetching bootstrap..."
+curl -L --silent https://github.com/twbs/bootstrap/releases/download/v3.1.1/bootstrap-3.1.1-dist.zip > bootstrap.zip
+unzip -q -o bootstrap.zip -d $DEST_DIR/
+mv $DEST_DIR/bootstrap-3.1.1-dist $DEST_DIR/bootstrap
+rm -f bootstrap.zip
+
+echo "Fetching jquery-graphite..."
+curl -L --silent https://github.com/prestontimmons/graphitejs/archive/master.zip > jquery-graphite.zip
+unzip -q -o jquery-graphite.zip -d $DEST_DIR/
+python2 -mrjsmin < $DEST_DIR/graphitejs-master/jquery.graphite.js > $DEST_DIR/js/jquery.graphite.min.js
+rm -Rf jquery-graphite.zip $DEST_DIR/graphitejs-master
+```
+
+
Here is an example apache vhost configuration:
<VirtualHost zuul-web.example.com:80>
DocumentRoot /var/www/zuul-web