It was a darkish and stormy night time. The devoted engineer careened throughout the rain and dirt to ship her vital package deal by the difficult terrain of the infamous Pipeline Traverse. She had a supply of the utmost significance and time was of the essence. Nonetheless, her confidence was sturdy. In any case, she had delivered related packages lots of of occasions. She shortly however fastidiously ushered this essential supply, navigating round the entire acquainted potholes, hairpin turns, and imposing cliff faces. She was simply starting to essentially benefit from the thrill of the effectivity and precision of her path when the catastrophe struck.
You see, the acquainted path of the Pipeline Traverse modified! It was not the identical route that she was anticipating, and sadly she was by no means notified of the change. The crash was large. And dear. However worst of all, she now discovered herself misplaced in the course of an unfamiliar path with no thought how she might make her supply. She was misplaced, and the package deal couldn’t be delivered as wanted.
Let me reign myself in earlier than I get too engrossed on this story and give up my day job to pursue cheeseball novels. Cheese apart, is not our protagonist on this story relatable to anybody concerned in managing a software program supply pipeline? It appears simply after we are most assured in our supply pipeline that catastrophe strikes (often at 4:30 on a Friday afternoon amirite ?).
And if the issue is in your pipeline or your pipeline configuration, when it strikes it may be actually difficult to debug. That is very true in case your CI/CD pipeline is buried within the UI. Have you ever ever discovered your self muttering issues like:
“The place did I set this pipeline up?”
“Who modified my pipeline?!”
“I want I did not want this boiler plate for all my tasks!”
…or, for those who ever have the disagreeable expertise of knowledge loss or corruption of your CI config information…
“How on the planet did I set that up once more (over the course of three years and a number of adjustments)?”
Nicely these sentiments are what invariably result in a greater means. Ultimately most tasks deal with the issue of pipeline administration by the precept of Configuration as Code. This is likely one of the many weblog matters I’ve promised you we might deal with and focus on right here, and so lastly right here we’re.
Configuration as Code follows the precept that we reduce CI configuration in a CI server UI. What we do within the pipeline shouldn’t be outlined as obscure and opaque metadata that’s held onto by a CI server occasion someplace (the place? who is aware of!). We must always as a substitute outline that course of and pipeline with the code – the place the adjustments occur. The place the adjustments are recorded, could be reverted, and are utterly impartial of a specific CI server occasion and it is state.
With our protagonist delivering alongside the Pipeline Traverse, whereas she might not have been in a position to keep away from all crashes, when an issue does present up it’s a lot simpler to diagnose and pinpoint the trigger and in the end the best way out of the canyon.
Our Jenkins plugin helps this. Additionally most different platforms we assist, like CircleCI, Travis CI, Azure DevOps, and GitHub Actions comply with this precept as properly.
To see this work for our Jenkins plugin, let me present you how one can translate the venture we mentioned right here over to a Jenkinsfile utilizing the plugin’s assist for a characteristic referred to as Jenkins Pipelines. This venture features a MEX compile step and a subsequent step to run the exams and produce take a look at consequence and protection artifacts.
It is really fairly straightforward. This venture had the next steps in its pipeline:
- Inform Jenkins the place MATLAB is (there’s really extra information which makes this simpler to handle as properly, however perhaps that is a future weblog submit)
- Compile the mex information
- Run the exams
- Course of the take a look at consequence and protection artifacts
Now as a substitute of defining these within the UI, we’re going to create a Jenkinsfile that comprises these steps of the pipeline, and this we are able to examine into our venture proper alongside our code.
Let’s begin with a primary pipeline that specifies it could actually use any out there Jenkins agent and has a placeholder so as to add our phases to the pipeline.
pipeline { agent any phases { } }
Step 1
Keep in mind our pipeline had 4 steps, so let’s begin with step 1. We have to inform Jenkins the place MATLAB is. Truly that is actually simply accomplished by setting the atmosphere such that the machine itself is aware of the place MATLAB is on the system PATH. When invoking MATLAB the plugin will merely name MATLAB from the shell, so enabling this to work accurately merely means prepending the PATH atmosphere variable with MATLAB throughout this pipeline in order that invoking matlab from the shell will invoke the specified MATLAB arrange on the construct agent. This seems to be like so:
atmosphere { PATH = "/Functions/MATLAB_R2020b.app/bin:${PATH}" }
Step 2
The subsequent step is to construct the mex information. As a reminder the instance venture we’re working with right here, libDirectional, has a pleasant perform referred to as compileAll that does the trick for us. Keep in mind, we confirmed right here that placing this within the type of a MATLAB venture helps get our surroundings setup accurately. So our command is only a fast opening of the venture and a name to the nifty compileAll perform. Right here we use the runMATLABCommand step that comes as a part of the plugin. We needn’t fear about how MATLAB launches (which varies with completely different releases), we simply fear concerning the command we have to invoke. It is as straightforward as including a stage with this step inside it:
stage('Compile MEX information') { steps { runMATLABCommand 'openProject(pwd); compileAll' } }
Step 3
Now let’s run the exams! Final time we touched on this we ran all of the exams outlined within the venture and we generated take a look at ends in the TAP format and code protection within the Cobertura format. I’m going to make a slight tweak right here, as a result of the TAPPlugin, which processes these TAP outcomes, would not assist Jenkins pipelines in addition to the JUnit plugin. As you could be beginning to see, this may be accomplished with some simple pipeline syntax that matches the identical type of factor we are able to do by the UI.
stage('Run MATLAB exams') { steps { runMATLABTests( testResultsJUnit: 'matlabTestArtifacts/junittestreport.xml', codeCoverageCobertura: 'matlabTestArtifacts/cobertura.xml' ) } }
Step 4
…and eventually, now that now we have constructed our venture, examined it and generated some take a look at outcomes and protection artifacts, we are able to now course of these artifacts utilizing different plugins meant for that function (the JUnit plugin and the Code Protection API plugin). I am going to simply add them to the identical stage because the take a look at run.
stage('Run MATLAB exams') { steps { runMATLABTests( testResultsJUnit: 'matlabTestArtifacts/junittestreport.xml', codeCoverageCobertura: 'matlabTestArtifacts/cobertura.xml' ) junit 'matlabTestArtifacts/junittestreport.xml' publishCoverage adapters: [coberturaAdapter('matlabTestArtifacts/cobertura.xml')] } }
That is it, that is all we want. Right here is the entire Jenkinsfile for reference:
pipeline { agent any atmosphere { PATH = "/Functions/MATLAB_R2020b.app/bin:${PATH}" } phases { stage('Compile MEX information') { steps { runMATLABCommand 'openProject(pwd); compileAll' } } stage('Run MATLAB exams') { steps { runMATLABTests( testResultsJUnit: 'matlabTestArtifacts/junittestreport.xml', codeCoverageCobertura: 'matlabTestArtifacts/cobertura.xml' ) junit 'matlabTestArtifacts/junittestreport.xml' publishCoverage adapters: [coberturaAdapter('matlabTestArtifacts/cobertura.xml')] } } } }
Now simply examine one thing like that into the foundation of your repository, and you may be good to go. This is the way you create a Jenkins job that makes use of it:
…and now you may see the pipeline runs simply high-quality and dandy because it pulls its pipeline directions from the Jenkinsfile as a substitute of the Jenkins UI:
…and now since this pipeline configuration is checked in, it travels with the code, it may be reverted with the code, it may be reviewed with the code, and it may be reasoned with the code. Code is gorgeous, particularly when backed by a bit of little bit of supply management, MATLAB tasks, and what we hope are helpful CI platform integrations.
Now let’s all burst out in tune!!
Printed with MATLAB® R2020b