참고
Jenkins pipeline 문법
NOTE
Jenkins Pipeline이란 복잡한 CI/CD 파이프라인의 Jenkins 통합을 지원하는 플러그인 셋이다!
•
Groovy 코드형태(Jenkinsfile)로 빌드/배포 스텝을 정의하기 때문에, Jenkins Job설정을 SCM에 저장하여 형상 관리와 리뷰가 가능하다.
•
Job의 실행 흐름을 세밀하게 컨트롤할 수 있다.
FreeStyle Job vs 파이프라인
NOTE
GUI vs 코드라고 생각하면 된다.
FreeStyle Job
•
미리 규정된 스텝을 사용하여 빌드/배포 실행
•
UI를 통해 조작 가능하므로 사전지식이 많이 필요하지 않다.
•
설정에 대한 형상관리가 불가능하다.
Pipeline
•
자유롭게 스텝을 정의하고 복잡한 CI/CD 수준의 컨트롤이 가능하다.
•
state별로 별도의 agent를 사용할 수 있다.
•
사용자의 입력을 받기 위해 중지/재시작이 가능하고, 재부팅 시에도 실패한곳에서 재시작한다.
•
설정을 코드로 관리하므로 SCM을 사용한 형상관리가 가능해진다.
젠킨스 파이프라인 작성
Groovy 기초
NOTE
Groovy는 JVM위에서 동작하는 동적 타입 프로그래밍 언어이며, Java의 슈퍼셋 문법과 DSL과 단순화된 문법을 지원한다!
a = 3
b = 4
// ""(변수 출력) ''(변수 무시)
println("a=${a}")
println("a=$a")
println('b=${b}')
println("""
a=${a}
b=${b}
""")
println('''
a=${a}
b=${b}
''')
// ${ } 내부에는 어떤 평가식도 사용 가능
println("""a + b + " WOW"= ${(a + b) + " WOW"}""")
// 자바와는 달리 스트링이 같은지 비교를 == 를 사용하여 처리 가능
a = "hello"
b = "hell"
if (a == (b + "o")) {
println("두 스트링이 같습니다.")
}
Groovy
복사
변수 사용
// 메소드는 def 함수명(파라미터) { ... } 로 정의
def plus(a, b = 0) {
return a + b
}
// 메소드 실행후 결과를 볼 수 있음, 심지어는 ${} 내부에서도 사용 가능
println("plus(a, b) = " + plus(a, b) + " WOW")
println("""plus(a, b) = ${plus(a, b) + " WOW "} """)
// return 을 쓰지 않으면 마지막 평가결과가 리턴
def multiple(a, b) {
a * b
}
// param으로 한번에 받기 가능
def multiply(param) {
param.a * param.b
}
// 한 라인에 기록되어 있고, 호출 혼란 여지가 없다면 ( ) 생략 가능
e = multiply c, d
println(e)
e = multiply a=c, b=d
println(e)
e = multiply a:c, b:d
println(e)
Groovy
복사
함수 사용
// 리스트
list = [1, 2, 3, 4]
// 리스트 출력
println(list)
println(list[0])
// 리스트를 다른 형태로 변환
println(list.collect { it + 3 } )
// 맵
map = ["hello":"world", "my name is": "juno"]
// 맵 출력
println(map)
println(map["hello"])
// 맵을 다른 형태로 변환
println(map.collectEntries { k, v ->
[k.toUpperCase(), v.toUpperCase()]
})
// Java 클래스 사용
import java.util.Date
// 자바와 동일하게 메소드 호출 가능
println(new Date().getHours())
// get~~ 메소드인 경우에는 프로퍼티 처럼 호출 가능
println(new Date().hours)
// Jenkins instance 접근. Sandbox 에서 사용 불가
instance = Jenkins.instance
println(instance.pluginManager.plugins)
instance.items.each {
println(it.name)
}
Groovy
복사
자료구조 사용
stages / stage / steps
NOTE
stages / stage
•
stages는 다수개의 stage를 포함할 수 있다.
•
stage는 stages / parallel / matrix / steps중 하나를 포함할 수 있다.
steps
pipeline {
agent any
stages {
stage('Hello') {
steps { // 실제 실행 작업
echo 'Hello World'
}
}
}
}
Groovy
복사
•
steps은 각 stage에서 실제로 실행할 1개 이상의 작업을 지정한다.
post
NOTE
pipeline {
agent any
stages {
// ...
}
post {
always { // 항상 실행
echo "This will always run"
}
success { // 빌드 성공시
echo "This will run when the run finished successfully"
}
failure { // 빌드 실패시
echo "This will run if failed"
}
unstable { // 빌드 unstable
echo "This will run when the run was marked as unstable"
}
changed { // 지난번과 다른 빌드 결과 발생시
echo "This will run when the state of the pipeline has changed"
}
fixed { // 이전에 성공했으나 이번에 실패한 경우
echo "This will run when the state of the pipeline has changed"
}
}
}
Groovy
복사
•
post는 FreeStyle의 빌드 후 조치에 해당하는 항목이다.
agent / options / environments / tools
NOTE
agent / options / environment / tools는 파이프라인 하위(전역) 또는 stage에 위치할 수 있다!
agent(실행환경)
pipeline {
agent none // 파이프라인 전체에 대해 agent를 지정하지 않음. 각 stage에서 개별적으로 agent를 지정해야 함
stages {
stage('Example') {
agent { // 이 stage를 위한 agent를 지정
docker {
image 'maven:3.9.0-eclipse-temurin-11' // 사용할 도커 이미지
label 'my-defined-label' // Jenkins에서 빌드를 할 agent의 라벨
args '-v /tmp:/tmp' // 도커 실행 시 추가할 파라미터
}
}
steps {
// 빌드 명령 실행
sh 'mvn clean package'
}
}
}
}
Groovy
복사
maven의존성을 docker 이미지로 사용한다.
•
pipeline 또는 stage에서 사용할 에이전트를 지정할 수 있다.
•
ex) docker, kubernetes, node, any …
environment
- env
env.BUILD_NUMBER
env.BUILD_URL
env.JOB_URL
env.WORKSPACE
- params
if (params.getOrDefault('BOOLEAN_PARAM_NAME', true)) {doSomething()}
- currentBuild
currentBuild.number
currentBuild.currentResult
currentBuild.projectName
currentBuild.absoluteUrl
Groovy
복사
pipeline에서 제공해주는 전역변수
pipeline {
agent any
environment {
// 파이프라인 전역에 적용될 환경 변수
MAVEN_HOME = '/usr/local/maven' // 예제로 사용되는 Maven 홈 디렉터리 경로
}
stages {
stage('Build') {
environment {
// 이 스테이지에만 적용될 환경 변수
DB_USERNAME = credentials('db-username') // 데이터베이스 사용자 이름에 대한 자격증명
DB_PASSWORD = credentials('db-password') // 데이터베이스 비밀번호에 대한 자격증명
}
steps {
echo "Building with Maven"
// 환경 변수를 사용하여 Maven 명령 실행
sh "${env.MAVEN_HOME}/bin/mvn clean package -Ddb.username=${env.DB_USERNAME} -Ddb.password=${env.DB_PASSWORD}"
}
}
}
}
Groovy
복사
•
pipeline 또는 stage에서 사용할 환경변수 지정한다.
•
Groovy 스크립트에서는 env.변수명, 문자열에서는 ${변수명}으로 참조가능하다.
tools
pipeline {
agent any
tools {
// Jenkins에 설정된 툴의 이름을 사용합니다.
// 'Git'와 'Maven'은 Jenkins에 미리 설정되어 있어야 합니다.
maven 'Maven 3.6.0'
git 'Git 2.20.1'
}
stages {
stage('Checkout') {
steps {
// Git 리포지토리로부터 소스 코드를 체크아웃합니다.
git url: 'https://github.com/your/repo.git', branch: 'master'
}
}
stage('Build') {
steps {
// Maven을 사용하여 프로젝트를 빌드합니다.
sh 'mvn clean package'
}
}
stage('Test') {
steps {
// 테스트 단계에서는 단위 테스트를 실행할 수 있습니다.
sh 'mvn test'
}
}
}
}
Groovy
복사
mavne, git 2가지의 tool사용
•
pipeline에서 사용할 도구를 지정한다.
•
Global Tool Configuration에서 툴의 이름과 버전을 설정할 수 있다.
triggers
triggers {
pollSCM('*/5 * * * *') // 5분마다 SCM 확인
upstream( // 다른 프로젝트(상위 프로젝트)의 빌드가 성공하면 실행
upstreamProjects: 'UpstreamProjectName',
threshold: hudson.model.Result.SUCCESS
)
githubPush() // GitHub push 이벤트에 의해 실행
}
Groovy
복사
pipeline {
agent any
triggers {
pollSCM('*/5 * * * *') // 5분마다 SCM 확인
}
stages {
stage('Example') {
steps {
echo 'Checking for SCM changes.'
}
}
}
}
Groovy
복사
when / input /script
NOTE
when
when {
// 'main' 브랜치일 때만 실행
branch 'main'
// 환경 변수 DEPLOY_ENV가 'production'일 때만 실행
environment name: 'DEPLOY_ENV', value: 'production'
// 변경 요청이 있을 때만 실행
changeRequest()
// Groovy 함수를 사용한 복잡한 조건 평가
expression {
return someComplexCondition()
}
// 여러 조건 조합
allOf {
branch 'develop'
environment name: 'DEPLOY_ENV', value: 'staging'
}
}
Groovy
복사
pipeline {
agent any
stages {
stage('Only on Production') {
when {
// 환경 변수 DEPLOY_ENV가 'production'일 때만 실행
environment name: 'DEPLOY_ENV', value: 'production'
}
steps {
echo 'Deploying to production environment.'
}
}
}
}
Groovy
복사
•
steps 앞에 위치하며 steps의 실행 여부를 판단한다.
input / script
pipeline {
agent any
stages {
stage('Example') {
steps {
script {
// 여기서 변수 선언과 로직 처리
def userInput = input(
message: "Should we deploy to production?",
ok: "Yes, we should.",
submitter: "alice,bob",
parameters: [
string(name: 'DEPLOY_ENV', defaultValue: 'production', description: 'The environment to deploy to')
]
)
def deployEnv = params.DEPLOY_ENV
// 사용자 입력에 따라 행동
echo "Deploying to ${deployEnv}..."
}
}
}
}
}
Groovy
복사
•
input은 steps 앞에 위치하여 입력받으며, when과 혼합해서 사용할 수 있다.
•
scripts은 steps 내에서 자유롭게 groovy 스크립트를 사용할 수 있다.