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
[JENKINS-42091] Add JSON steps #22
Conversation
Seems that only Cloudbees setup has no problem with current pom.xml and the createOnlineSlave statement of JenkinsRules. |
} else if (f.isDirectory()) { | ||
logger.print("warning: "); | ||
logger.print(f.getRemote()); | ||
logger.println(" is a directory, omitting from properties gathering"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
properties gathering?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
copy / paste error. Noted
} | ||
|
||
@Extension | ||
public static class JSONWhiteLister extends Whitelist { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's better to contribute this whitelisting to script-security-plugin
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This whitelist only permit the basic isArray and size methods needed to navigate json object in pipeline. The json implementation I decide to use (instead GJSON or similar) is because is shipped by default with Jenkins.
In script-security-plugin I see only JVM or groovy library packages so is the right place for net.sf.json? Question because the step readMavenPOM have a more permissive whitelist. Are you moving all custom whitelist to that plugin?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
net.sf.json
is part of Jenkins core, that's why they belong there. The whitelisting of the maven parts in this plugin is because it is this plugin that adds the dependency.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok I will create a PR to that plugin refering this discussion.
PrintStream logger = listener.getLogger(); | ||
JSON json = new JSONObject(); | ||
|
||
JsonSlurper jsonSlurper = new JsonSlurper(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why are you using JsonSlurper
? Normally you would just call JSONObject.fromObject(jsonString)
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
because I do not know if json is a json array or a json object.
By default I setup json as empty json object {}
than JsonSlurper instantiates the correct JSONObject or JSONArray.
JsonSluper provides a default jsonConfig and parse from inputstream.
content.put("tags", tags); | ||
File file = temp.newFile(); | ||
try (FileWriter f = new FileWriter(file)) { | ||
new JsonBuilder(content).writeTo(f); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
content.write(f)
no need for JsonBuilder
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Noted
Test will not pass until this pr is accepted and released |
Since the custom If you agree I could proceed to implement writeJSON step |
Regarding the pom file problems; have you setup your settings.xml as described here? |
No but in the pom.xml there are both repository and pluginrepository so the same of settings. |
I've add writeJSON step, remove JsonSlurper as requested. If you agree I could also make a single squash commit |
Enable i18n for UI messages. Move validation checks to StepExecution instead on the step definition.
script-security-plugin #109 was released in script-security-1.27 so you can probably bump the dependency to make the tests pass If you want to tests those bits. |
if (step.getJson() == null) { | ||
throw new IllegalArgumentException(Messages.WriteJSONStepExecution_missingJSON(step.getDescriptor().getFunctionName())); | ||
} | ||
if (StringUtils.isBlank(step.getFile())) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since you do require both arguments to be set they should both be in the @DataboundConstructor
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
right, I miss due I've add json later.
/* | ||
* The MIT License (MIT) | ||
* | ||
* Copyright (c) 2016 CloudBees Inc. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you work for CloudBees? If not you shouldn't claim their copyright.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I didn't comment on the copyright of the other step's files since they where about 90% copy & paste so I deemed that to be correct.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I do not work for CloudBees so what I could wrote? Should I have to remove Copyright row?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Either you own the copyright or the company you work for.
<?jelly escape-by-default='true'?> | ||
<j:jelly xmlns:j="jelly:core" xmlns:f="/lib/form"> | ||
<f:block> | ||
<p>This is a special step. No snippet generation available. See inline help for more information.</p> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you can make the snippet generator work here since you are using standard data bound fields.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this means that I can remove both config.jelly and help.html files?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, you should change config.jelly to contain a proper config page for the databound fields. And change the help file to more explain to a human what the step actually does.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Snippet generator is not able to handle correctly complex type like net.sf.json.JSON (interface) in data bound fields. So I leave the same as maven step does where the help explain how to use by example.
Instead readJSON config.jelly was changed to support snippet generator also with optional fields. The same could be do for readProperties and readManifest.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, sorry, I was stupid.
WorkflowJob p = j.jenkins.createProject(WorkflowJob.class, "p"); | ||
p.setDefinition(new CpsFlowDefinition( | ||
"node {\n" + | ||
" def json = readJSON file: '" + separatorsToSystemEscaped(file.getAbsolutePath()) + "'\n" + |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we need to test that non system escaped separators works. Java should translate some/path
to some\path
on windows without us needing to do anything. If that doesn't work then we need to fix that in the step, the users shouldn't have to do that.
It's one of the main points of this plugin to be platform agnostic.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok, consider that all yaml, properties, maven, manifest (where I copy test methodology) use same escape function. I will change it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes I was a bit out of touch when I approved those changes. I think the problem they solved was that on windows the path would be 'some\path' when calling file.getAbsolutePath()
and that caused issues.
What I should have argued in that case was to make sure the format was always `some/path'.
So keep it like it is in here and I'll fix it in another PR at a later date.
Move pipeline-security version to 1.27. Mark fields of writeJSON step as required. Reduce use of real file in test case.
Fix copyright header. Let me squash commits if pull request could be considered approved by you |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing config.jelly with data bindings fir writeJSON
The Snippet generator does not handle correctly any FormException("message", "fieldName"), the only checked exception of newInstance(StaplerRequest req, JSONObject formData). I would notice that in Jenkins 1.x any exception server side is showed in the snippet text area as trackstrace instead in Jenkins 2.x no error is shown at all. I would expect that form exception message was placed near the form exception field. |
Ah, yes. I had a temporary lapse in stupidness, sorry :) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems to suffer from more copy paste problems.
FilePath f = ws.child(step.getFile()); | ||
if (f.exists() && !f.isDirectory()) { | ||
try (InputStream is = f.read()) { | ||
json = JSONSerializer.toJSON(IOUtils.toString(is)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can return the object here directly, since you don't seem to try to do any override (even if your help text below at times indicates you do)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I could but personally I do not like too much exit point, when is possible I prefer this way
SonarQube open a violation when >= 5 return in a method
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK, it's just that this behaves a bit differently then from what is stated, if both file and text is set (which is blocked in newInstance
but can happen by other means) it would read the file and then overwrite the val with what is in text. Nothing wrong with that, just that the code doesn't fully reflect what is expected.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If both fields are set an IllegalArgumentException will be throw at the begin of this method
} | ||
} | ||
if (!isBlank(step.getText())) { | ||
json = JSONSerializer.toJSON(step.getText().trim()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here
if (path.isDirectory()) { | ||
throw new FileNotFoundException(Messages.JSONStepExecution_fileIsDirectory(path.getRemote())); | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps a nice thing to do would be to warn if you are overwriting an existing file.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Typicall scenario of writeJSON is read json file and manipulate its data, add other data and update the same file (like maven step does).
For example autoincrement version: beta3 -> beta4 of a package.json
If I put a warn it's very annoing in console log.
I could add a boolean property override to step, but this could be a show stopper in case devops change the pipeline and/or developer would provide a base JSON file to be enhance with writeJSON step, etc etc.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok
~ SOFTWARE. | ||
--> | ||
<p> | ||
Path to a file in the workspace to read the properties from. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Properties?
--> | ||
<p> | ||
Path to a file in the workspace to read the properties from. | ||
<em>These are added to the resulting map after the defaults and so will overwrite any key/value pairs already present.</em> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
map?
~ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
~ SOFTWARE. | ||
--> | ||
<p>A JSON object data, written as name/value pairs. Values must be |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
JSON data is normally structured and I don't see any indications of you limiting that structure to be name/value pairs.
Shouldn't just "A string containing JSON formatted data" or similar be enough?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes
<p> | ||
<strong>Example:</strong><br/> | ||
<code><pre> | ||
def props = readJSON file: 'dir/input.json', text: '{ other: Override }' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In help-text.html
and help-file.html
you state that file
or text
can be used, not both at the same time. Yet this example uses both.
Also I don't think the text will parse since Override
isn't surrounded by quotes.
The use of Override is also a bit confusing, since the other steps in this plugin that uses it to exeplify how to override data in the file. So it's better to use some other string to not further confuse the user.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the example is wrong, too many copy/paste in late hours
<?jelly escape-by-default='true'?> | ||
<j:jelly xmlns:j="jelly:core" xmlns:f="/lib/form"> | ||
<f:block> | ||
<p>This is a special step. No snippet generation available. See inline help for more information.</p> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, sorry, I was stupid.
The first implementation add a step to read JSON from text or file.
It adds also unit test but with the actual pom.xml there is no way that is work on any OS (Windows 7/MacOS/Linux CentoOS). I have test and write tests with an updated pom.xml