Skip to content

Commit 6862d34

Browse files
committed
handle null from XStream readResolve and refactor to fluent interface
1 parent 990a259 commit 6862d34

File tree

6 files changed

+88
-52
lines changed

6 files changed

+88
-52
lines changed

CONTRIBUTING.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ General rules:
44

55
- check the [general Jenkins development guide](https://www.jenkins.io/doc/developer/book/)
66
- make sure to provide tests
7+
- when adding new fields, make sure to [include backward-compatibility](https://www.jenkins.io/doc/developer/persistence/backward-compatibility/) and tests for that
78
- mark the Pull Request as _draft_ initially, to make sure all the checks pass correctly, then convert it to non-draft.
89

910
## Setting up your environment
@@ -22,20 +23,19 @@ brew install pre-commit && pre-commit install --install-hooks
2223

2324
Use [docker-compose](./docker-compose.yml) to run a local Jenkins instance with the plugin installed. The configuration includes local volumes for both: Jenkins and ssh-agent, so you can easily test the plugin in a clean environment.
2425

25-
```bash
2626

2727
### Atlassian sources import
2828

29-
To resolve some binary compatibility issues [JENKINS-48357](https://issues.jenkins-ci.org/browse/JENKINS-48357),
29+
To resolve [some binary compatibility issues](https://github.com/jenkinsci/jira-plugin/pull/140),
3030
the sources from the artifact [com.atlassian.httpclient:atlassian-httpclient-plugin:0.23](https://packages.atlassian.com/maven-external/com/atlassian/httpclient/atlassian-httpclient-plugin/0.23.0/)
3131
has been imported in the project to have control over http(s) protocol transport layer.
3232
The downloaded sources didn't have any license headers but based on the [pom](https://packages.atlassian.com/maven-external/com/atlassian/httpclient/atlassian-httpclient-plugin/0.23.0/atlassian-httpclient-plugin-0.23.0.pom)
33-
sources are Apache License (see pom in src/main/resources/atlassian-httpclient-plugin-0.23.0.pom)
33+
sources are Apache License (see pom in src/main/resources/atlassian-httpclient-plugin-0.23.0.pom)
3434

3535
### Testing
3636

3737
There is a [Jira Cloud](https://jenkins-jira-plugin.atlassian.net/) test instance that the changes can be tested against, official maintainers are admins that can grant access for testing to PR submitters on a need-to-have basis.
3838

3939
### Releasing the plugin
4040

41-
Make sure you have your `~/.m2/settings.xml` configured accordingly - refer to [releasing Jenkins plugins](https://www.jenkins.io/doc/developer/publishing/releasing/).
41+
See [releasing Jenkins plugins](https://www.jenkins.io/doc/developer/publishing/releasing-manually/).

README.md

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@
66
[![Jenkins CI](https://ci.jenkins.io/buildStatus/icon?job=Plugins/jira-plugin/master)](https://ci.jenkins.io/job/Plugins/job/jira-plugin/)
77
[![Contributors](https://img.shields.io/github/contributors/jenkinsci/jira-plugin.svg)](https://github.com/jenkinsci/jira-plugin/graphs/contributors)
88

9-
See user documentation at [https://jenkinsci.github.io/jira-plugin/](https://jenkinsci.github.io/jira-plugin/)
9+
1. See user documentation at [https://jenkinsci.github.io/jira-plugin/](https://jenkinsci.github.io/jira-plugin/).
10+
1. Use [Declarative pipelines](https://www.jenkins.io/doc/book/pipeline/#declarative-versus-scripted-pipeline-syntax).
11+
1. Check [jira plugin steps reference](https://www.jenkins.io/doc/pipeline/steps/jira/).
1012

1113
## i18n
1214

@@ -22,10 +24,3 @@ See user documentation at [https://jenkinsci.github.io/jira-plugin/](https://jen
2224

2325
This plugin uses [CrowdIn platform](https://jenkins.crowdin.com/jira-plugin) as the frontend to manage translations. If you would like to contribute translation of this plugin in your language, you're most welcome! For details, see [jenkins.io CrowdIn introduction](https://www.jenkins.io/doc/developer/crowdin/translating-plugins/).
2426

25-
## Contributing
26-
27-
There have been many developers involved in the development of this plugin and there are many downstream users who depend on it. Tests help us assure that we're delivering a reliable plugin and that we've communicated our intent to other developers in a way that they can detect when they run tests.
28-
29-
- each change should be covered by appropriate unit tests
30-
- in case it is not testable via a unit test, it should be tested against a real Jira instance - possibly both Jira Server and Jira Cloud. There is a [Jira Cloud test instance](https://jenkins-jira-plugin.atlassian.net/) that we are using for testing the plugin releases - let us know in the Pull Request in case you need access for testing
31-

src/main/java/hudson/plugins/jira/JiraVersionCreator.java

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,15 @@
1818
* A build step which creates new Jira version
1919
*
2020
* @author Artem Koshelev [email protected]
21-
* @deprecated Replaced by {@link JiraVersionCreatorBuilder}. Read its description to see why.
22-
* Kept for backward compatibility.
21+
* @deprecated Replaced by {@link JiraVersionCreatorBuilder}. Read its
22+
* description to see why. Kept for backward compatibility.
2323
*/
2424
@Deprecated
2525
public class JiraVersionCreator extends Notifier {
26+
2627
private String jiraVersion;
2728
private String jiraProjectKey;
28-
private boolean failIfAlreadyExists = true;
29+
private Boolean failIfAlreadyExists = true;
2930

3031
@DataBoundConstructor
3132
public JiraVersionCreator(String jiraVersion, String jiraProjectKey) {
@@ -67,14 +68,24 @@ public void setFailIfAlreadyExists(boolean failIfAlreadyExists) {
6768
public boolean perform(AbstractBuild<?, ?> build, Launcher launcher, BuildListener listener) {
6869
VersionCreator versionCreator = new VersionCreator();
6970
versionCreator.setFailIfAlreadyExists(failIfAlreadyExists);
70-
return versionCreator.perform(build.getProject(), jiraVersion, jiraProjectKey, build, listener);
71+
versionCreator.setJiraVersion(jiraVersion);
72+
versionCreator.setJiraProjectKey(jiraProjectKey);
73+
return versionCreator.perform(build.getProject(), build, listener);
7174
}
7275

7376
@Override
7477
public BuildStepDescriptor<Publisher> getDescriptor() {
7578
return DESCRIPTOR;
7679
}
7780

81+
protected Object readResolve() {
82+
if (failIfAlreadyExists == null) {
83+
setFailIfAlreadyExists(true);
84+
}
85+
86+
return this;
87+
}
88+
7889
@Extension
7990
public static final DescriptorImpl DESCRIPTOR = new DescriptorImpl();
8091

@@ -103,5 +114,6 @@ public String getDisplayName() {
103114
public String getHelpFile() {
104115
return "/plugin/jira/help-version-create.html";
105116
}
117+
106118
}
107119
}

src/main/java/hudson/plugins/jira/JiraVersionCreatorBuilder.java

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ public class JiraVersionCreatorBuilder extends Builder implements SimpleBuildSte
2626

2727
private String jiraVersion;
2828
private String jiraProjectKey;
29-
private boolean failIfAlreadyExists = true;
29+
private Boolean failIfAlreadyExists = true;
3030

3131
@DataBoundConstructor
3232
public JiraVersionCreatorBuilder(String jiraVersion, String jiraProjectKey) {
@@ -59,6 +59,14 @@ public boolean isFailIfAlreadyExists() {
5959
return failIfAlreadyExists;
6060
}
6161

62+
protected Object readResolve() {
63+
if (failIfAlreadyExists == null) {
64+
setFailIfAlreadyExists(true);
65+
}
66+
67+
return this;
68+
}
69+
6270
@DataBoundSetter
6371
public void setFailIfAlreadyExists(boolean failIfAlreadyExists) {
6472
this.failIfAlreadyExists = failIfAlreadyExists;
@@ -68,7 +76,9 @@ public void setFailIfAlreadyExists(boolean failIfAlreadyExists) {
6876
public void perform(Run<?, ?> run, EnvVars env, TaskListener listener) {
6977
VersionCreator versionCreator = new VersionCreator();
7078
versionCreator.setFailIfAlreadyExists(failIfAlreadyExists);
71-
versionCreator.perform(run.getParent(), jiraVersion, jiraProjectKey, run, listener);
79+
versionCreator.setJiraVersion(jiraVersion);
80+
versionCreator.setJiraProjectKey(jiraProjectKey);
81+
versionCreator.perform(run.getParent(), run, listener);
7282
}
7383

7484
@Override

src/main/java/hudson/plugins/jira/VersionCreator.java

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
package hudson.plugins.jira;
22

3+
import java.util.Collections;
4+
import java.util.List;
5+
import java.util.Optional;
6+
import java.util.logging.Logger;
7+
38
import static org.apache.commons.lang.StringUtils.isEmpty;
49

510
import hudson.model.BuildListener;
@@ -8,11 +13,6 @@
813
import hudson.model.Run;
914
import hudson.model.TaskListener;
1015
import hudson.plugins.jira.extension.ExtendedVersion;
11-
import java.util.Collections;
12-
import java.util.List;
13-
import java.util.Optional;
14-
import java.util.logging.Logger;
15-
import org.kohsuke.stapler.DataBoundSetter;
1616

1717
/**
1818
* Performs an action which creates new Jira version.
@@ -23,17 +23,27 @@ class VersionCreator {
2323

2424
private boolean failIfAlreadyExists = true;
2525

26-
@DataBoundSetter
27-
public void setFailIfAlreadyExists(boolean failIfAlreadyExists) {
26+
private String jiraVersion;
27+
28+
private String jiraProjectKey;
29+
30+
public VersionCreator setFailIfAlreadyExists(boolean failIfAlreadyExists) {
2831
this.failIfAlreadyExists = failIfAlreadyExists;
32+
return this;
2933
}
3034

31-
public boolean isFailIfAlreadyExists() {
32-
return failIfAlreadyExists;
35+
public VersionCreator setJiraVersion(String jiraVersion) {
36+
this.jiraVersion = jiraVersion;
37+
return this;
38+
}
39+
40+
public VersionCreator setJiraProjectKey(String jiraProjectKey) {
41+
this.jiraProjectKey = jiraProjectKey;
42+
return this;
3343
}
3444

3545
protected boolean perform(
36-
Job<?, ?> project, String jiraVersion, String jiraProjectKey, Run<?, ?> build, TaskListener listener) {
46+
Job<?, ?> project, Run<?, ?> build, TaskListener listener) {
3747
String realVersion = null;
3848
String realProjectKey = null;
3949

@@ -75,9 +85,6 @@ protected boolean perform(
7585
listener.fatalError("Unable to add version %s to Jira project %s", realVersion, realProjectKey, e));
7686
}
7787

78-
if (listener instanceof BuildListener) {
79-
((BuildListener) listener).finished(Result.FAILURE);
80-
}
8188
return false;
8289
}
8390

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

Lines changed: 33 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,37 @@
11
package hudson.plugins.jira;
22

3+
import java.io.IOException;
4+
import java.io.PrintStream;
5+
import java.util.Arrays;
6+
37
import static org.hamcrest.MatcherAssert.assertThat;
48
import static org.hamcrest.Matchers.is;
9+
import org.joda.time.DateTime;
10+
import org.junit.jupiter.api.BeforeEach;
11+
import org.junit.jupiter.api.Test;
12+
import org.junit.jupiter.api.extension.ExtendWith;
13+
import org.mockito.ArgumentCaptor;
514
import static org.mockito.ArgumentMatchers.any;
15+
import org.mockito.Captor;
16+
import org.mockito.Mock;
17+
import org.mockito.Mockito;
618
import static org.mockito.Mockito.doReturn;
719
import static org.mockito.Mockito.reset;
820
import static org.mockito.Mockito.spy;
921
import static org.mockito.Mockito.times;
1022
import static org.mockito.Mockito.verify;
1123
import static org.mockito.Mockito.when;
24+
import org.mockito.junit.jupiter.MockitoExtension;
25+
import org.mockito.stubbing.Answer;
1226

1327
import com.atlassian.jira.rest.client.api.RestClientException;
28+
1429
import hudson.EnvVars;
1530
import hudson.model.AbstractBuild;
1631
import hudson.model.AbstractProject;
1732
import hudson.model.BuildListener;
1833
import hudson.model.Result;
1934
import hudson.plugins.jira.extension.ExtendedVersion;
20-
import java.io.IOException;
21-
import java.io.PrintStream;
22-
import java.util.Arrays;
23-
import org.joda.time.DateTime;
24-
import org.junit.jupiter.api.BeforeEach;
25-
import org.junit.jupiter.api.Test;
26-
import org.junit.jupiter.api.extension.ExtendWith;
27-
import org.mockito.ArgumentCaptor;
28-
import org.mockito.Captor;
29-
import org.mockito.Mock;
30-
import org.mockito.Mockito;
31-
import org.mockito.junit.jupiter.MockitoExtension;
32-
import org.mockito.stubbing.Answer;
3335

3436
@ExtendWith(MockitoExtension.class)
3537
class VersionCreatorTest {
@@ -96,7 +98,9 @@ void callsJiraWithSpecifiedParameters() throws InterruptedException, IOException
9698

9799
// for new version, verify the addVersion method is called
98100
when(session.getVersions(JIRA_PRJ)).thenReturn(null);
99-
boolean result = versionCreator.perform(project, JIRA_VER, JIRA_PRJ, build, listener);
101+
versionCreator.setJiraProjectKey(JIRA_PRJ);
102+
versionCreator.setJiraVersion(JIRA_VER);
103+
boolean result = versionCreator.perform(project, build, listener);
100104
verify(session, times(1)).addVersion(versionCaptor.capture(), projectCaptor.capture());
101105
assertThat(projectCaptor.getValue(), is(JIRA_PRJ));
102106
assertThat(versionCaptor.getValue(), is(JIRA_VER));
@@ -106,7 +110,9 @@ void callsJiraWithSpecifiedParameters() throws InterruptedException, IOException
106110
// for existing version, verify the addVersion method is not called
107111
reset(session);
108112
when(session.getVersions(JIRA_PRJ)).thenReturn(Arrays.asList(existingVersion));
109-
result = versionCreator.perform(project, JIRA_VER, JIRA_PRJ, build, listener);
113+
versionCreator.setJiraProjectKey(JIRA_PRJ);
114+
versionCreator.setJiraVersion(JIRA_VER);
115+
result = versionCreator.perform(project, build, listener);
110116
verify(session, times(0)).addVersion(versionCaptor.capture(), projectCaptor.capture());
111117
verify(logger, times(1)).println(Messages.JiraVersionCreator_VersionExists(JIRA_VER, JIRA_PRJ));
112118
verify(listener).finished(Result.FAILURE);
@@ -120,7 +126,9 @@ void expandsEnvParameters() throws InterruptedException, IOException, RestClient
120126

121127
// for new version, verify the addVersion method is called
122128
when(session.getVersions(JIRA_PRJ)).thenReturn(null);
123-
boolean result = versionCreator.perform(project, JIRA_VER_PARAM, JIRA_PRJ_PARAM, build, listener);
129+
versionCreator.setJiraProjectKey(JIRA_PRJ_PARAM);
130+
versionCreator.setJiraVersion(JIRA_VER_PARAM);
131+
boolean result = versionCreator.perform(project, build, listener);
124132
verify(session, times(1)).addVersion(versionCaptor.capture(), projectCaptor.capture());
125133
assertThat(projectCaptor.getValue(), is(JIRA_PRJ));
126134
assertThat(versionCaptor.getValue(), is(JIRA_VER));
@@ -129,7 +137,9 @@ void expandsEnvParameters() throws InterruptedException, IOException, RestClient
129137
// for existing version, verify the addVersion method is called
130138
reset(session);
131139
when(session.getVersions(JIRA_PRJ)).thenReturn(Arrays.asList(existingVersion));
132-
result = versionCreator.perform(project, JIRA_VER_PARAM, JIRA_PRJ_PARAM, build, listener);
140+
versionCreator.setJiraProjectKey(JIRA_PRJ_PARAM);
141+
versionCreator.setJiraVersion(JIRA_VER_PARAM);
142+
result = versionCreator.perform(project, build, listener);
133143
verify(session, times(0)).addVersion(versionCaptor.capture(), projectCaptor.capture());
134144
verify(logger, times(1)).println(Messages.JiraVersionCreator_VersionExists(JIRA_VER, JIRA_PRJ));
135145
verify(listener).finished(Result.FAILURE);
@@ -143,8 +153,9 @@ void buildDidNotFailWhenVersionExists() throws IOException, InterruptedException
143153
new ExtendedVersion(null, ANY_ID, JIRA_VER, null, false, true, ANY_DATE, ANY_DATE);
144154
when(site.getSession(any())).thenReturn(session);
145155
when(session.getVersions(JIRA_PRJ)).thenReturn(Arrays.asList(releasedVersion));
146-
147-
versionCreator.perform(project, JIRA_VER_PARAM, JIRA_PRJ_PARAM, build, listener);
156+
versionCreator.setJiraProjectKey(JIRA_PRJ_PARAM);
157+
versionCreator.setJiraVersion(JIRA_VER_PARAM);
158+
versionCreator.perform(project, build, listener);
148159
verify(session, times(0)).addVersion(any(), any());
149160
}
150161

@@ -157,8 +168,9 @@ void buildDoesNotFailWhenVersionExistsAndFailIfAlreadyExistsIsFalse()
157168

158169
// Set failIfAlreadyExists to false
159170
versionCreator.setFailIfAlreadyExists(false);
160-
161-
boolean result = versionCreator.perform(project, JIRA_VER, JIRA_PRJ, build, listener);
171+
versionCreator.setJiraProjectKey(JIRA_PRJ);
172+
versionCreator.setJiraVersion(JIRA_VER);
173+
boolean result = versionCreator.perform(project, build, listener);
162174

163175
// Verify that addVersion is not called (because version already exists)
164176
verify(session, times(0)).addVersion(any(), any());

0 commit comments

Comments
 (0)