Home > database >  Provide task inputs based on variable populated by dependent task
Provide task inputs based on variable populated by dependent task

Time:11-29

Use Case

We've setup a pre-commit git hook that lints declarative pipelines (Jenkinsfiles). Currently all Jenkinsfiles in the repository are linted every time git commit is issued. I am looking to improve the process by only linting Jenkinsfiles that have changed since the last Gradle execution. We are using Gradle (v7.5.1) to orchestrate tasks like Spotless check/apply and Jenkinsfile linting.

Example

I've registered two tasks in build.gradle. One task rounds up all Jenkinsfiles in the repository and the other lints them. For the purposes of brevity I've simplified the tasks listed below.

def jenkinsfiles = []

task getJenkinsfiles {
    doLast {
        jenkinsfiles = ['Jenkinsfile1', 'Jenkinsfile2', 'Jenkinsfile3']
        //println(jenkinsfiles)
    }
}

task lintJenkinsfiles {
    dependsOn getJenkinsfiles
    inputs.file(jenkinsfiles)
    outputs.file('lintJenkinsfile.cache')
    doLast {
        println(jenkinsfiles)
    }
}

Results

getJenkinsfiles executes first without issue. If I uncomment println(jenkinsfiles) in getJenkinsfiles task, the value is printed to the console. However, lintJenkinsfiles fails and states that the path may not be null or empty string. path='[]'.

How does one reference a variable populated in task1 as an input in task2?

CodePudding user response:

I created the following task that's inspired by Torek's comment on my original question.

  1. Get all changed files using git status --short. Split the result by newline.
  2. Iterate over each entry. Each entry will be in the format of <status> <filename> (i.e., M test.txt, M test.txt, MM test.txt). See the git-status page for more information.
  3. If the entry's key (status) does not contain 'D' (deleted), add it to the jenkinsfiles list.
task lintJenkinsfiles {
    def jenkinsfiles = []
    def statusFileEntries = 'git status --short'.execute().text.split('\n')
    for (def statusFileEntry : statusFileEntries) {
        def statusFileEntryCapture = statusFileEntry =~ /^\s{0,1}(\w{1,2})\s{1,2}(.*Jenkinsfile)$/
        if (statusFileEntryCapture.matches() && !statusFileEntryCapture[0][1].contains('D')) {
            jenkinsfiles  = statusFileEntryCapture[0][2].trim()
        }
    }
    inputs.files(jenkinsfiles)
    outputs.file('lintJenkinsfiles.cache')
    doLast {
        if (!jenkinsfiles.isEmpty()) {
            println("Linting: ${jenkinsfiles}")
        }
    }
}
  • Related