How to trigger a build only if changes happen on particular set of files

后端 未结 8 1572
后悔当初
后悔当初 2020-11-28 20:01

How do I tell Jenkins/Hudson to trigger a build only for changes on a particular project in my Git tree?

相关标签:
8条回答
  • If you are using a declarative syntax of Jenkinsfile to describe your building pipeline, you can use changeset condition to limit stage execution only to the case when specific files are changed. This is now a standard feature of Jenkins and does not require any additional configruation/software.

    stages {
        stage('Nginx') {
            when { changeset "nginx/*"}
            steps {
                sh "make build-nginx"
                sh "make start-nginx"
            }
        }
    }
    

    You can combine multiple conditions using anyOf or allOf keywords for OR or AND behaviour accordingly:

    when {
        anyOf {
            changeset "nginx/**"
            changeset "fluent-bit/**"
        }
    }
    steps {
        sh "make build-nginx"
        sh "make start-nginx"
    }
    
    0 讨论(0)
  • 2020-11-28 20:23

    I wrote this script to skip or execute tests if there are changes:

    #!/bin/bash
    
    set -e -o pipefail -u
    
    paths=()
    while [ "$1" != "--" ]; do
        paths+=( "$1" ); shift
    done
    shift
    
    if git diff --quiet --exit-code "${BASE_BRANCH:-origin/master}"..HEAD ${paths[@]}; then
        echo "No changes in ${paths[@]}, skipping $@..." 1>&2
        exit 0
    fi
    echo "Changes found in ${paths[@]}, running $@..." 1>&2
    
    exec "$@"
    

    So you can do something like:

    ./scripts/git-run-if-changed.sh cmd vendor go.mod go.sum fixtures/ tools/ -- go test

    0 讨论(0)
  • 2020-11-28 20:27

    I answered this question in another post:

    How to get list of changed files since last build in Jenkins/Hudson

    #!/bin/bash
    
    set -e
    
    job_name="whatever"
    JOB_URL="http://myserver:8080/job/${job_name}/"
    FILTER_PATH="path/to/folder/to/monitor"
    
    python_func="import json, sys
    obj = json.loads(sys.stdin.read())
    ch_list = obj['changeSet']['items']
    _list = [ j['affectedPaths'] for j in ch_list ]
    for outer in _list:
      for inner in outer:
        print inner
    "
    
    _affected_files=`curl --silent ${JOB_URL}${BUILD_NUMBER}'/api/json' | python -c "$python_func"`
    
    if [ -z "`echo \"$_affected_files\" | grep \"${FILTER_PATH}\"`" ]; then
      echo "[INFO] no changes detected in ${FILTER_PATH}"
      exit 0
    else
      echo "[INFO] changed files detected: "
      for a_file in `echo "$_affected_files" | grep "${FILTER_PATH}"`; do
        echo "    $a_file"
      done;
    fi;
    

    You can add the check directly to the top of the job's exec shell, and it will exit 0 if no changes are detected... Hence, you can always poll the top level for check-in's to trigger a build.

    0 讨论(0)
  • 2020-11-28 20:29

    You can use Generic Webhook Trigger Plugin for this.

    With a variable like changed_files and expression $.commits[*].['modified','added','removed'][*].

    You can have a filter text like $changed_files and filter regexp like "folder/subfolder/[^"]+?" if folder/subfolder is the folder that should trigger builds.

    0 讨论(0)
  • 2020-11-28 20:35

    The Git plugin has an option (excluded region) to use regexes to determine whether to skip building based on whether files in the commit match the excluded region regex.

    Unfortunately, the stock Git plugin does not have a "included region" feature at this time (1.15). However, someone posted patches on GitHub that work on Jenkins and Hudson that implement the feature you want.

    It is a little work to build, but it works as advertised and has been extremely useful since one of my Git trees has multiple independent projects.

    https://github.com/jenkinsci/git-plugin/pull/49

    Update: The Git plugin (1.16) now has the 'included' region feature.

    0 讨论(0)
  • 2020-11-28 20:36

    While this doesn't affect single jobs, you can use this script to ignore certain steps if the latest commit did not contain any changes:

    /*
     * Check a folder if changed in the latest commit.
     * Returns true if changed, or false if no changes.
     */
    def checkFolderForDiffs(path) {
        try {
            // git diff will return 1 for changes (failure) which is caught in catch, or
            // 0 meaning no changes 
            sh "git diff --quiet --exit-code HEAD~1..HEAD ${path}"
            return false
        } catch (err) {
            return true
        }
    }
    
    if ( checkFolderForDiffs('api/') ) {
        //API folder changed, run steps here
    }
    
    0 讨论(0)
提交回复
热议问题