Issue 1
There are two ways to aggregate multiple builds into one buildInfo instance in a pipeline script.
The first one is exactly what you did - save the buildInfo instance returned from the server.uoload or server.downkoad methods and then use the buildInfo.append method to append (aggregate) two buildInfo instances.
The second way, which is probably what you need, is to create a buildInfo instance and send it as an argument to server.uoload or server.doenload methods. This way, you can send the same buildInfo instance to multiple upload or download methods and have it aggregate everything.
Here how you do it:
def buildInfo = Artifactory.newBuildInfo()
server.download spec: downloadSpec, buildInfo: buildInfo
server.upload spec: uploadSpec, buildInfo: buildInfo
server.publishBuildInfo buildInfo
How does it help you?
Well, since you manually create your buildInfo instance, you can define it in a scope which is above the two stages, and this way, all stages can use the buildInfo instance.
Here's an example:
node {
// Obtain an Artifactory server instance, defined in Jenkins --> Manage:
def server = Artifactory.server "SERVER_ID"
// Create a buildInfo instance, to be used by the stages of this pipeline:
def buildInfo = Artifactory.newBuildInfo()
stage ('Upload files to Artifactory') {
def uploadSpec = """{
"files": [
{ "pattern": "/Users/eyalb/.m2/repository/a*a*.jar",
"target": "generic-local",
"excludePatterns": ["*SNAPSHOT*"],
"flat": "false"
}
]
}"""
server.upload spec: uploadSpec, buildInfo: buildInfo
}
stage ('Collect env vars') {
buildInfo.env.filter.addExclude("DONT_COLLECT*")
// By default the filter is configured to exclude "*password*,*secret*,*key*", but since we're overriding this configuration by adding our own exclusion, let's add these excludes:
buildInfo.env.filter
.addExclude("*password*")
.addExclude("*secret*")
.addExclude("*key*")
withEnv(['DO_COLLECT_FOO=BAR', 'DONT_COLLECT_FOO=BAR']) {
buildInfo.env.collect()
}
}
stage ('Access build info env vars') {
// BAR will printed
echo buildInfo.env.vars['DO_COLLECT_FOO']
// null will be printed, because we excluded it.
echo buildInfo.env.vars['DONT_COLLECT_FOO']
}
stage ('Set build retention') {
buildInfo.retention maxBuilds: 1, maxDays: 2, doNotDiscardBuilds: ["3"], deleteBuildArtifacts: true
}
stage ('Publish build info') {
server.publishBuildInfo buildInfo
}
}
If you'd like to use declarative pipeline, here's how you share the same buildInfo instance between multiple stages. Notice the initBuildInfo() method - it needs to be invoked only once. The below example include only two of the stages from the above scripted pipeline example:
pipeline {
agent {
label "my-agents"
}
stages {
stage('Upload files to Artifactory') {
steps {
initBuildInfo()
def uploadSpec = """{
"files": [
{ "pattern": "/Users/eyalb/.m2/repository/a*a*.jar",
"target": "generic-local",
"excludePatterns": ["*SNAPSHOT*"],
"flat": "false"
}
]
}"""
server.upload spec: uploadSpec, buildInfo: buildInfo
}
}
stage('Collect env vars') {
steps {
buildInfo.env.filter.addExclude("DONT_COLLECT*")
// By default the filter is configured to exclude "*password*,*secret*,*key*", but since we're overriding this configuration by adding our own exclusion, let's add these excludes:
buildInfo.env.filter
.addExclude("*password*")
.addExclude("*secret*")
.addExclude("*key*")
withEnv(['DO_COLLECT_FOO=BAR', 'DONT_COLLECT_FOO=BAR']) {
buildInfo.env.collect()
}
}
}
}
}
def rtServer, buildInfo
void initBuildInfo() {
script {
rtServer = Artifactory.server "JX_ARTIFACTORY_SERVER"
buildInfo = Artifactory.newBuildInfo()
}
}
Issue 2
When you're running:
buildInfo.env.collect()
You're asking Jenkins to collect the environment variables now (at the time of the collect() method execution) and store them on this buildInfo instance.
When setting:
buildInfo.env.capture = true
You're asking Jenkins to collect environment variables with every upload and download method which uses this buildInfo. You can use this as follows:
def buildInfo = Artifactory.newBuildInfo()
buildInfo.env.capture = true
server.download spec: downloadSpec, buildInfo: buildInfo
server.upload spec: uploadSpec, buildInfo: buildInfo
server.publishBuildInfo buildInfo
Notice that you should set
buildInfo.env.capture = true
before executing the uploads or downloads.
So the advantage of using:
buildInfo.env.capture = true
is that you can set it once on your buildInfo instance and then have the env vars collected for you from that point on.
On the other hand, there are scenarios when you'd like the collect the env vars at a specific point during your pipeline. That is when
buildInfo.env.collect()
comes in handy.