-
Bug
-
Resolution: Unresolved
-
Minor
-
Powered by SuggestiMate -
Blue Ocean - Candidates
I've created a jenkins plugin with a bunch of pipeline steps for use in either scripted or declarative pipelines. They show up in the regular Pipeline Syntax UI in Jenkins along with the Blue Ocean Pipeline editor.
In the Pipeline Syntax UI the default values appear in the form (due to the `default="foo"` in the jelly config.xml files) however in the Blue Ocean pipeline editor the forms are always blank.
Is this a known bug with Blue Ocean pipeline editor; or is there some alternative way to specify default values for the form in the plugin so that the pipeline editor can find them?
If you want to try out the plugin yourself there's a snapshot plugin here:
https://github.com/fabric8-jenkins/fabric8-declarative-pipeline-step-functions-plugin#building
[JENKINS-48095] pipeline steps from a jenkins plugin do not show any default values in the form
Sure. I'll go ahead and try to repro this within the next couple days after I clear an in-progress task. jstrachan I'll reach out to if I run into any problems with repo.
Testing Notes:
Once implemented, it seems the ideal way to go about testing this is at the unit level (or, to say it another way, "not in the Selenium tests").
jstrachan I did some investigation and there are two issues here, although perhaps we can move it forward with some discussion:
(A) The editor fetches metadata about all steps via REST API call and here is the payload returned for the "mavenPipeline" step:
{ "_class": "io.blueocean.rest.pipeline.editor.ExportedPipelineStep", "displayName": "Full CI / CD pipeline for maven projects", "hasSingleRequiredParameter": true, "help": null, "parameters": [{ "capitalizedName": "GitCloneUrl", "collectionTypes": [], "descriptorUrl": null, "help": null, "isDeprecated": false, "isRequired": true, "name": "gitCloneUrl", "type": "java.lang.String" }, { "capitalizedName": "ArtifactExtensionToWaitFor", "collectionTypes": [], "descriptorUrl": null, "help": null, "isDeprecated": false, "isRequired": false, "name": "artifactExtensionToWaitFor", "type": "java.lang.String" }, { "capitalizedName": "ArtifactIdToWaitFor", "collectionTypes": [], "descriptorUrl": null, "help": null, "isDeprecated": false, "isRequired": false, "name": "artifactIdToWaitFor", "type": "java.lang.String" }, { "capitalizedName": "ContainerName", "collectionTypes": [], "descriptorUrl": null, "help": null, "isDeprecated": false, "isRequired": false, "name": "containerName", "type": "java.lang.String" }, { "capitalizedName": "DockerOrganisation", "collectionTypes": [], "descriptorUrl": null, "help": null, "isDeprecated": false, "isRequired": false, "name": "dockerOrganisation", "type": "java.lang.String" }, { "capitalizedName": "ExtraImagesToStage", "collectionTypes": [], "descriptorUrl": null, "help": null, "isDeprecated": false, "isRequired": false, "name": "extraImagesToStage", "type": "java.util.List" }, { "capitalizedName": "ExtraImagesToTag", "collectionTypes": [], "descriptorUrl": null, "help": null, "isDeprecated": false, "isRequired": false, "name": "extraImagesToTag", "type": "java.util.List" }, { "capitalizedName": "ExtraSetVersionArgs", "collectionTypes": [], "descriptorUrl": null, "help": null, "isDeprecated": false, "isRequired": false, "name": "extraSetVersionArgs", "type": "java.lang.String" }, { "capitalizedName": "GroupId", "collectionTypes": [], "descriptorUrl": null, "help": null, "isDeprecated": false, "isRequired": false, "name": "groupId", "type": "java.lang.String" }, { "capitalizedName": "PromoteDockerImages", "collectionTypes": [], "descriptorUrl": null, "help": null, "isDeprecated": false, "isRequired": false, "name": "promoteDockerImages", "type": "java.util.List" }, { "capitalizedName": "PromoteToDockerRegistry", "collectionTypes": [], "descriptorUrl": null, "help": null, "isDeprecated": false, "isRequired": false, "name": "promoteToDockerRegistry", "type": "java.lang.String" }, { "capitalizedName": "RepositoryToWaitFor", "collectionTypes": [], "descriptorUrl": null, "help": null, "isDeprecated": false, "isRequired": false, "name": "repositoryToWaitFor", "type": "java.lang.String" }, { "capitalizedName": "UseGitTagForNextVersion", "collectionTypes": [], "descriptorUrl": null, "help": null, "isDeprecated": false, "isRequired": false, "name": "useGitTagForNextVersion", "type": "boolean" } ], "symbol": null, "type": "io.fabric8.pipeline.steps.MavenPipelineStep", "functionName": "mavenPipeline", "descriptorUrl": "descriptorByName/io.fabric8.pipeline.steps.MavenPipelineStep", "isBlockContainer": false, "providedContext": [], "requiredContext": [ "hudson.FilePath", "hudson.model.TaskListener" ] },
Our model exposes the parameters and their types but nothing around their default values. Certainly it would be possible to expose that and smarten up the UI to populate default values when the step is added.
(B) Looking deeper, our model wraps the DescribableModel and DescribableParameter classes, although I don't see anything in there that would hold default values. I noticed that MavenPipeline is using the @Step and @Argument annotations, and I'm a little unclear on how that data flows into the above model types. Unfortunately this area of the model isn't something I've worked with before so I'm unsure how to proceed.
If you're knowledgeable about these parts, perhaps you could steer me in the right direction. Otherwise I'll solicit michaelneale for some input.
cliffmeyers I totally did not fully read the description of the ticket. Basically at the moment the steps put it in the jelly for classic UI, so I don't think the "data" that is locked up in them will be available for the pipeline editor in blue ocean.
So this changes the nature of the ticket, basically we need to find a way to include the default values in the code, vs the UI, and surface that via the API. this is a VERY different problem, worth thinking about, but may be more effort, as it then required the plugins that provide the steps to be modified to include the default values vs Jelly.
Is this a tractable problem? it now seems much bigger than it was when we started... (and I don't think we can programmatically reliably dig things out of jelly...)
I did wonder if the Blue Ocean editor was not using Jelly - which is fine - I guess we just need to figure out some way that a Step can expose more metadata about itself (e.g. display names, default values, possibly validation/editor CSS styles like number/positive/required and the like).
This could be a Java API or static metadata (xml / json / yaml / something else) as for now the default values are not dynamic; though I guess a Java API of sorts might be cleaner longer term for more complex processing of defaults. (e.g. if one property is a github organisation name, then the combo box of repository names may be dynamic etc)
cliffmeyers sorry those steps are confusing it was an experiment to create a simple POJO model for writing steps such that developers don't need to grok any of the ninja jenkins stuff around groovy / CPS / Steps et al.
What actually happens is a maven plugin generates the Step class. Here's the generated step class for the mavenPipeline step: https://gist.github.com/jstrachan/96b116ce233249e9bea8dbce93343b24
so its regular Step stuff - so we can hack that code to do whatever you need. Is there an example anywhere of a Step written to provide more metadata for Blue Ocean editor that I can copy/noodle?
jstrachan cliffmeyers I am not sure we can solve this within the original scope here... basically we need to find a way to expose this meta data, and then all the steps need to be updated to have the defaults in their classes (vs in jelly, no small job)
jstrachan were there specific steps you were thinking of where this is most problematic, or were you looking at making new steps, or libraries that could do with defaults?
After hitting a limitation in the simple POJO model (java steps can't easily invoke other steps like sh()) I'm now focussing on a single 'pseudo step' , mavenFlow defined via groovy: https://github.com/fabric8-jenkins/fabric8-pipelines-plugin/blob/master/src/main/resources/dsl/mavenFlow.groovy
then exposed using a GlobalVariable: https://github.com/fabric8-jenkins/fabric8-pipelines-plugin/blob/master/src/main/java/org/jenkinsci/plugins/fabric8/dsl/MavenFlowDSL.java#L26
so maybe that @Extension class could be the pseudo step we use to try expose metadata into. Though now things are slightly different in right now this pseudo step doesn't even appear in blue ocean at all as its not a Step per say but a global variable.
So I wonder if we need to raise a separate issue? We've kinda 2 issues now:
- how to add extra metadata to DescribableModel for things like displayName, defaultValue, required, number & other validation/CSS type stuff
- how to expose a DescribableModel at all for 'groovy steps' which are not Java Step classes but DSL functions exposed as global variables like example https://github.com/jenkinsci/simple-build-for-pipeline-plugin/
I've just raised https://issues.jenkins-ci.org/browse/JENKINS-48205 for the latter; we should maybe try tackle that one first - then try figure out how to add more metadata/info to the DescribableModel for this issue?
cliffmeyers mind having a crack at this one?