Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add setters to the StashNotifier.DescriptorImpl class #201

Merged
merged 8 commits into from Apr 1, 2019
Merged

Add setters to the StashNotifier.DescriptorImpl class #201

merged 8 commits into from Apr 1, 2019

Conversation

alexchiri
Copy link
Contributor

In order to be able to configure this plugin using the Configuration As Code plugin, the StashNotifier.DescriptorImpl needs to have setters or public fields. Using YAML to configure Jenkins is pretty nice and this would enable this to work with this plugin as well.

@scaytrase
Copy link
Member

All or most of this properties could be set while construction. While should we allow dynamically change the settings during lifecycle. Isn't it enough to pass YAML configuration to constructor in some way?

@alexchiri
Copy link
Contributor Author

@scaytrase Unfortunately, at least as far as I can see in the plugin implementation, it works by discovering fields and setters to determine what properties can be set from the YAML. They have some guidelines for plugin developers here. There can be some custom implementation be done on the configuration-as-code plugin side to handle different ways of configuring plugins, but I felt since stash notifier has quite a basic config, that would be a bit of an overkill.

Copy link
Collaborator

@darxriggs darxriggs left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please also use data-binding via request.bindJson(this, json) inside configure(...).
See Step 5 in https://github.com/jenkinsci/configuration-as-code-plugin/blob/configuration-as-code-1.8/docs/PLUGINS.md.

There should also be two tests - one for configuring Jenkins via YAML and one for exporting a configured Jenkins to YAML.
See How to test? in https://github.com/jenkinsci/configuration-as-code-plugin/blob/configuration-as-code-1.8/docs/PLUGINS.md.

Note: I am not a maintainer of this plugin. But I already have migrated some other plugins to be compatible with JCasC.

@@ -611,34 +611,66 @@ public String getStashRootUrl() {
}
}

public void setStashRootUrl(String stashRootUrl) {
this.stashRootUrl = stashRootUrl;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use correct indentation for all new code.
Here and in other places spaces & tabs are currently mixed up.

@@ -611,34 +611,66 @@ public String getStashRootUrl() {
}
}

public void setStashRootUrl(String stashRootUrl) {
Copy link
Collaborator

@darxriggs darxriggs Mar 26, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@alexchiri
Copy link
Contributor Author

@darxriggs Thank you for the feedback and review. Will work further on the PR soon.

@scaytrase
Copy link
Member

@alexchiri as soon I have no views on architectural future of this plugin version (only some thoughts on 2.x version), I think we can accept this PR after suggested impovements

… to match JCasC plugin.

Add JCasC plugin test dependency to be able to test config as code functionality.
Add matrix-project plugin as a test dependency, since it is required in tests by the JenkinsRule.
Fix spacing and add @DataBoundSetter annotations to setters.
Rewrite configure method and test to use req.bindJSON.
Add tests to verify that configure using yaml and export to yaml work.
Copy link
Collaborator

@darxriggs darxriggs left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the quick update.
I had another look at the new changes. It already looks pretty good.
See my comments for some required changes.

<relativePath />
</parent>
<packaging>hpi</packaging>
<properties>
<revision>1.18</revision>
<changelist>-SNAPSHOT</changelist>
<!-- Baseline Jenkins version you use to build the plugin. Users must have this version or newer to run. -->
<jenkins.version>1.625.3</jenkins.version>
<jenkins.version>2.60.3</jenkins.version>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suggest to reduce it to the following snippet:

<properties>
    <revision>1.18</revision>
    <changelist>-SNAPSHOT</changelist>
    <jenkins.version>2.60.3</jenkins.version>
    <java.level>8</java.level>
</properties>

The rest is already covered by the parent pom nowadays.
(This can be verified with mvn help:effective-pom.)

pom.xml Outdated
@@ -3,20 +3,20 @@
<parent>
<groupId>org.jenkins-ci.plugins</groupId>
<artifactId>plugin</artifactId>
<version>3.10</version>
<version>3.36</version>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you like, there is already 3.40 - see https://github.com/jenkinsci/plugin-pom/releases.

public String getProjectKey() {
return projectKey;
}

public void setProjectKey(String projectKey) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems you missed a @DataBoundSetter here.

@@ -637,34 +626,73 @@ public String getStashRootUrl() {
}
}

@DataBoundSetter
public void setStashRootUrl(String stashRootUrl) {
this.stashRootUrl = stashRootUrl;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For Strings like this one I suggest to use something like Apache Commons Lang StringUtils::trimToNull or Jenkins Util::fixEmptyAndTrim. This improves user experience by better handling strings with leading/trailing spaces.

public String getProjectKey() {
return projectKey;
}

public void setProjectKey(String projectKey) {
this.projectKey = projectKey;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See comment about setStashRootUrl() on trimming.

stashRootUrl = formData.getString("stashRootUrl");
ignoreUnverifiedSsl = formData.getBoolean("ignoreUnverifiedSsl");
includeBuildNumberInKey = formData.getBoolean("includeBuildNumberInKey");
this.stashRootUrl = null;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suggest to keep the order consistent for easier reading/comparison:

  • field declarations in StashNotifier (maybe)
  • setters/getters in StashNotifier (maybe)
  • default values (lines 751-758) in StashNotifier::configure
  • assertThat calls (lines 27-33) in ConfigAsCodeTest::should_support_jcasc_from_yaml
  • setter calls (lines 40-47) in ConfigAsCodeTest::should_support_jcasc_to_yaml

includeBuildNumberInKey: true
prependParentProjectKey: true
projectKey: "JEN"
stashRootUrl: "https://bitbucket.com"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Even if it's only an example value, I suggest to use something like https://my.company.intranet/bitbucket. This more clearly states that this plugin is about "Bitbucket Server" and not "Bitbucket Cloud". Also see #225 for a cleanup regarding this.

assertThat(desc.isIncludeBuildNumberInKey(), is(true));
assertThat(desc.isPrependParentProjectKey(), is(true));
assertThat(desc.isApplicable(AbstractProject.class), is(true));
verify(request).bindJSON(desc, json);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The question is, if just verifying a bindJSON call is sufficient for you.
To be really sure, values should still be verified (using a StaplerRequest implementation/mock that implements bindJSON if possible). Otherwise if you for example missed a setter for a field, this would not be caught here and JCasC and UI based configuration would be broken.

Update parent version to latest.
Remove Maven properties that are inherited anyway from parent pom.
Order plugin attributes in the same way everywhere.
Trim String attributes.
Add forgotten @DataBoundSetter.
Update example value for stashRootUrl.
Implement more rigorous unit test for configure method.
@alexchiri
Copy link
Contributor Author

alexchiri commented Mar 30, 2019

Thanks again for the detailed feedback and advice on this @darxriggs. Learned some things and feel I'm getting better at it. 😊

Please let me know if anything else sticks out!

public void setIncludeBuildNumberInKey(boolean includeBuildNumberInKey) {
this.includeBuildNumberInKey = includeBuildNumberInKey;
}

public String getProjectKey() {
return projectKey;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You moved the field projectKey before the field stashRootUrl but the setter/getter order doesn't match this. But it doesn't really matter.

@@ -74,20 +77,30 @@ public void testConfigure() throws Descriptor.FormException {
//given
doNothing().when(desc).save();

ServletContext servletContext = PowerMockito.mock(ServletContext.class);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If possible try not to use PowerMockito but only Mockito. You can have a look in the internet why to avoid PowerMock.

PowerMockito is mainly required to mock constructors and static methods. That's often the case for legacy code that was written without testability in mind. At first sight that's not the case here.

private boolean ignoreUnverifiedSsl;
private boolean includeBuildNumberInKey;
private String projectKey;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@scaytrase I am wondring why projectKey is a field in StashNotifier.DescriptorImpl. It is not visible in the UI and was never part of global.jelly. Shouldn't it be removed from StashNotifier.DescriptorImpl and only be a field in StashNotifier?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure for it really, may be a copy-paste coincident. We can try to remove it, cannot image when project key should be declared on global level

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if it's non blocking for this PR we can try it as a separate change

@darxriggs
Copy link
Collaborator

Apart from the projectKey field issue, which is to be decided by @scaytrase, this pull request now looks good to me.
I suggest to squash all the commits into one before merging.

@scaytrase scaytrase self-requested a review April 1, 2019 19:25
@scaytrase scaytrase merged commit 38063fe into jenkinsci:release/1.x Apr 1, 2019
@scaytrase
Copy link
Member

scaytrase commented Apr 2, 2019

thank you @alexchiri ! (and @darxriggs for comments, for sure)

Copy link
Contributor

@proski proski left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It was surprising to find this large commit in the commit history with a description that makes it sound like a minor change.

@@ -143,6 +135,18 @@
<version>2.0</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.jenkins-ci.plugins</groupId>
<artifactId>matrix-project</artifactId>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why was the matrix project dependency added? The commit description makes no mention of it. I don't see the matrix plugin being used in the code. I see that it's only for testing, but I still don't see those new tests.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a test scope dependency required by the new tests.

Copy link
Contributor Author

@alexchiri alexchiri Apr 3, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I missed to add that. I added the Matrix project test dependency because the JenkinsRule requires it and it has been removed from core since 1.561. I added the JenkinsRule in the test that verifies the configuration as code setup, according to JCasC documentation. (import and export yaml). (this is the issue where I found more information about the NoClassDefFoundError I got while using the JenkinsRule: https://issues.jenkins-ci.org/browse/JENKINS-27826)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the explanation!

import hudson.FilePath;
import hudson.Launcher;
import hudson.ProxyConfiguration;
import hudson.*;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think wildcards make the code better. There are plenty of tools to keep an up-to-date list of used imports.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For me, using wildcard imports or not is a project decision. There are as always advantages and disadvantages. And nowadays tools should be able to handle both.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree on all counts, I just wanted to make sure it was an intentional change and not somebody's sloppiness that everybody missed.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not in general a Java developer and I adopted (ocassionaly, huh) this plugin with worse code conventions than it have today, but there is still no CSC strictly defined here today. We can adopt one, I think, if it make life easier.

@darxriggs
Copy link
Collaborator

darxriggs commented Apr 20, 2019

@scaytrase I am looking forward for this to be released. :-)

@darxriggs
Copy link
Collaborator

Just as reference, there is also JENKINS-56899 tracking this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants