วิธีทริกเกอร์บิวด์เฉพาะเมื่อมีการเปลี่ยนแปลงเกิดขึ้นกับไฟล์ชุดใดชุดหนึ่งเท่านั้น


87

ฉันจะบอกเจนกินส์ / ฮัดสันให้ทริกเกอร์บิวด์สำหรับการเปลี่ยนแปลงเฉพาะโปรเจ็กต์เฉพาะในแผนผัง Git ของฉันได้อย่างไร

คำตอบ:


65

ปลั๊กอิน Git มีตัวเลือก (ภูมิภาคที่ยกเว้น) เพื่อใช้ regexes เพื่อพิจารณาว่าจะข้ามการสร้างโดยขึ้นอยู่กับว่าไฟล์ในการคอมมิตตรงกับ regex ของภูมิภาคที่ยกเว้น

ขออภัยปลั๊กอิน Stock Git ไม่มีคุณลักษณะ "รวมภูมิภาค" ในขณะนี้ (1.15) อย่างไรก็ตามมีคนโพสต์แพตช์บน GitHub ที่ทำงานกับ Jenkins และ Hudson ที่ใช้คุณลักษณะที่คุณต้องการ

เป็นงานสร้างเพียงเล็กน้อย แต่ใช้งานได้ตามที่โฆษณาและมีประโยชน์อย่างมากเนื่องจากต้นไม้ Git ของฉันมีโครงการอิสระหลายโครงการ

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

อัปเดต: ตอนนี้ปลั๊กอิน Git (1.16) มีคุณสมบัติภูมิภาค 'รวม'


5
1.1.16 เป็นหมายเลขเวอร์ชันที่ถูกต้องสำหรับคุณลักษณะที่รวมอยู่ (ไม่มี 1.16)
dan carter

ฉันไม่สามารถทำให้มันใช้งานได้ฉันมี repositorie ที่มีหลายโมดูล (โดเมน, ทั่วไป, api, desktop_app, ... ) ฉันต้องการทริกเกอร์บิวด์สำหรับ desktop_app เช่นฉันใส่ "พื้นที่ที่รวมไว้" production_app / *, ฉันลองชุดค่าผสมหลายอย่างเช่น. /desktop_app แม้กระทั่งเส้นทางที่แน่นอน Andi Ignored commit c6e2b1dca0d1885: No paths matched included region whitelistได้เสมอ เบาะแสใด ๆ ? รายละเอียดเพิ่มเติมที่นี่: stackoverflow.com/questions/47439042/…
FranAguiar

38

โดยพื้นฐานแล้วคุณต้องมีสองงาน หนึ่งในการตรวจสอบว่าไฟล์มีการเปลี่ยนแปลงหรือไม่และอีกไฟล์ที่จะสร้างจริง:

งาน # 1

สิ่งนี้ควรถูกทริกเกอร์เมื่อมีการเปลี่ยนแปลงในที่เก็บ Git ของคุณ จากนั้นจะทดสอบว่าเส้นทางที่คุณระบุ ("src" ที่นี่) มีการเปลี่ยนแปลงหรือไม่จากนั้นใช้CLI ของ Jenkinsเพื่อทริกเกอร์งานที่สอง

export JENKINS_CLI="java -jar /var/run/jenkins/war/WEB-INF/jenkins-cli.jar"
export JENKINS_URL=http://localhost:8080/
export GIT_REVISION=`git rev-parse HEAD`
export STATUSFILE=$WORKSPACE/status_$BUILD_ID.txt

# Figure out, whether "src" has changed in the last commit
git diff-tree --name-only HEAD | grep src

# Exit with success if it didn't
$? || exit 0

# Trigger second job
$JENKINS_CLI build job2 -p GIT_REVISION=$GIT_REVISION -s

งาน # 2

กำหนดค่างานนี้เพื่อรับพารามิเตอร์ GIT_REVISION เช่นนั้นเพื่อให้แน่ใจว่าคุณกำลังสร้างการแก้ไขที่งานแรกเลือกสร้าง

พารามิเตอร์สตริงบิลด์ที่กำหนดพารามิเตอร์ สร้างพารามิเตอร์ Git checkout


7
จะเกิดอะไรขึ้นถ้าการกระทำสองครั้งขึ้นไปเกิดขึ้นตั้งแต่การสร้างครั้งล่าสุด? ฉันคิดว่าคุณอาจพลาดการเปลี่ยนแปลงใน src เนื่องจากคุณกำลังตรวจสอบการคอมมิต HEAD เท่านั้น
Adam Monsen

@AdamMonsen ขวา. แต่คุณสามารถปรับสคริปต์ด้านบนให้เข้ากับสถานการณ์ / เงื่อนไขที่คุณต้องการทดสอบได้อย่างง่ายดาย .. ตัวอย่างเช่นไม่แตกต่างจาก HEAD แต่เทียบกับ HEAD ครั้งสุดท้ายที่สคริปต์ทำงาน
peritus

มีบางอย่างหายไปที่$? || exit 0... test $? -eq 0 || exit 0อาจจะ?
antak

34

หากคุณกำลังใช้ไวยากรณ์ที่เปิดเผยของJenkinsfileเพื่ออธิบายท่ออาคารของคุณคุณสามารถใช้การแก้ไขเงื่อนไขในการดำเนินการขั้นตอนการ จำกัด เฉพาะกรณีเมื่อเฉพาะไฟล์ที่มีการเปลี่ยนแปลง ตอนนี้นี่เป็นคุณสมบัติมาตรฐานของJenkinsและไม่ต้องการการกำหนดค่า / ซอฟต์แวร์เพิ่มเติมใด ๆ

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

คุณสามารถรวมหลายเงื่อนไขโดยใช้anyOfหรือallOfคำหลักสำหรับพฤติกรรมORหรือANDตาม:

when {
    anyOf {
        changeset "nginx/**"
        changeset "fluent-bit/**"
    }
}
steps {
    sh "make build-nginx"
    sh "make start-nginx"
}

1
โปรดทราบว่าอาจใช้ไม่ได้ในบางกรณี อ้างถึงissue.jenkins-ci.org/browse/JENKINS-26354สำหรับรายละเอียดเพิ่มเติม
tamerlaha

7

แม้ว่าจะไม่มีผลกับงานเดี่ยว แต่คุณสามารถใช้สคริปต์นี้เพื่อละเว้นขั้นตอนบางอย่างได้หากการกระทำล่าสุดไม่มีการเปลี่ยนแปลงใด ๆ :

/*
 * 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
}

1
@Karl อย่าลังเลที่จะแก้ไขรหัสหากมันเหมาะกับคุณ นั่นเป็นปัญหาหนึ่งที่ฉันพบเมื่อใช้รหัสนี้ (ในความล้มเหลวของการสร้างมันจะไม่ลองคอมมิตใหม่อีกครั้งหากการกระทำล่าสุดสัมบูรณ์ไม่ได้เปลี่ยนapi/โฟลเดอร์ด้วย) หากคุณสามารถแก้ไขได้ฉันชอบการเปลี่ยนแปลงที่แนะนำ !
Goodbye StackExchange

2

หากตรรกะในการเลือกไฟล์ไม่สำคัญฉันจะทริกเกอร์การเรียกใช้สคริปต์ในการเปลี่ยนแปลงแต่ละครั้งจากนั้นเขียนสคริปต์เพื่อตรวจสอบว่าจำเป็นต้องมีการสร้างหรือไม่จากนั้นจึงทริกเกอร์บิวด์หากเป็นเช่นนั้น


1

คุณสามารถใช้Generic Webhook Trigger Pluginสำหรับสิ่งนี้

กับตัวแปรเช่นและการแสดงออกchanged_files$.commits[*].['modified','added','removed'][*]

คุณสามารถมีข้อความตัวกรองเช่น$changed_filesและกรอง regexp เช่น"folder/subfolder/[^"]+?"if folder/subfolderเป็นโฟลเดอร์ที่ควรทริกเกอร์บิวด์


ฉันพยายามทำสิ่งนี้ แต่ก็หลงทางนิดหน่อย จะส่งเส้นทางของไฟล์ที่เปลี่ยนแปลงไปยัง jenkins ได้อย่างไร? คุณช่วยอธิบายเพิ่มเติมอีกนิดได้ไหม จะวางตัวแปร change_files ไว้ที่ใด
Souad

คุณต้องกำหนดค่า webhook ในบริการ Git ที่คุณใช้ ถ้าเป็น GitHub มีตัวอย่างที่นี่: github.com/jenkinsci/generic-webhook-trigger-plugin/blob/master/…
Tomas Bjerre

ในความเป็นจริงขณะที่ฉันใช้ Bitbucket ฉันตระหนักว่ารายการ Changed_files ไม่สามารถใช้ได้ใน payload ของเหตุการณ์ push ใน bibucket (ref: confluence.atlassian.com/bitbucket/… ) ดังนั้นฉันจึงไม่แน่ใจว่าจะทำได้อย่างไร ฉันจะอาศัยข้อความยืนยันที่ฉันคิด ขอบคุณ
Souad

1

ฉันตอบคำถามนี้ในโพสต์อื่น:

วิธีรับรายการไฟล์ที่เปลี่ยนแปลงตั้งแต่สร้างล่าสุดใน 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;

คุณสามารถเพิ่มการตรวจสอบได้โดยตรงที่ด้านบนสุดของ exec shell ของงานและexit 0หากตรวจไม่พบการเปลี่ยนแปลง ... ดังนั้นคุณสามารถสำรวจระดับบนสุดสำหรับการเช็คอินเพื่อทริกเกอร์บิลด์ได้ตลอดเวลา


1

ฉันเขียนสคริปต์นี้เพื่อข้ามหรือดำเนินการทดสอบหากมีการเปลี่ยนแปลง:

#!/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 "$@"

คุณสามารถทำสิ่งต่างๆเช่น:

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

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.