Jenkins pipeline from YAML file - jenkins

Jenkins declarative pipeline is too powerful for us, often users can abuse it. We are thinking to use an opinionated YAML to describe CI/CD pipeline. And it seems there are two choices.
Write a plugin and consume YAML and dynamically create stage / steps.
Write a plugin to convert a YAML to Jenkins pipeline.
I am not expert on Jenkins, so I hope some expert can give some guidance and maybe an example.

using official plugin pipeline-as-yaml, but it has a fixed grammar.
using or customization wolox-ci
create your own shared libaray. However, they are easy from beginning but full grammer design is required when used widely. Here is a psudo code based on curry.
// create a file named yamlCompiler.groovy in shared library,
def call(str){
def rawMap = readYaml(text: str)
// consume yaml and get a lambda function
return {
stage{
steps.each{it ->
it."$type"(it)
}
}
}
}
Use yamlCompiler in your jenkinsfile code block.
#Library('your libs name')
def str =
'''
steps:
- type: sh
script: ls -la
- type: echo
message: xxx
'''
Closure closure = yamlCompiler(str)
closure.call()

I'm looking for a similar solution. We run hardened predefined pipelines for every project, but still want to allow dev teams to customise certain steps within the process —without allowing them the full power of a Jenkinsfile.
I'm also exploring the possibility of an —in your words— "opinionated YAML".
I've so far only found one example of such an implementation: Wolox-CI supports their own pre-defined build steps via YAML. You'll be able to see the steps they support here.
I'm thinking of parsing the YAML using Snake YAML. Here's an SO answer with an example on how to do it.

Two solutions:
create a shared library to abstract the actual pipeline and provide to your users some guidance on how to setup a shared library and a Jenkinsfile sample. Here is an example of embeded pipeline https://github.com/SAP/jenkins-library/blob/master/vars/piperPipeline.groovy
use another tool like https://drone.io/
If you're not an expert and don't want/have the time to become one, the second solution might be the best one.

Really? Is the only difference here when the plugin is executed?:
Write a plugin and consume YAML and dynamically create stage / steps.
Write a plugin to convert a YAML to Jenkins pipeline.
Forgive me, because I may be a little hardened, but abstracting a layer for the dynamic creation of a declarative, or scripted, Jenkinsfile written in the simple groovy lang syntax so that it can be pretty-printed in yml prevents users from updating your yml exactly how? It seems to me your abstraction only adds to the complexity with which you wish to implement usability.
One, all the current yml plugins for Jenkins do exactly that. Two, they don't actually have the full breadth of "features" (yes, I'm using that term loosely here) accessible by implementing the groovy/(java) classes already available in the Jenkins domain (referencing the DSL). Two solutions exist right now for this, and I've investigated both, and implemented both, extensively. One is wolox-ci, which is the better of the two, and the other is Pipeline-as-YAML. In my opinion, it's easy to use, but both lack the full breadth of implementation features simply using groovy provides. So why force it? Simply so your users can have a pretty-printed yml file, and not have to be concerned with simple syntax, which you claim hardens your infrastructure-as-code backend so that the same users can't screw it up? Sorry, I'm calling bull pucky on that assertion. What's to stop anyone from totally screwing up your builds by pushing a change to the yml file which breaks the integration with groovy, or worse, completely changes an algorithm you worked hard to customize?
Sorry, I just don't get it. Sure, making something more human readable is always a good thing. Doing it because of the reasons you've stipulated makes no sense, though. Also, unless you have a super simple defined algorithm in your CI/CD process, without any non-continuous-passing-style transform methods being implemented, then using the current iterations of the yml-as-Jenkinsfile-templates plugins is probably not the way you want to go.
Now, you could write your own plugin to do this, but what's the technical debt on that, versus just learning the groovy syntax? Also, it still doesn't prevent users from making code changes to your build infrastructure, then integrating those changes in a simple yml file.

Related

Add condition to transition using script runner

I am using the scriptrunner plugin for Jira.
Is it possible to add a condition to a transition using scriptrunner?
Currently, my condition is in a script which I have manually added to the workflow.
But I was wondering if there is a way to do it automatically?
I was looking through documentation on: https://docs.atlassian.com/
I came across this method:
replaceConditionInTransition which is a method of WorkFlowManager.
But I'm unsure on how to use this.
Any help would be appreciated.
Conditions as any another scripts can be added from file system. You can store scripts in any VCS (bitbucket, github, gitlab, etc) and automatically deploy them to Jira server file system through any CI/CD system (teamcity, jenkins, bamboo, gitlab, etc).
So, as result process will be looks like. 1. commit changes in you script to vcs 2. wait a bit for auto deploy (e.g. triggered by commit) 3. done. As additional you can write any script/service/etc for commit these changes automatically if needed.
Also look at script roots it's helpful way which allows reuse any of script fragments through helpers classes.
It's rather conceptual answer basically because implementation is depends on environment, but I hope that you get at least one more point of view to solve this task.
I think that using the Java API to modify Jira workflows is pretty tough. You could dig around in the workflow editor to see how conditions are added there. Remember that you have to do this in a draft workflow and then publish it, which takes some time in large projects
I like the idea of replacing a script file as easier, if it can be done when no issues are transitioning

How to create a Jenkins job config.xml?

When I create a jenkins job via the API, I use a previous job's config.xml, make my modifications and then make the POST call to create the job.
My questions is, is there a way to generate this programmatically? I.e. is there a structure of a config.xml, what XML entities it should have, what values, etc so I can write a small module to generate one and send it to the jenkins API call?
I don't think there's any mandatory XML entities. Submitting an empty structure should result in a job that has default values for all settings.
What you want to do is exactly what's done by the Jenkins Job Builder. It provides a YAML-based framework for creating Job configuration XML files and submitting them to Jenkins. It's a common alternative to the Job DSL plugin. I wouldn't recommend to re-implement such a solution yourself -- handling all the plugin-specific XML configuration parts will be a nightmare.
We create our jobs using Job DSL plugin. You can try the playground http://job-dsl.herokuapp.com/.
At first, it seems that it is hard to learn, but after the first seed job, it is much better.
When we started writing our scripts we were afraid that there will not be suitable API methods for our needs. It turned out that we had one such case, which was solved using the configure block.
Get started guide here.

How to skip already-run steps in kubeflow pipeline?

I'm building an ML pipeline in Kubeflow and I have a question. Is there anything out of the box that allows me to configure my pipeline, such that a step is not rerun if its output exists? I've thought of ways to do this manually (either checking for existing outputs as I'm compiling the pipeline, or having an initial step that returns a list of steps to run, or manually configuring which steps to run as an input parameter) but I cannot find a native way of handling this.
The common use case for me would be to rerun the model step without rerunning any pre-processing of the data; but without having to have a specific "model development" pipeline that would differ from the more general prod one that would include the data pre-processing step. Or perhaps I'm iterating on an evaluation phase and I don't even need retraining but I would still like to use the same pipeline. Right now, colleagues are using several pipelines, that each start at a different step, to work around this.
I'm coming at it from a map-reduce perspective where this is trivial - the framework automatically detects which outputs are present and doesn't rebuild them as default, but easily gives you the option to rebuild some or all of them. Maybe this is biasing my way of working with kubeflow?
Any help appreciated!
Ok, I thought I'd put on here what I've found to solve this.
As of September 2019, this is not a feature of Kubeflow (according to people working on it), but there is a caching feature in the works that should not rerun any steps whose outputs exist.
In the meantime I manually implemented it, via a pipelineParam 'startingStep' from which everything needs to be rerun. Something like this:
with dsl.Condition(first_step_to_run == "prep"):
create_ops(StartingStep.prep)
with dsl.Condition(first_step_to_run == "train"):
create_ops(StartingStep.train)
with dsl.Condition(first_step_to_run == "evaluate"):
create_ops(StartingStep.evaluate)
with a create_ops method that understands what order to create steps in and chains them appropriately (we actually have seven steps so I really wanted to avoid copy/pasting all over).

Jenkins "Job Template" from SCM?

Is it possible to configure a "Job Template" (this is a particular kind of Jenkins item) with the groovy template coming from SCM as is possible in other job types? I don't see it as an option in ours, but perhaps there is another plugin required for this?
There is not such an option. The closest equivalent would be to create a job template using the Pipeline transformer, where the inline script is merely boilerplate running a load step to load the “real” code. (An existing RFE CJP-1718 suggests removing the need for this boilerplate; if that would be useful to you, file a support ticket mentioning it.)

Can you put resources in Jenkins Workflow Global Library

I am trying out the Jenkins Workflow plugin (https://github.com/jenkinsci/workflow-plugin) and using the Workflow Global Library (https://github.com/jenkinsci/workflow-plugin/tree/master/cps-global-lib) that comes with it.
I wanted to embed some script calls in my shared functions (bash/python). The obvious way to do this seems to be by using sh """...""". However this leads to some escaping being required ($ has to be escaped). Also its a bit messy to develop a script inside string quotes.
Is there a way to access resource files (e.g. a .sh or .py file) stored in the Global Library during a workflow execution?
So that I can do something like
sh getScript("script.sh")
''' syntax might be more helpful, since it reduces the need to escape. There are other Groovy syntaxes that are even better for long blocks, with various tradeoffs on the escape character.
But yes it would be helpful to be able to reference a static resource in the “classpath”. Feel free to file an RFE for this.

Resources