From d43c49a61f10a866951451993cb3ca9193392174 Mon Sep 17 00:00:00 2001 From: Allan Burdajewicz Date: Mon, 7 Mar 2016 17:49:16 +1000 Subject: [PATCH 1/5] [JENKINS-32526] - Handle null @AncestorInPath when selecting Jobs/Downstream/Upstream Jobs and for autocompletion. --- .../plugins/copyartifact/CopyArtifact.java | 4 +- .../copyartifact/DownstreamBuildSelector.java | 11 ++- .../copyartifact/CopyArtifactTest.java | 6 ++ .../DownstreamBuildSelectorTest.java | 92 ++++++++++++++++--- 4 files changed, 99 insertions(+), 14 deletions(-) diff --git a/src/main/java/hudson/plugins/copyartifact/CopyArtifact.java b/src/main/java/hudson/plugins/copyartifact/CopyArtifact.java index b48e8373..16abf72a 100644 --- a/src/main/java/hudson/plugins/copyartifact/CopyArtifact.java +++ b/src/main/java/hudson/plugins/copyartifact/CopyArtifact.java @@ -577,7 +577,9 @@ public String resolve(String name) { public static final class DescriptorImpl extends BuildStepDescriptor { public FormValidation doCheckProjectName( - @AncestorInPath Job anc, @QueryParameter String value) { + @AncestorInPath AbstractProject anc, @QueryParameter String value) { + // JENKINS-32526: Check that it behaves gracefully for an unknown context + if (anc == null) return FormValidation.ok(); // Require CONFIGURE permission on this project if (!anc.hasPermission(Item.CONFIGURE)) return FormValidation.ok(); diff --git a/src/main/java/hudson/plugins/copyartifact/DownstreamBuildSelector.java b/src/main/java/hudson/plugins/copyartifact/DownstreamBuildSelector.java index 5b76924d..89521a27 100644 --- a/src/main/java/hudson/plugins/copyartifact/DownstreamBuildSelector.java +++ b/src/main/java/hudson/plugins/copyartifact/DownstreamBuildSelector.java @@ -188,6 +188,11 @@ public FormValidation doCheckUpstreamProjectName( if (containsVariable(upstreamProjectName)) { return FormValidation.ok(); } + + if (project == null) { + // Context is unknown and validation is useless. + return FormValidation.ok(); + } Jenkins jenkins = Jenkins.getInstance(); if (jenkins == null) { @@ -239,7 +244,7 @@ public FormValidation doCheckUpstreamBuildNumber( } AbstractProject upstreamProject = jenkins.getItem( - upstreamProjectName, project.getRootProject(), AbstractProject.class + upstreamProjectName, project == null ? null : project.getRootProject(), AbstractProject.class ); if (upstreamProject == null || !upstreamProject.hasPermission(Item.READ)) { return FormValidation.ok(); @@ -292,7 +297,9 @@ public AutoCompletionCandidates doAutoCompleteUpstreamProjectName( @AncestorInPath AbstractProject project ) { // Specified Item to allow to autocomplete folders (maybe confusing...). - return AutoCompletionCandidates.ofJobNames(Item.class, value, project, project.getParent()); + return project == null + ? AutoCompletionCandidates.ofJobNames(Item.class, value, null) + : AutoCompletionCandidates.ofJobNames(Item.class, value, project, project.getParent()); } } } diff --git a/src/test/java/hudson/plugins/copyartifact/CopyArtifactTest.java b/src/test/java/hudson/plugins/copyartifact/CopyArtifactTest.java index 04bd5625..6e61b610 100644 --- a/src/test/java/hudson/plugins/copyartifact/CopyArtifactTest.java +++ b/src/test/java/hudson/plugins/copyartifact/CopyArtifactTest.java @@ -1155,10 +1155,16 @@ public void testFieldValidation() throws Exception { assertSame(FormValidation.Kind.ERROR, descriptor.doCheckProjectName(p, "").kind); // Parameterized value assertSame(FormValidation.Kind.WARNING, descriptor.doCheckProjectName(p, "$FOO").kind); + //JENKINS-32526: Check that it behaves gracefully for an unknown context. + assertSame(FormValidation.Kind.OK, descriptor.doCheckProjectName(null, p.getFullName()).kind); + assertSame(FormValidation.Kind.OK, descriptor.doCheckProjectName(null, "").kind); + assertSame(FormValidation.Kind.OK, descriptor.doCheckProjectName(null, "$FOO").kind); + // Just returns OK if no permission hudson.setAuthorizationStrategy(new GlobalMatrixAuthorizationStrategy()); SecurityContextHolder.clearContext(); assertSame(FormValidation.Kind.OK, descriptor.doCheckProjectName(p, "").kind); + assertSame(FormValidation.Kind.OK, descriptor.doCheckProjectName(null, "").kind); // Other descriptor methods assertTrue(descriptor.isApplicable(null)); assertTrue(descriptor.getDisplayName().length() > 0); diff --git a/src/test/java/hudson/plugins/copyartifact/DownstreamBuildSelectorTest.java b/src/test/java/hudson/plugins/copyartifact/DownstreamBuildSelectorTest.java index b5a39ddd..a631d1bb 100644 --- a/src/test/java/hudson/plugins/copyartifact/DownstreamBuildSelectorTest.java +++ b/src/test/java/hudson/plugins/copyartifact/DownstreamBuildSelectorTest.java @@ -31,19 +31,10 @@ import java.util.Map; import java.util.Set; +import hudson.model.*; import hudson.plugins.copyartifact.testutils.CopyArtifactUtil; import jenkins.model.Jenkins; import hudson.FilePath; -import hudson.model.Cause; -import hudson.model.FreeStyleProject; -import hudson.model.FreeStyleBuild; -import hudson.model.Item; -import hudson.model.ParametersAction; -import hudson.model.ParametersDefinitionProperty; -import hudson.model.StringParameterDefinition; -import hudson.model.StringParameterValue; -import hudson.model.User; -import hudson.model.Result; import hudson.plugins.copyartifact.testutils.FileWriteBuilder; import hudson.security.Permission; import hudson.security.AuthorizationMatrixProperty; @@ -57,6 +48,7 @@ import org.acegisecurity.context.SecurityContextHolder; import org.junit.Rule; import org.junit.Test; +import org.jvnet.hudson.test.Issue; import org.jvnet.hudson.test.JenkinsRule; import org.jvnet.hudson.test.MockFolder; @@ -546,6 +538,21 @@ public void testCheckUpstreamProjectName() throws Exception { assertEquals(FormValidation.Kind.OK, d.doCheckUpstreamProjectName(project2, "../project1").kind); assertEquals(FormValidation.Kind.OK, d.doCheckUpstreamProjectName(project2, "project3").kind); assertEquals(FormValidation.Kind.OK, d.doCheckUpstreamProjectName(project2, "/folder1/project3").kind); + + //JENKINS-32526: Check that it behaves gracefully for an unknown context + assertEquals(FormValidation.Kind.ERROR, d.doCheckUpstreamProjectName(null, null).kind); + assertEquals(FormValidation.Kind.ERROR, d.doCheckUpstreamProjectName(null, "").kind); + assertEquals(FormValidation.Kind.ERROR, d.doCheckUpstreamProjectName(null, " ").kind); + + //Ancestor null returns OK + assertEquals(FormValidation.Kind.OK, d.doCheckUpstreamProjectName(null, "nosuchproject").kind); + assertEquals(FormValidation.Kind.OK, d.doCheckUpstreamProjectName(null, "$VAR").kind); + assertEquals(FormValidation.Kind.OK, d.doCheckUpstreamProjectName(null, "FOO${VAR}").kind); + assertEquals(FormValidation.Kind.OK, d.doCheckUpstreamProjectName(null, "Project\\$").kind); // limitation + assertEquals(FormValidation.Kind.OK, d.doCheckUpstreamProjectName(null, "folder1/project2").kind); + assertEquals(FormValidation.Kind.OK, d.doCheckUpstreamProjectName(null, "../project1").kind); + assertEquals(FormValidation.Kind.OK, d.doCheckUpstreamProjectName(null, "project3").kind); + assertEquals(FormValidation.Kind.OK, d.doCheckUpstreamProjectName(null, "/folder1/project3").kind); // permission check Authentication a = Jenkins.getAuthentication(); @@ -553,6 +560,8 @@ public void testCheckUpstreamProjectName() throws Exception { SecurityContextHolder.getContext().setAuthentication(User.get("devel").impersonate()); assertEquals(FormValidation.Kind.OK, d.doCheckUpstreamProjectName(project2, "../project1").kind); assertEquals(FormValidation.Kind.ERROR, d.doCheckUpstreamProjectName(project2, "project3").kind); + assertEquals(FormValidation.Kind.OK, d.doCheckUpstreamProjectName(null, "../project1").kind); + assertEquals(FormValidation.Kind.OK, d.doCheckUpstreamProjectName(null, "project3").kind); } finally { SecurityContextHolder.getContext().setAuthentication(a); } @@ -605,14 +614,75 @@ public void testCheckUpstreamBuildNumber() throws Exception { assertEquals(FormValidation.Kind.ERROR, d.doCheckUpstreamBuildNumber(project1, "project2", "9999").kind); assertEquals(FormValidation.Kind.ERROR, d.doCheckUpstreamBuildNumber(project1, "project2", "NosuchBuild").kind); - + + //JENKINS-32526: Check that it behaves gracefully for an unknown context + assertEquals(FormValidation.Kind.OK, d.doCheckUpstreamBuildNumber(null, "", Integer.toString(build1.getNumber())).kind); + assertEquals(FormValidation.Kind.OK, d.doCheckUpstreamBuildNumber(null, "$VAR", Integer.toString(build1.getNumber())).kind); + + assertEquals(FormValidation.Kind.ERROR, d.doCheckUpstreamBuildNumber(null, "project2", null).kind); + assertEquals(FormValidation.Kind.ERROR, d.doCheckUpstreamBuildNumber(null, "project2", "").kind); + assertEquals(FormValidation.Kind.ERROR, d.doCheckUpstreamBuildNumber(null, "project2", " ").kind); + + assertEquals(FormValidation.Kind.OK, d.doCheckUpstreamBuildNumber(null, "project2", "FOO${VAR}").kind); + assertEquals(FormValidation.Kind.OK, d.doCheckUpstreamBuildNumber(null, "project2", "\\${VAR}").kind); // limitation + + assertEquals(FormValidation.Kind.OK, d.doCheckUpstreamBuildNumber(null, "project2", Integer.toString(build1.getNumber())).kind); + assertEquals(FormValidation.Kind.OK, d.doCheckUpstreamBuildNumber(null, "project2", build1.getId()).kind); + assertEquals(FormValidation.Kind.OK, d.doCheckUpstreamBuildNumber(null, "project2", build1.getDisplayName()).kind); + + assertEquals(FormValidation.Kind.ERROR, d.doCheckUpstreamBuildNumber(null, "project2", "9999").kind); + assertEquals(FormValidation.Kind.ERROR, d.doCheckUpstreamBuildNumber(null, "project2", "NosuchBuild").kind); + // permission check Authentication a = Jenkins.getAuthentication(); try { SecurityContextHolder.getContext().setAuthentication(User.get("devel").impersonate()); assertEquals(FormValidation.Kind.OK, d.doCheckUpstreamBuildNumber(project1, "project3", "nosuchbuild").kind); // limitation + assertEquals(FormValidation.Kind.OK, d.doCheckUpstreamBuildNumber(null, "project3", "nosuchbuild").kind); } finally { SecurityContextHolder.getContext().setAuthentication(a); } } + + @Test + public void testAutoCompleteUpstreamProjectName() throws Exception { + DownstreamBuildSelector.DescriptorImpl d = (DownstreamBuildSelector.DescriptorImpl) j.jenkins.getDescriptorOrDie(DownstreamBuildSelector.class); + + ProjectMatrixAuthorizationStrategy pmas = new ProjectMatrixAuthorizationStrategy(); + pmas.add(Jenkins.READ, "devel"); + + j.jenkins.setSecurityRealm(j.createDummySecurityRealm()); + j.jenkins.setAuthorizationStrategy(pmas); + + // project1 + // project2 cannot read from devel + FreeStyleProject project1 = j.createFreeStyleProject("project1"); + { + Map> map = new HashMap>(); + map.put(Item.READ, Sets.newHashSet("devel")); + project1.addProperty(new AuthorizationMatrixProperty(map)); + } + + FreeStyleProject project2 = j.createFreeStyleProject("project2"); + + //Check Empty strings + testAutoCompleteUpstreamProjectName(new String [] {project1.getName(), project2.getName()}, "", project1, d); + //Check simple matching string + testAutoCompleteUpstreamProjectName(new String [] {project1.getName(), project2.getName()}, "proj", project1, d); + //Check non matching string + testAutoCompleteUpstreamProjectName(new String [] {}, "FOO", project1, d); + //Check matching string + testAutoCompleteUpstreamProjectName(new String [] {project1.getName()}, "project1", project2, d); + } + + private void testAutoCompleteUpstreamProjectName( + String [] expectedValues, + String value, + AbstractProject project, + DownstreamBuildSelector.DescriptorImpl d) { + + assertArrayEquals(expectedValues, d.doAutoCompleteUpstreamProjectName(value, project).getValues().toArray()); + //JENKINS-32526 + assertArrayEquals(expectedValues, d.doAutoCompleteUpstreamProjectName(value, null).getValues().toArray()); + } } From 85c8b1a6e8dd74300cbd82ce4d341ad4f1510aee Mon Sep 17 00:00:00 2001 From: Allan Burdajewicz Date: Sat, 12 Mar 2016 14:25:32 +1000 Subject: [PATCH 2/5] [JENKINS-32526] - Fixed imports and ordered set, changed attribute class back to Job, added message about the context --- .../plugins/copyartifact/CopyArtifact.java | 4 ++-- .../plugins/copyartifact/Messages.properties | 1 + .../DownstreamBuildSelectorTest.java | 20 +++++++++++++++---- 3 files changed, 19 insertions(+), 6 deletions(-) diff --git a/src/main/java/hudson/plugins/copyartifact/CopyArtifact.java b/src/main/java/hudson/plugins/copyartifact/CopyArtifact.java index 16abf72a..130fb188 100644 --- a/src/main/java/hudson/plugins/copyartifact/CopyArtifact.java +++ b/src/main/java/hudson/plugins/copyartifact/CopyArtifact.java @@ -577,9 +577,9 @@ public String resolve(String name) { public static final class DescriptorImpl extends BuildStepDescriptor { public FormValidation doCheckProjectName( - @AncestorInPath AbstractProject anc, @QueryParameter String value) { + @AncestorInPath Job anc, @QueryParameter String value) { // JENKINS-32526: Check that it behaves gracefully for an unknown context - if (anc == null) return FormValidation.ok(); + if (anc == null) return FormValidation.ok(Messages.CopyArtifact_AncestorIsNull()); // Require CONFIGURE permission on this project if (!anc.hasPermission(Item.CONFIGURE)) return FormValidation.ok(); diff --git a/src/main/resources/hudson/plugins/copyartifact/Messages.properties b/src/main/resources/hudson/plugins/copyartifact/Messages.properties index 37f6edd4..755d1de1 100644 --- a/src/main/resources/hudson/plugins/copyartifact/Messages.properties +++ b/src/main/resources/hudson/plugins/copyartifact/Messages.properties @@ -1,3 +1,4 @@ +CopyArtifact.AncestorIsNull=Ancestor/Context Unknown: the project specified cannot be validated CopyArtifact.Copied=Copied {0} {0,choice,0#artifacts|1#artifact|1 actualValues = new TreeSet(d.doAutoCompleteUpstreamProjectName(value, project).getValues()); + assertArrayEquals(expectedValues, actualValues.toArray(new String [actualValues.size()])); //JENKINS-32526 - assertArrayEquals(expectedValues, d.doAutoCompleteUpstreamProjectName(value, null).getValues().toArray()); + actualValues = new TreeSet(d.doAutoCompleteUpstreamProjectName(value, null).getValues()); + assertArrayEquals(expectedValues, actualValues.toArray(new String [actualValues.size()])); } } From 65b30d6da1983e11be0f93d9defb664796fca99d Mon Sep 17 00:00:00 2001 From: Allan Burdajewicz Date: Thu, 17 Mar 2016 08:26:04 +1000 Subject: [PATCH 3/5] [JENKINS-32526] - Fixed workflow compatibility for DownstreamBuilds selection. --- .../copyartifact/DownstreamBuildSelector.java | 27 ++++++++++++------- .../DownstreamBuildSelectorTest.java | 12 ++++----- 2 files changed, 23 insertions(+), 16 deletions(-) diff --git a/src/main/java/hudson/plugins/copyartifact/DownstreamBuildSelector.java b/src/main/java/hudson/plugins/copyartifact/DownstreamBuildSelector.java index 89521a27..c907ce37 100644 --- a/src/main/java/hudson/plugins/copyartifact/DownstreamBuildSelector.java +++ b/src/main/java/hudson/plugins/copyartifact/DownstreamBuildSelector.java @@ -177,7 +177,7 @@ protected boolean containsVariable(String str) { * @return */ public FormValidation doCheckUpstreamProjectName( - @AncestorInPath AbstractProject project, + @AncestorInPath Job project, @QueryParameter String upstreamProjectName ) { upstreamProjectName = StringUtils.trim(upstreamProjectName); @@ -188,20 +188,22 @@ public FormValidation doCheckUpstreamProjectName( if (containsVariable(upstreamProjectName)) { return FormValidation.ok(); } - - if (project == null) { - // Context is unknown and validation is useless. - return FormValidation.ok(); - } Jenkins jenkins = Jenkins.getInstance(); if (jenkins == null) { // Jenkins is unavailable and validation is useless. return FormValidation.ok(); } + + AbstractProject upstreamRoot; + if(project != null && project instanceof AbstractProject) { + upstreamRoot = ((AbstractProject) project).getRootProject(); + } else { + upstreamRoot = null; + } AbstractProject upstreamProject = jenkins.getItem( - upstreamProjectName, project.getRootProject(), AbstractProject.class + upstreamProjectName, upstreamRoot, AbstractProject.class ); if (upstreamProject == null || !upstreamProject.hasPermission(Item.READ)) { return FormValidation.error(Messages.DownstreamBuildSelector_UpstreamProjectName_NotFound()); @@ -215,7 +217,7 @@ public FormValidation doCheckUpstreamProjectName( * @return */ public FormValidation doCheckUpstreamBuildNumber( - @AncestorInPath AbstractProject project, + @AncestorInPath Job project, @QueryParameter String upstreamProjectName, @QueryParameter String upstreamBuildNumber ) { @@ -242,9 +244,16 @@ public FormValidation doCheckUpstreamBuildNumber( // Jenkins is unavailable and validation is useless. return FormValidation.ok(); } + + AbstractProject rootProject; + if(project != null && project instanceof AbstractProject) { + rootProject = ((AbstractProject) project).getRootProject(); + } else { + rootProject = null; + } AbstractProject upstreamProject = jenkins.getItem( - upstreamProjectName, project == null ? null : project.getRootProject(), AbstractProject.class + upstreamProjectName, rootProject, AbstractProject.class ); if (upstreamProject == null || !upstreamProject.hasPermission(Item.READ)) { return FormValidation.ok(); diff --git a/src/test/java/hudson/plugins/copyartifact/DownstreamBuildSelectorTest.java b/src/test/java/hudson/plugins/copyartifact/DownstreamBuildSelectorTest.java index cd023d62..d8859e4c 100644 --- a/src/test/java/hudson/plugins/copyartifact/DownstreamBuildSelectorTest.java +++ b/src/test/java/hudson/plugins/copyartifact/DownstreamBuildSelectorTest.java @@ -554,15 +554,13 @@ public void testCheckUpstreamProjectName() throws Exception { assertEquals(FormValidation.Kind.ERROR, d.doCheckUpstreamProjectName(null, "").kind); assertEquals(FormValidation.Kind.ERROR, d.doCheckUpstreamProjectName(null, " ").kind); - //Ancestor null returns OK - assertEquals(FormValidation.Kind.OK, d.doCheckUpstreamProjectName(null, "nosuchproject").kind); + //Ancestor null + assertEquals(FormValidation.Kind.ERROR, d.doCheckUpstreamProjectName(null, "nosuchproject").kind); assertEquals(FormValidation.Kind.OK, d.doCheckUpstreamProjectName(null, "$VAR").kind); assertEquals(FormValidation.Kind.OK, d.doCheckUpstreamProjectName(null, "FOO${VAR}").kind); assertEquals(FormValidation.Kind.OK, d.doCheckUpstreamProjectName(null, "Project\\$").kind); // limitation + //Only relative path from Root works assertEquals(FormValidation.Kind.OK, d.doCheckUpstreamProjectName(null, "folder1/project2").kind); - assertEquals(FormValidation.Kind.OK, d.doCheckUpstreamProjectName(null, "../project1").kind); - assertEquals(FormValidation.Kind.OK, d.doCheckUpstreamProjectName(null, "project3").kind); - assertEquals(FormValidation.Kind.OK, d.doCheckUpstreamProjectName(null, "/folder1/project3").kind); // permission check Authentication a = Jenkins.getAuthentication(); @@ -570,8 +568,8 @@ public void testCheckUpstreamProjectName() throws Exception { SecurityContextHolder.getContext().setAuthentication(User.get("devel").impersonate()); assertEquals(FormValidation.Kind.OK, d.doCheckUpstreamProjectName(project2, "../project1").kind); assertEquals(FormValidation.Kind.ERROR, d.doCheckUpstreamProjectName(project2, "project3").kind); - assertEquals(FormValidation.Kind.OK, d.doCheckUpstreamProjectName(null, "../project1").kind); - assertEquals(FormValidation.Kind.OK, d.doCheckUpstreamProjectName(null, "project3").kind); + assertEquals(FormValidation.Kind.OK, d.doCheckUpstreamProjectName(null, "/project1").kind); + assertEquals(FormValidation.Kind.ERROR, d.doCheckUpstreamProjectName(null, "project3").kind); } finally { SecurityContextHolder.getContext().setAuthentication(a); } From bf6f1e176a5f9795f155726c252200d17375c738 Mon Sep 17 00:00:00 2001 From: Allan Burdajewicz Date: Sat, 19 Mar 2016 10:34:14 +1000 Subject: [PATCH 4/5] [JENKINS-32526] - Ancestors null: Fixed autocompletion and the method to find upstream project. --- .../copyartifact/DownstreamBuildSelector.java | 22 ++++--------------- .../plugins/copyartifact/Messages.properties | 2 +- .../DownstreamBuildSelectorTest.java | 4 ++-- 3 files changed, 7 insertions(+), 21 deletions(-) diff --git a/src/main/java/hudson/plugins/copyartifact/DownstreamBuildSelector.java b/src/main/java/hudson/plugins/copyartifact/DownstreamBuildSelector.java index c907ce37..f038d989 100644 --- a/src/main/java/hudson/plugins/copyartifact/DownstreamBuildSelector.java +++ b/src/main/java/hudson/plugins/copyartifact/DownstreamBuildSelector.java @@ -194,16 +194,9 @@ public FormValidation doCheckUpstreamProjectName( // Jenkins is unavailable and validation is useless. return FormValidation.ok(); } - - AbstractProject upstreamRoot; - if(project != null && project instanceof AbstractProject) { - upstreamRoot = ((AbstractProject) project).getRootProject(); - } else { - upstreamRoot = null; - } AbstractProject upstreamProject = jenkins.getItem( - upstreamProjectName, upstreamRoot, AbstractProject.class + upstreamProjectName, project, AbstractProject.class ); if (upstreamProject == null || !upstreamProject.hasPermission(Item.READ)) { return FormValidation.error(Messages.DownstreamBuildSelector_UpstreamProjectName_NotFound()); @@ -244,16 +237,9 @@ public FormValidation doCheckUpstreamBuildNumber( // Jenkins is unavailable and validation is useless. return FormValidation.ok(); } - - AbstractProject rootProject; - if(project != null && project instanceof AbstractProject) { - rootProject = ((AbstractProject) project).getRootProject(); - } else { - rootProject = null; - } AbstractProject upstreamProject = jenkins.getItem( - upstreamProjectName, rootProject, AbstractProject.class + upstreamProjectName, project, AbstractProject.class ); if (upstreamProject == null || !upstreamProject.hasPermission(Item.READ)) { return FormValidation.ok(); @@ -303,11 +289,11 @@ public FormValidation doCheckUpstreamBuildNumber( */ public AutoCompletionCandidates doAutoCompleteUpstreamProjectName( @QueryParameter String value, - @AncestorInPath AbstractProject project + @AncestorInPath Job project ) { // Specified Item to allow to autocomplete folders (maybe confusing...). return project == null - ? AutoCompletionCandidates.ofJobNames(Item.class, value, null) + ? new AutoCompletionCandidates() : AutoCompletionCandidates.ofJobNames(Item.class, value, project, project.getParent()); } } diff --git a/src/main/resources/hudson/plugins/copyartifact/Messages.properties b/src/main/resources/hudson/plugins/copyartifact/Messages.properties index 755d1de1..74f1f4f9 100644 --- a/src/main/resources/hudson/plugins/copyartifact/Messages.properties +++ b/src/main/resources/hudson/plugins/copyartifact/Messages.properties @@ -1,4 +1,4 @@ -CopyArtifact.AncestorIsNull=Ancestor/Context Unknown: the project specified cannot be validated +CopyArtifact.AncestorIsNull=Context Unknown: the project specified cannot be validated CopyArtifact.Copied=Copied {0} {0,choice,0#artifacts|1#artifact|1 actualValues = new TreeSet(d.doAutoCompleteUpstreamProjectName(value, project).getValues()); assertArrayEquals(expectedValues, actualValues.toArray(new String [actualValues.size()])); - //JENKINS-32526 + //JENKINS-32526: Auto-completion disabled if no context actualValues = new TreeSet(d.doAutoCompleteUpstreamProjectName(value, null).getValues()); - assertArrayEquals(expectedValues, actualValues.toArray(new String [actualValues.size()])); + assertArrayEquals(new String[] {}, actualValues.toArray(new String [actualValues.size()])); } } From 44cfb04bf15ff8ef5fb4f083edbd099aec1111a8 Mon Sep 17 00:00:00 2001 From: Allan Burdajewicz Date: Sun, 27 Mar 2016 13:27:21 +1000 Subject: [PATCH 5/5] [JENKINS-32526] - Ancestors null: Reimplemented getRootProject and skip validation when null. --- .../copyartifact/DownstreamBuildSelector.java | 30 +++++++++++++++---- .../plugins/copyartifact/Messages.properties | 2 +- .../DownstreamBuildSelectorTest.java | 8 ++--- 3 files changed, 30 insertions(+), 10 deletions(-) diff --git a/src/main/java/hudson/plugins/copyartifact/DownstreamBuildSelector.java b/src/main/java/hudson/plugins/copyartifact/DownstreamBuildSelector.java index f038d989..eb78b91f 100644 --- a/src/main/java/hudson/plugins/copyartifact/DownstreamBuildSelector.java +++ b/src/main/java/hudson/plugins/copyartifact/DownstreamBuildSelector.java @@ -194,10 +194,20 @@ public FormValidation doCheckUpstreamProjectName( // Jenkins is unavailable and validation is useless. return FormValidation.ok(); } - - AbstractProject upstreamProject = jenkins.getItem( - upstreamProjectName, project, AbstractProject.class + + if (project == null) { + // Context is unknown and validation is useless. + return FormValidation.ok(Messages.CopyArtifact_AncestorIsNull()); + } + + Job upstreamRoot = (project instanceof AbstractProject) + ? ((AbstractProject) project).getRootProject() + : project; + + Job upstreamProject = jenkins.getItem( + upstreamProjectName, upstreamRoot, Job.class ); + if (upstreamProject == null || !upstreamProject.hasPermission(Item.READ)) { return FormValidation.error(Messages.DownstreamBuildSelector_UpstreamProjectName_NotFound()); } @@ -237,10 +247,20 @@ public FormValidation doCheckUpstreamBuildNumber( // Jenkins is unavailable and validation is useless. return FormValidation.ok(); } - + + if (project == null) { + // Context is unknown and validation is useless. + return FormValidation.ok(Messages.CopyArtifact_AncestorIsNull()); + } + + Job upstreamRoot = (project instanceof AbstractProject) + ? ((AbstractProject) project).getRootProject() + : project; + AbstractProject upstreamProject = jenkins.getItem( - upstreamProjectName, project, AbstractProject.class + upstreamProjectName, upstreamRoot, AbstractProject.class ); + if (upstreamProject == null || !upstreamProject.hasPermission(Item.READ)) { return FormValidation.ok(); } diff --git a/src/main/resources/hudson/plugins/copyartifact/Messages.properties b/src/main/resources/hudson/plugins/copyartifact/Messages.properties index 74f1f4f9..342acac0 100644 --- a/src/main/resources/hudson/plugins/copyartifact/Messages.properties +++ b/src/main/resources/hudson/plugins/copyartifact/Messages.properties @@ -1,4 +1,4 @@ -CopyArtifact.AncestorIsNull=Context Unknown: the project specified cannot be validated +CopyArtifact.AncestorIsNull=Context Unknown: the value specified cannot be validated CopyArtifact.Copied=Copied {0} {0,choice,0#artifacts|1#artifact|1