Skip to content

Commit 97d1b92

Browse files
authored
Merge pull request #319 from warden/PR162
JENKINS-43980: add support for expanding variables in IssueFieldUpdaterStep
2 parents 78bcbcd + 12dd7e8 commit 97d1b92

File tree

4 files changed

+186
-116
lines changed

4 files changed

+186
-116
lines changed

pom.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
<jira-rest-client.version>5.2.2</jira-rest-client.version>
2424
<fugue.version>3.0.0</fugue.version>
2525
<!-- jenkins -->
26-
<jenkins.version>2.222.4</jenkins.version>
26+
<jenkins.version>2.249.3</jenkins.version>
2727
<!-- security spotbugs -->
2828
<spotbugs.failOnError>false</spotbugs.failOnError>
2929
</properties>
@@ -321,7 +321,7 @@
321321
<dependencies>
322322
<dependency>
323323
<groupId>io.jenkins.tools.bom</groupId>
324-
<artifactId>bom-2.222.x</artifactId>
324+
<artifactId>bom-2.249.x</artifactId>
325325
<version>23</version>
326326
<scope>import</scope>
327327
<type>pom</type>

src/main/java/hudson/plugins/jira/pipeline/IssueFieldUpdateStep.java

Lines changed: 45 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package hudson.plugins.jira.pipeline;
22

33
import com.atlassian.jira.rest.client.api.RestClientException;
4+
import hudson.EnvVars;
45
import hudson.Extension;
56
import hudson.FilePath;
67
import hudson.Launcher;
@@ -17,17 +18,17 @@
1718
import hudson.tasks.BuildStepDescriptor;
1819
import hudson.tasks.Builder;
1920
import hudson.util.FormValidation;
20-
import jenkins.tasks.SimpleBuildStep;
21-
import org.kohsuke.stapler.DataBoundConstructor;
22-
import org.kohsuke.stapler.DataBoundSetter;
23-
import org.kohsuke.stapler.QueryParameter;
24-
25-
import javax.servlet.ServletException;
2621
import java.io.IOException;
2722
import java.io.PrintStream;
2823
import java.util.ArrayList;
24+
import java.util.Collections;
2925
import java.util.List;
3026
import java.util.Set;
27+
import javax.servlet.ServletException;
28+
import jenkins.tasks.SimpleBuildStep;
29+
import org.kohsuke.stapler.DataBoundConstructor;
30+
import org.kohsuke.stapler.DataBoundSetter;
31+
import org.kohsuke.stapler.QueryParameter;
3132

3233
/**
3334
* Issue custom fields updater
@@ -84,9 +85,11 @@ public String prepareFieldId(String fieldId) {
8485
return prepared;
8586
}
8687

87-
@Override
88-
public void perform(Run<?, ?> run, FilePath workspace, Launcher launcher, TaskListener listener)
89-
throws IOException {
88+
@Override
89+
public void perform(
90+
Run<?, ?> run, FilePath workspace, EnvVars env, Launcher launcher, TaskListener listener)
91+
throws IOException {
92+
9093
PrintStream logger = listener.getLogger();
9194

9295
AbstractIssueSelector selector = issueSelector;
@@ -115,14 +118,45 @@ public void perform(Run<?, ?> run, FilePath workspace, Launcher launcher, TaskLi
115118
return;
116119
}
117120

118-
List<JiraIssueField> fields = new ArrayList();
119-
fields.add(new JiraIssueField(prepareFieldId(fieldId), fieldValue));
121+
List<JiraIssueField> fields = Collections.singletonList(
122+
new JiraIssueField(
123+
prepareFieldId(getFieldId()),
124+
getFieldValue()
125+
)
126+
);
127+
128+
fields = expandVariables(fields, env);
120129

121130
for (String issue : issues) {
122131
submitFields(session, issue, fields, logger);
123132
}
133+
134+
}
135+
136+
@Override
137+
@Deprecated
138+
public void perform(Run<?, ?> run, FilePath workspace, Launcher launcher, TaskListener listener)
139+
throws InterruptedException, IOException {
140+
this.perform(run, workspace, run.getEnvironment(listener), launcher, listener);
141+
}
142+
143+
private List<JiraIssueField> expandVariables(List<JiraIssueField> fields, EnvVars envVars) {
144+
List<JiraIssueField> expandedFields = new ArrayList<>();
145+
for (JiraIssueField f : fields) {
146+
JiraIssueField jiraIssueField = new JiraIssueField(
147+
f.getId(),
148+
envVars.expand(f.getValue().toString())
149+
);
150+
expandedFields.add(jiraIssueField);
151+
}
152+
153+
return expandedFields;
124154
}
125155

156+
/**
157+
* @deprecated no reason for this to be exposed/public, use perform(...) instead
158+
*/
159+
@Deprecated
126160
public void submitFields(JiraSession session, String issueId, List<JiraIssueField> fields, PrintStream logger) {
127161
try {
128162
session.addFields(issueId, fields);

src/test/java/hudson/plugins/jira/IssueFieldUpdateStepTest.java

Lines changed: 0 additions & 103 deletions
This file was deleted.
Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
package hudson.plugins.jira.pipeline;
2+
3+
import static org.hamcrest.MatcherAssert.assertThat;
4+
import static org.hamcrest.Matchers.containsString;
5+
import static org.junit.Assert.assertEquals;
6+
import static org.junit.Assert.assertSame;
7+
import static org.mockito.ArgumentMatchers.any;
8+
import static org.mockito.ArgumentMatchers.anyList;
9+
import static org.mockito.ArgumentMatchers.anyString;
10+
import static org.mockito.Mockito.doAnswer;
11+
import static org.mockito.Mockito.doReturn;
12+
import static org.mockito.Mockito.mock;
13+
import static org.mockito.Mockito.spy;
14+
import static org.mockito.Mockito.when;
15+
16+
import hudson.EnvVars;
17+
import hudson.Launcher;
18+
import hudson.model.AbstractBuild;
19+
import hudson.model.AbstractProject;
20+
import hudson.model.BuildListener;
21+
import hudson.model.Job;
22+
import hudson.model.Result;
23+
import hudson.plugins.jira.JiraGlobalConfiguration;
24+
import hudson.plugins.jira.JiraSession;
25+
import hudson.plugins.jira.JiraSite;
26+
import hudson.plugins.jira.model.JiraIssueField;
27+
import hudson.plugins.jira.selector.ExplicitIssueSelector;
28+
import io.jenkins.plugins.casc.misc.JenkinsConfiguredWithCodeRule;
29+
import java.io.IOException;
30+
import java.io.PrintStream;
31+
import java.util.ArrayList;
32+
import java.util.Arrays;
33+
import java.util.Collections;
34+
import java.util.List;
35+
import java.util.Random;
36+
import org.junit.Before;
37+
import org.junit.Rule;
38+
import org.junit.Test;
39+
import org.junit.runner.RunWith;
40+
import org.jvnet.hudson.test.JenkinsRule;
41+
import org.mockito.Mock;
42+
import org.mockito.junit.MockitoJUnitRunner;
43+
import org.mockito.stubbing.Answer;
44+
45+
/** @author Dmitry Frolov tekillaz.dev@gmail.com */
46+
@RunWith(MockitoJUnitRunner.class)
47+
public class IssueFieldUpdateStepTest {
48+
49+
private static final String BUILD_NUMBER_VAR = "${BUILD_NUMBER}";
50+
51+
@Rule public JenkinsRule r = new JenkinsConfiguredWithCodeRule();
52+
53+
@Mock JiraSite site;
54+
@Mock JiraSession session;
55+
@Mock PrintStream logger;
56+
@Mock AbstractBuild build;
57+
@Mock Launcher launcher;
58+
@Mock BuildListener listener;
59+
@Mock AbstractProject project;
60+
@Mock Job job;
61+
62+
@Before
63+
public void before() {
64+
when(build.getParent()).thenReturn(project);
65+
when(build.getProject()).thenReturn(project);
66+
when(listener.getLogger()).thenReturn(logger);
67+
doReturn(session).when(site).getSession(any());
68+
JiraGlobalConfiguration.get().setSites(Collections.singletonList(site));
69+
// when(jiraGlobalConfiguration.getSites()).thenReturn(sites);
70+
// .getSession(build.getParent())).thenReturn(session);
71+
when(job.getBuild(any())).thenReturn(build);
72+
}
73+
74+
@Test
75+
public void checkPrepareFieldId() {
76+
77+
List<String> field_test = Arrays.asList("10100", "customfield_10100", "field_10100");
78+
79+
List<String> field_after =
80+
Arrays.asList("customfield_10100", "customfield_10100", "customfield_field_10100");
81+
82+
IssueFieldUpdateStep jifu = new IssueFieldUpdateStep(null, null, "");
83+
for (int i = 0; i < field_test.size(); i++)
84+
assertEquals(
85+
"Check field id conversion #" + i,
86+
jifu.prepareFieldId(field_test.get(i)),
87+
field_after.get(i));
88+
}
89+
90+
@Test(expected = IOException.class)
91+
public void shouldFailIfSelectorIsNull() throws InterruptedException, IOException {
92+
IssueFieldUpdateStep jifu = spy(new IssueFieldUpdateStep(null, "", ""));
93+
jifu.perform(build, null, launcher, listener);
94+
assertSame("Check selector is null", Result.FAILURE, build.getResult());
95+
}
96+
97+
@Test
98+
// @ConfiguredWithCode("single-site.yml")
99+
public void checkSubmit() throws InterruptedException, IOException {
100+
Random random = new Random();
101+
Integer randomBuildNumber = random.nextInt(85) + 15; // random number 15 < r < 99
102+
String issueId = "ISSUE-" + random.nextInt(1000) + 999;
103+
String beforeFieldid = "field" + random.nextInt(100) + 99;
104+
String beforeFieldValue = "Some comment, build #${BUILD_NUMBER}";
105+
106+
EnvVars env = new EnvVars();
107+
env.put("BUILD_NUMBER", randomBuildNumber.toString());
108+
when(build.getEnvironment(listener)).thenReturn(env);
109+
110+
final ExplicitIssueSelector issueSelector = new ExplicitIssueSelector(issueId);
111+
final List<String> issuesAfter = new ArrayList<String>();
112+
final List<JiraIssueField> fieldsAfter = new ArrayList<JiraIssueField>();
113+
114+
doAnswer(
115+
invocation -> {
116+
String id = (String) invocation.getArguments()[0];
117+
List<JiraIssueField> jif = (List<JiraIssueField>) invocation.getArguments()[1];
118+
issuesAfter.add(id);
119+
fieldsAfter.addAll(jif);
120+
return null;
121+
})
122+
.when(session)
123+
.addFields(anyString(), anyList());
124+
125+
IssueFieldUpdateStep jifu = spy(new IssueFieldUpdateStep(issueSelector, beforeFieldid, beforeFieldValue));
126+
jifu.perform(build, null, launcher, listener);
127+
128+
assertEquals("Check issue value", issuesAfter.get(0), issueId);
129+
assertEquals("customfield_" + beforeFieldid, fieldsAfter.get(0).getId());
130+
assertThat(
131+
fieldsAfter.get(0).getValue().toString(),
132+
containsString("build #" + randomBuildNumber.toString()));
133+
134+
jifu.perform(build, null, env, launcher, listener);
135+
assertThat(
136+
fieldsAfter.get(1).getValue().toString(),
137+
containsString("build #" + randomBuildNumber.toString()));
138+
}
139+
}

0 commit comments

Comments
 (0)