Tech

Jenkins Declarative pipeline 입문하기

태산곰 2022. 10. 19. 14:07

Jenkins 소개

Jenkins는 소프트웨어 구축, 테스트, 전달 및 배포와 관련된 모든 종류의 작업을 자동화하는데 사용할 수 있는 오픈 소스 자동화 서버로 jenkins외에 bamboo, JetBrains TeamCity, buddy 등이 있으나, 다른 건 비용이 비싸고 도입하기 어려운 반면, 막강한 기능임에도 무료인 jenkins가 가장 많이 사용되고 있고 우리도  jenkins를 쓰고 있다.

 

Jenkins 장점

  1. 무료!
  2. 사용자가 많아서 정보가 많다.
  3. 사용하기 쉽다.
  4. 많은 플러그인 (Pipeline도 플러그인임)

 

Jenkins Pipeline 필요성과 장점

https://www.jenkins.io/doc/book/pipeline/를 보면 아래와 같이 언급하고 있다.

Jenkins is, fundamentally, an automation engine which supports a number of automation patterns. Pipeline adds a powerful set of automation tools onto Jenkins, supporting use cases that span from simple continuous integration to comprehensive CD pipelines. By modeling a series of related tasks, users can take advantage of the many features of Pipeline.

요약하면, Pipeline을 사용하면 복잡한 매우 Job도 잘 구성할 수 있다는 것이다.

글쓴이가 느끼는 장점은 다음과 같다.

 

  • Job 설정을 code 로 저장할 수 있다.
    • 저장된 code는 git 등의 SCM을 사용해서 version control이 가능하다.

 

  • Job을 Stage별로 구분할 수 있다.
    • build, test, deploy 등 ...
    • 각 stage 들은 서로 다른 agent에서 동시에 실행이 가능하다.
    • Job 실패 시, 실패한 Stage부터 다시 실행이 가능하다.

 

Declarative vs Scripted pipeline

Jenkins pipeline에 대해서 검색하다보면 다음의 두 가지 형태를 확인할 수 있다.

  • declarative
pipeline {
    ...
}
  • scripted
node("myAgent") {
	....
}

declarative 방식이 좀 더 최근에 추가된 기능이고, 본 글에서는 declarative 방식에 대해서만 다룬다.

 

어떻게 생겼는지 한번 보자.

1. 새로운 아이템

2. Pipeline 만들기

3. Pipeline Tab 선택, "try sample Pipeline..." 에서 "Hello World" 선택

4. 저장 후, "지금 빌드" 실행 그리고 "Build History" 에서 실행 결과 확인

Script 좀 더 확인하기

script를 확인하면 agent, stages, stage, steps와 echo의 구문으로 구성되어 있다.

agent 구문은 일단 무시하기로 하자.

stage는 job을 build, test, deploy와 같은 좀 큰 단계들로 구분지어 놓았다고 생각하면 된다.

각 stage는 echo와 같은 많은 step들로 구성되어 있다.

 

Variable

Job 설정에서 Jenkins에서 기정의해둔 pre-defined variable과 user-defined variable을 사용할 수 있다.

pre-defined variable은 다음 위치에서 확인가능하다.

  • <Jenkins-url>/env-vars.html

pre-defined varible을 하나 참조해보자

pipeline {
    agent any
    
    stages {
        stage('Hello') {
            steps {
                echo "BUILD_NUMBER IS ${BUILD_NUMBER}"
            }
        }
    }
}

주의) 문자열을 single quotation이 아니고 double quotation으로 표현했다. single quotation으로 표현하면 문자열 대체가 발생하지 않는다.

 

사용자 변수는 environment 구문을 사용해서 정의한다.

pipeline {
    agent any
    
    environment {
        TOOL_NAME = "Jenkins"
    }
    
    stages {
        stage('Hello') {
            steps {
                echo "BUILD_NUMBER IS ${BUILD_NUMBER}"
                echo "TOOL_NAME is ${TOOL_NAME}"
            }
        }
    }
}

위의 경우 변수가 pipeline (global) level 에 정의된 경우고, stage level 에도 정의할 수 있다.

pipeline {
    agent any
    
    environment {
        TOOL_NAME = "Jenkins"
    }
    
    stages {
        stage('Hello') {
            environment {
               END_POINT = "some-where"
            }
            
            steps {
                echo "BUILD_NUMBER IS ${BUILD_NUMBER}"
                echo "TOOL_NAME is ${TOOL_NAME}"
                echo "END_POINT is ${END_POINT}"
            }
        }
    }
}

steps 에서 script 구문을 사용해서 변수를 새로 정의 (혹은 변경) 할 수 있다.

pipeline {
    agent any
    
    environment {
        TOOL_NAME = "Jenkins"
    }
    
    stages {
        stage('Hello') {
            environment {
               END_POINT = "some-where"
            }
            
            steps {
                echo "BUILD_NUMBER IS ${BUILD_NUMBER}"
                echo "TOOL_NAME is ${TOOL_NAME}"
                echo "END_POINT is ${END_POINT}"
                script {
                    END_POINT = 'new-end-point'
                    END_POINT2 = 'second-end-point'
                }
                echo "END_POINT is ${END_POINT}"
                echo "END_POINT2 is ${END_POINT2}"
            }
        }
    }
}

BUILD_NUMBER IS 6
TOOL_NAME is Jenkins
END_POINT is some-where
END_POINT is new-end-point
END_POINT2 is second-end-point

주의) script 구문으로 정의된 변수는 이어지는 stage들에도 계속 존속하는 것으로 확인된다???

pipeline {
    agent any
    
    environment {
        TOOL_NAME = "Jenkins"
    }
    
    stages {
        stage('Hello') {
            environment {
               END_POINT = "some-where"
            }
            
            steps {
                echo "BUILD_NUMBER IS ${BUILD_NUMBER}"
                echo "TOOL_NAME is ${TOOL_NAME}"
                echo "END_POINT is ${END_POINT}"
                script {
                    END_POINT = 'new-end-point'
                    END_POINT2 = 'second-end-point'
                }
                echo "END_POINT is ${END_POINT}"
                echo "END_POINT2 is ${END_POINT2}"
            }
        }
        stage('World') {
            steps {
                echo "END_POINT in World is ${END_POINT}"
                echo "END_POINT2 in World is ${END_POINT2}"
            }
        }
    }
}

BUILD_NUMBER IS 7
TOOL_NAME is Jenkins
END_POINT is some-where
END_POINT is new-end-point
END_POINT2 is second-end-point
END_POINT in World is new-end-point
END_POINT2 in World is second-end-point

 

script 구문을 사용해서 변수를 정의한 경우에 environment에 정의된 변수가 가리게 되는데, 가려진 변수를 참조하려면 env.변수이름 구문을 사용한다.

pipeline {
    agent any
    
    stages {
        stage('Hello') {
            environment {
               END_POINT = "some-where"
            }
            
            steps {
                echo "BUILD_NUMBER IS ${BUILD_NUMBER}"
                echo "END_POINT is ${END_POINT}"
                script {
                    END_POINT = 'local-end-point'
                }
                echo "local END_POINT is ${END_POINT}"
                echo "stage END_POINT is ${env.END_POINT}"
            }
        }
    }
}

BUILD_NUMBER IS 8
END_POINT is some-where
local END_POINT is local-end-point
stage END_POINT is some-where

Parameters

Job parameter는 기존과 같이 ui로 설정할 수도 있고, code로 설정할 수도 있다.

parameter는 variable과 같은 방법으로 대체된다.

pipeline {
    agent any
    
    parameters {
        string(name: 'TOOL', defaultValue: 'Mr Jenkins', description: 'Who should I say hello to?')
        text(name: 'DESC', defaultValue: '', description: 'Enter some information about the person')
        booleanParam(name: 'SONAR', defaultValue: true, description: 'Toggle this value')
        choice(name: 'STAGE', choices: 'BUILD\nTest\nDeploy', description: 'stage')
        password(name: 'PASSWORD', defaultValue: 'SECRET', description: 'Enter a password')
        file(name: 'FILE', description: 'Choose a file')
    }
    
    stages {
        stage('Hello') {
            steps {
                echo "TOOL is ${TOOL}"
            }
        }
    }
}

주의) parameter를 code로 설정한 경우, 변경 사항이 바로 반영되지 않는다. 한번 실행후에 "parameter와 함께 빌드"에 반영된다.

다음 번에는

retry, timeout, job schedule 및 다른 job build 호출하는 등의 기능에 대해서 정리해보도록 하자.