Hi there,
I've been struggling a bit in order to accomplish the below use case, first of all this is a long message, It works so far although I've found it a bit 'too much' hacky. That's the reason I want to explain how I did it just in case someone got a similar use case or even, most likely, a better approach.
Use Case
Using Declarative Pipeline I'd like to inject global env variables using the Gerrit Trigger plugin, then those details will be added as a Gerrit comment. Those env variables will be changed/created on the fly.
Gerrit Trigger plugin allows to customise the Gerrit comment using the existing env variables plus some default ones, as you can see in the below links
I've tried to override the value of those env variables or even create a new env variable but those variables weren't expanded correctly or even didn't exist.
From the implementation point of view I used two different DSLs: Pipeline and JobDSL.
The JobDSL part is just the Pipeline Job and how it's integrated with Gerrit, while the Pipeline is the declarative pipeline itself.
pipelineJob("gatekeeper") {
triggers {
gerritTrigger {
gerritProjects {
gerritProject {
compareType('PLAIN')
pattern('driver')
branches {
branch {
compareType('PLAIN')
pattern('trunk')
}
}
disableStrictForbiddenFileVerification(false)
}
}
serverName("gerrit-gpu")
triggerOnEvents {
commentAddedContains {
commentAddedCommentContains('AutomateMe')
}
}
silentMode(false)
}
}
definition {
cps {
sandbox()
script(readFileFromWorkspace('pipeline.groovy'))
}
}
}
pipeline {
agent any
stage('TestLab') {
steps {
script {
// This is a Long Execution Build in the Test Lab
def bRun = build job: 'testlab', parameters: [string(name: 'GERRIT_PATCHSET_REVISION', GERRIT_PATCHSET_REVISION)], propagate: false
sh """
curl "${bRun.getRawBuild().getAbsoluteUrl()}/artifact/testlab_run.properties/*view*/" --write-out %{http_code} --silent --output /dev/null | grep '200' >/dev/null \
&& curl -s -o ti2_run.properties "${bRun.getRawBuild().getAbsoluteUrl()}/artifact/testlab_run.properties/*view*/" || echo "TESTLAB_URL=null" > testlab_run.properties
"""
}
}
}
}
}
How did I inject env variables on the fly using the Declarative Pipeline?
import hudson.tasks.test.AbstractTestResultAction
// List of Functions
@NonCPS
def addParameter(build, name, value) {
// Given a Build it will Inject a Parameter and Value pair
StringParameterValue p = new StringParameterValue(name, value)
ParametersAction a = build.getAction(ParametersAction.class)
if (a) {
build.replaceAction(a.createUpdated(Collections.singleton(p)));
} else {
build.addAction(new ParametersAction(p));
}
}
pipeline {
agent any
parameters {
string(name: 'TESTLAB_URL', description: 'To expose as a comment in Gerrit')
}
stage('TestLab') {
...
post {
always {
script {
def props = readProperties file: 'testlab_run.properties'
addParameter(currentBuild.rawBuild, "TESTLAB_URL", "${props.
TESTLAB_URL}")
}
}
}
}
It --worked like a charm--, although I didn't like much the idea of playing with the internal api though. But ... I started to see the below errors:
groovy.lang.MissingPropertyException: No such property: GERRIT_PATCHSET_REVISION
for class: WorkflowScript
Null value not allowed as an environment variable: TESTLAB_URL
Those errors where only happing when the pipeline was launched without editing it previously. What do I mean? If i do change the pipeline job, using the Jenkins UI, and save it, then those errors go away only for the next build, while if I don't change anything the next build will fail with the above errors.
How did I solve them?
1st stacktrace error was solved by injecting those env variables which are provided by the Gerrit Trigger as Pipeline parameters:
agent any
parameters {
string(name: 'TESTLAB_URL', description: 'To expose as a comment in Gerrit')
string(name: 'GERRIT_PATCHSET_REVISION', description: 'To solve MissingPropertyException')
}
stage('TestLab') {
steps {
script {
// This is a Long Execution Build in the Test Lab
def bRun = build job: 'testlab', parameters: [string(name: 'GERRIT_PATCHSET_REVISION', params.GERRIT_PATCHSET_REVISION)], propagate: false
2nd one was by enabling a default value to those parameters
agent any
parameters {
string(name: 'TESTLAB_URL', defaultValue: "empty", description: 'To expose as a comment in Gerrit')
string(name: 'GERRIT_PATCHSET_REVISION', defaultValue: "empty", description: 'To solve MissingPropertyException')
}
Final thoughts
This is not an ideal implementation:
- too complicated
- too many dependencies
- non KISS
Since I couldn't find another way to inject env variables on the fly, I'd like to ask whether you got some ideas, workarounds or even think this is too unstable to keep it running for a while.
Thanks and sorry for this long message