특정 파일 세트에서 변경이 발생하는 경우에만 빌드를 트리거하는 방법


87

Jenkins / Hudson에게 내 Git 트리의 특정 프로젝트에 대한 변경 사항에 대해서만 빌드를 트리거하도록 지시하는 방법은 무엇입니까?

답변:


65

Git 플러그인에는 커밋의 파일이 제외 된 영역 정규식과 일치하는지 여부에 따라 빌드를 건너 뛸지 여부를 결정하기 위해 정규식을 사용하는 옵션 (제외 된 영역)이 있습니다.

안타깝게도 현재 Git 플러그인에는 "포함 된 지역"기능이 없습니다 (1.15). 그러나 누군가가 원하는 기능을 구현하는 Jenkins 및 Hudson에서 작동하는 GitHub에 패치를 게시했습니다.

빌드하는 것은 약간의 작업이지만 광고 된대로 작동하고 내 Git 트리 중 하나에 여러 개의 독립적 인 프로젝트가 있기 때문에 매우 유용했습니다.

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

업데이트 : Git 플러그인 (1.16)에는 이제 '포함 된'지역 기능이 있습니다.


5
1.1.16은 포함 된 기능의 올바른 버전 번호입니다. (더 1.16 없음)
댄 카터

작동하도록 만들 수 없습니다. 여러 모듈 (도메인, 공통, api, desktop_app, ...)이있는 저장소가 있습니다. 예를 들어 desktop_app에 대한 빌드를 트리거하고 싶습니다. "포함 된 지역"production_app / *, ./desktop_app과 같은 여러 조합을 시도했습니다. 그리고 나는 항상 Ignored commit c6e2b1dca0d1885: No paths matched included region whitelist. 단서가 있습니까? 더 자세한 사항은 여기에 : stackoverflow.com/questions/47439042/...
FranAguiar

38

기본적으로 두 가지 직업이 필요합니다. 하나는 파일이 변경되었는지 확인하고 다른 하나는 실제 빌드를 수행합니다.

직업 # 1

이것은 Git 저장소의 변경 사항에 대해 트리거되어야합니다. 그런 다음 지정한 경로 (여기서 "src")에 변경 사항이 있는지 테스트 한 다음 Jenkins의 CLI 를 사용 하여 두 번째 작업을 트리거합니다.

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 체크 아웃


6
마지막 빌드 이후에 두 개 이상의 커밋이 발생하면 어떻게 되나요? HEAD 커밋 만 검사하기 때문에 src의 변경 사항을 놓칠 수 있다고 생각합니다.
Adam Monsen 2011 년

@AdamMonsen 맞아. 그러나 위의 스크립트를 테스트하려는 상황 / 조건에 쉽게 적용 할 수 있습니다.
peritus 2011

에서 뭔가 빠진 게 있을거야 $? || exit 0... test $? -eq 0 || exit 0아마?
antak

31

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
일부 경우에는 작동하지 않습니다. 자세한 내용은 issues.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와 같은 필터 텍스트 와 필터 정규식을 가질 수 있습니다 ."folder/subfolder/[^"]+?"folder/subfolder


나는 이것을하려고 노력하고 있지만 조금 길을 잃었다. 변경된 파일의 경로를 젠킨스로 보내는 방법은 무엇입니까? 좀 더 설명해 주 시겠어요? changed_files 변수를 어디에 넣을까요?
Souad

사용중인 Git 서비스에서 웹훅을 구성해야합니다. 이 GitHub의 경우 예를 들어 여기에 있습니다 : github.com/jenkinsci/generic-webhook-trigger-plugin/blob/master/...
토마스 Bjerre

실제로 Bitbucket을 사용하면서 Bibucket (참조 : confluence.atlassian.com/bitbucket/… ) 의 푸시 이벤트 페이로드에서 Changed_files 항목을 사용할 수 없음을 깨달았 으므로 어떻게해야할지 모르겠습니다. 나는 내가 생각하는 커밋 메시지에 의존 할 것이다. 감사합니다
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 셸 맨 위에 직접 검사를 추가 할 수 있으며 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.