I am trying to select branches with branch names starting with release.
stage("Upload Artifacts") {
when {
expression {
return env.BRANCH_NAME == "release/*"
}
}
steps {
...
...
}
}
The above code is not picking up my release branch and is simply skipping the stage.
Stage "Upload Artifacts" skipped due to when conditional
You are comparing the branch name with the verbatim string release/*. If there is only one branch called "release" just compare with that. If you wanted to use the * as a wild card you should use BRANCH_NAME.startsWith('release') or look into patterns in groovy.
when {
expression {
return (env.BRANCH_NAME).startsWith('release')
}
}
Related
Let's have a seed job in Jenkins Job DSL Groovy which generates a pipeline this way:
pipeline {
agent any
stages {
stage("DSL") {
steps {
jobDsl scriptText: """pipelineJob("test-pipeline-generated") {
definition {
cps {
script 'pipeline { agent(any); triggers{ cron("H/2 * * * *") }; stages { stage("Some") { steps { echo "Working ..." } } } }'
}
}
}
"""
}
}
}
}
It generates a pipeline job which has to be triggered manually for the first time to process triggers definition and everything works fine. However, when the seed job is triggered again it overwrites the pipeline job definition and triggers are gone again. This means that seed job disables all such jobs.
Does anybody know if there is any solution for it?
We would like to keep triggers there and if there are changes in the pipeline it will be processed after the first run. We would like to not specify triggers in job DSL because users are used to specify them in the pipeline definition.
There is a switch for not regenerating existing jobs/views:
DSL API:
ignoreExisting()
If you put the triggers inside the template pipeline (as well as in the seed job), it will remain for the next runs as well.
I am using gradle with dynamic versioning , i.e. something like this
dependencies {
compile("myGroup:myModule:1.9.+")
}
I would like to reject any SNAPSHOT canidates, such that the above example would match 1.9.1 but would reject 1.9.2-SNAPSHOT, except for the case that somebody explicitly required it.
So far, we worked with something like
resolutionStrategy.componentSelection {
all { ComponentSelection selection ->
if (selection.candidate.version.endsWith("-SNAPSHOT")){
selection.reject("Rejecting changing version (SNAPSHOT)'")
}
}
}
This rejects all canididates ending in SNAPSHOT.
I learned that one can also access requested version using something like this
resolutionStrategy.eachDependency { details ->
if (details.requested.version.endsWith("-SNAPSHOT")) {
...
}
}
Is there a way to combine the two into something like this?
if (selection.candidate.version.endsWith("-SNAPSHOT") && ! details.requested.version.endsWith("-SNAPSHOT")) {
selection.reject("Rejecting changing version (SNAPSHOT)'")
}
As in subject - is there any way to verify if current build is effect of using 'Replay' button?
I found the following solution using the rawBuild instance from currentBuild. Since we can't get the class of the causes, we just verify its string value.
def replayClassName = "org.jenkinsci.plugins.workflow.cps.replay.ReplayCause"
def isReplay = currentBuild.rawBuild.getCauses().any{ cause -> cause.toString().contains(replayClassName) }
This solution works for Jenkins with Blue-Ocean. References to how to get to this answer is Jenkins declarative pipeline: find out triggering job
Update
Using this a step condition works like a charm!
You can define a shared library like jenkins.groovy
def isBuildAReplay() {
// https://stackoverflow.com/questions/51555910/how-to-know-inside-jenkinsfile-script-that-current-build-is-an-replay/52302879#52302879
def replyClassName = "org.jenkinsci.plugins.workflow.cps.replay.ReplayCause"
currentBuild.rawBuild.getCauses().any{ cause -> cause.toString().contains(replyClassName) }
}
You can reuse it in a Jenkins pipeline
stage('Conditional Stage') {
when {
expression { jenkins.isBuildAReplay() }
}
steps {
...
...
}
}
Is there a way to add empty directories (e.g, "logs") when creating a distribution with the gradle distribution plugin?
I saw this JIRA, describing the exact same thing. It is still open https://issues.gradle.org/browse/GRADLE-1671
I wonder if there are any workarounds I can use. I don't quite understand the workarounds described in the jira.
Thank you.
So I managed to work around this by following the suggestion in the mentioned JIRA to create a dummy empty directory and then copy it to the distribution location.
It's ugly but works. I'm sure it can be written more efficiently though. This is the Copy block from inside distributions/main/contents:
into('') {
//create an empty 'logs' directory in distribution root
def logDirBase = new File('/tmp/app-dummy-dir')
logDirBase.mkdirs()
def logDir = new File(logDirBase.absolutePath + '/logs')
logDir.mkdirs()
from {logDirBase}
}
Based on Logato's own answer I've come up with the following code, which is more elegant and also closes the file pointer correctly (using the with context):
distributions {
main {
baseName = 'app'
contents {
into('') {
File.createTempDir().with {
def tmpLog = new File(absolutePath, 'logs')
println tmpLog.absolutePath
tmpLog.mkdirs()
from (absolutePath) {
includeEmptyDirs = true
}
}
// ...
}
// ...
}
}
}
This seems odd answering this so late. But, there are 2 issues here.
We should really avoid creating empty directories. But, if we must...we must.
The previous examples attempt to create empty directories outside of the current project, which seems to go against the goal of most builds. We can avoid this and work more naturally within gradle by adding a custom task.
plugins {
id 'java'
id 'distribution'
}
group 'org.example'
version '1.0-SNAPSHOT'
task createEmptyLogDir() {
ext {
buildDir = layout.buildDirectory.dir('empty_dirs')
}
doFirst {
File.createTempDir().with {
def dir = new File(buildDir.get().asFile, 'logs')
dir.mkdirs()
}
}
outputs.dir(buildDir)
}
tasks.assembleDist.configure {
dependsOn('createEmptyLogDir')
}
distributions {
main {
distributionBaseName = 'app'
contents {
into('lib') {
from tasks.jar
}
from tasks.createEmptyLogDir {
includeEmptyDirs = true
}
}
}
}
This has the advantage of building within the build directory, using task inputs/outputs for up-to-date checks, and cleaning up.
An important note is that we cannot just create the distribution with empty directories, alone. This will be seen as no source and up-to-date. So, I added the jar in this example. Tested with gradle 7.1.
Having an extract from https://github.com/gradle/gradle/blob/master/build.gradle:
ext {
isDevBuild = {
gradle.taskGraph.hasTask(developerBuild)
}
}
task developerBuild {
description = 'Builds distributions and runs pre-checkin checks'
group = 'build'
dependsOn testedDists
}
When I used this approach to create custom configuration in my project I discovered that:
isDevBuild === true
i.e. it's always true because task 'developerBuild' is inside my build.gradle project, and hence in graph. They have a couple of "different" configs (isCIBuild, isCommitBuild, isFinalReleaseBuild, ...) so I suppose I got something wrong here.
Can someone explain how to make this configs conditional based on some external parameter?
taskGraph.hasTask() tells if a task is in the task execution graph, that is whether it will get executed. Because the task execution graph is only created after the configuration phase, this method has to be called from a whenReady callback (or in the execution phase):
gradle.taskGraph.whenReady { graph ->
if (graph.hasTask(developerBuild)) {
// do conditional configuration
}
}
To make this more readable, we can introduce a new method:
def onlyFor(task, config) {
gradle.taskGraph.whenReady { graph ->
if (graph.hasTask(task)) {
project.configure(project, config)
}
}
}
Now we can write:
onlyFor(developerBuild) { ... }
onlyFor(ciBuild) { ... }
Another, simpler way to solve this problem is to check whether a particular task name is contained in gradle.startParameter.taskNames. However, this has two limitations: First, it compares task names, which can make a difference in multi-project builds. Second, it will only find tasks that have been specified directly (e.g. on the command line), but not dependencies thereof.
PS.: In your code, isDevBuild always holds because a (non-null) closure is true according to Groovy truth. (In contrast to isDevBuild(), isDevBuild won't call the closure.)