Do Something

[Jenkins] 원하는 브랜치의 원하는 폴더의 변경이 일어나면 실행 / 풀 받을때 갱신이 필요없는 빌드는 무시 본문

기타

[Jenkins] 원하는 브랜치의 원하는 폴더의 변경이 일어나면 실행 / 풀 받을때 갱신이 필요없는 빌드는 무시

뭐라도해야겠다 2023. 8. 6. 16:52

그냥 기억해둘려고 작성해둔다. 

 

pipeline {
    agent any

    tools {
        maven "maven-3.9.3"
    }

    stages {
        stage('Git pull') {
            steps {
                // Get some code from a GitHub repository
                checkout([$class: 'GitSCM', 
                    branches: [[name: '*/원하는 브랜치 ']],
                    doGenerateSubmoduleConfigurations: false,
                    extensions: [
                        [$class: 'SparseCheckoutPaths',  sparseCheckoutPaths:[[$class:'SparseCheckoutPath', path:'원하는 폴더']]]
                                ],
                    submoduleCfg: [],
                    userRemoteConfigs: [[credentialsId: '젠킨스에 저장해둔 gitlab에 인증정보', url: '깃 주소']]])
                script{
                		# gif diff를 사용해서 바뀐 파일들을 싹 가져온다.
                        # 가져온 파일들을 split한다. [0..-2]는 파일이름을 제거하기 위한거다. 특정 경로까지를 원한다면 여길 조정해주면 된다. 
                        # 가져온 경로의 이름을 파싱한거라 2차원 배열이므로, flatten함수를 사용해서 1차원으로 만들고 중복을 제거한다. 
                        # 바뀐 경로의 폴더 이름만 중복되지 않게 가져오는데 성공한다. 
                        changedFolders = sh(returnStdout: true, script: "git diff --name-only HEAD^ HEAD").trim().tokenize('\n').collect { it.split('/')[0..-2]}.unique()
                        changedFolders.each { folder -> echo "changed Folder : ${folder}" }
                        changedFolders = changedFolders.flatten().unique()
                        changedFolders.each { folder -> echo "Flatten Folder : ${folder}" }
                    }
            }
        }
        
        stage('build') {
            when {
                expression {
                	# 바뀐것중에 ProjectService폴더가 있으면 빌드한다. 
                    return changedFolders.contains("ProjectService")
                }
            }
            steps{
                dir('./BE/ProjectService'){
                    withMaven {
                        sh "mvn clean compile package -DskipTests -Dmaven.test.skip=true"
                    }
                }
            }
        }
        
        stage('deploy') {
            when {
                expression {
                	# 바뀐것중에 ProjectService폴더가 있으면 배포한다. 
                    return changedFolders.contains("ProjectService")
                }
            }
            steps {
                dir('./BE/ProjectService'){
                    sh "pwd"  
                    sh "chmod +x ./feature.sh  && ./feature.sh"
                }
            }
        }
    }
}

 

git diff를 사용해서 직전까지의 커밋만 확인할 수 있다는 한계가 있다. 

현재의 git상태와 pull받고 나서의 git상태를 비교하는 함수로 다시 만들어야 할거같긴 하지만, 대충 갈피를 잡았다는데 의의가 있다

 

실제로 ProjectService폴더 아래에서 바뀐게 없으면 build와 deploy가 생략되는걸 확인할 수 있다. 

 

 

 


아름다운 실패의흔적

새롭게 체크아웃 할 때 fetch를 먼저해서 가장 최신 커밋과 현재 저장소의 상태를 비교 후 변경되는 폴더의 이름을 저장하고

프로젝트가 그 특정 폴더에 들어있을 때만 빌드와 배포를 하는 코드를 만들었다

 

jenkins의 gitlab 플러그인이 checkout은 편리하게 지원하는데 fetch는 따로 지원하지 않아서 그냥 직접 git 명령어를 통해서 fetch를 해야만 했다. 

pipeline {
    agent any

    tools {
        maven "maven-3.9.3"
    }
    
    environment {
        currentBranch = "*/feature/project-api"
        changedFiles = ""
        changedFolders = ""
    }
    stages {
        stage('check Change'){
            steps {
				# 먼저 깃 패치를 한다. 
                # 이상하게 젠킨스에 등록해둔 gitlab token으로 인증하는것이 되지 않아서
                # usernamePassword로 인증을 진행했다. 
                withCredentials([usernamePassword(credentialsId: 'jaehyeon', usernameVariable: 'GITLAB_USERNAME', passwordVariable: 'GITLAB_PASSWORD')]) {
                    script {
                        sh  '''
                            git fetch https://${GITLAB_USERNAME}:${GITLAB_PASSWORD}@깃 주소
                            '''
                    }
                }
                # 이 스크립트를 통해서 바뀐 폴더의 이름들을 쫙 가져온다.
                script{
                    echo "체크 시작합니다"
                    changedFiles = sh(script: "git diff --name-only ${currentBranch}..origin/${currentBranch}", returnStdout: true).trim().tokenize('\n').collect { it.split('/')[0..-2]}
                    changedFolders = changedFiles.flatten().unique()
                    changedFolders.each {folder-> echo "Flatten Folders : ${folder}"}
                    echo "체크 끝났습니다"
                }
            }
        }
        
        
        stage('Git pull') {
            steps {
                // Get some code from a GitHub repository
                checkout([$class: 'GitSCM', 
                    branches: [[name: '*/feature/project-api']],
                    doGenerateSubmoduleConfigurations: false,
                    extensions: [
                        [$class: 'SparseCheckoutPaths',  sparseCheckoutPaths:[[$class:'SparseCheckoutPath', path:'BE/ProjectService']]]
                                ],
                    submoduleCfg: [],
                    userRemoteConfigs: [[credentialsId: 'jaehyeon', url: '깃 주소']]])
            }
        }
        
        stage('build') {
            when {
            	# expression의 조건을 통해서 폴더 이름중에 ProjectService가 있나 확인한다. 
                # 없다면 빌드가 진행되지 않는다. 
                expression {
                    return changedFolders.contains("ProjectService")
                }
            }
            steps{
                dir('./BE/ProjectService'){
                    withMaven {
                        sh "mvn clean compile package -DskipTests -Dmaven.test.skip=true"
                    }
                }
            }
        }
        
        stage('deploy') {
            when {
                expression {
                    return changedFolders.contains("ProjectService")
                }
            }
            steps {
                dir('./BE/ProjectService'){
                    sh "pwd"  
                    sh "chmod +x ./feature.sh  && ./feature.sh"
                }
            }
        }
    }
}