배경
Script를 수정하면서 매번 env 그리고 params가 헷갈렸다. 어디는 env… 어디는 params… 어디는 def… 그래서 이왕 블로그를 시작하는 김에 어떤 차이가 있는지 확인해 보려고 한다.
Params
사용하는 방법은 다음과 같다.
params.BRANCH
params.REQUEST_TYPEparams는 Jenkins Job 또는 Declarative Pipeline의 parameters에서 정의한 Build Parameter를 가져온다. 읽기 전용 Map이며 Boolean이나 String과 같은 원래 Parameter Type을 유지한다.
parameters {
string(name: 'BRANCH', defaultValue: 'main')
choice(name: 'REQUEST_TYPE', choices: ['plan', 'apply'])
booleanParam(name: 'DRY_RUN', defaultValue: true)
}
params.BRANCH
params.REQUEST_TYPE
params.DRY_RUNBuild Parameter는 Environment Variable로도 Export될 수 있다. 하지만 Pipeline Groovy Code에서는 어떤 값인지 명확하게 보이도록 params.BRANCH로 사용하는 것이 좋다.
Env
env.TEMP_WORKSPACEenv는 Jenkins에서 제공하거나 Pipeline에서 정의한 Environment Variable이다. 모든 값은 String으로 사용된다.
Declarative Pipeline에서는 top-level environment가 전체 Pipeline에, stage 안의 environment가 해당 stage에 적용된다. 일부 step에만 임시로 적용하려면 withEnv를 사용한다.
pipeline {
agent any
environment {
APP_ENV = 'dev'
}
stages {
stage('Build') {
environment {
BUILD_MODE = 'release'
}
steps {
echo "${env.APP_ENV} / ${env.BUILD_MODE}"
withEnv(['TEMP_FLAG=true']) {
echo env.TEMP_FLAG
}
}
}
}
}Def
일반적인 변수 선언과 동일하게 동작한다.
def workspacedef는 Groovy의 지역 변수이다. String뿐만 아니라 List, Map 등 여러 Type을 사용할 수 있고 선언한 Scope 안에서만 사용할 수 있다.
이 중 가장 헷갈렸던 것은 Env와 Def다. 2개 모두 Script 내부에서 선언하고 사용할 수 있고, env 또는 params로 선언한 값도 일부 코드에서는 Prefix 없이 사용하고 있었다. Script를 많이 다뤄보지 않은 입장에서는 헤메게 되는 경우였다.
env.나 params.가 없어도 동작하는 경우는 Jenkins의 Binding과 Environment Variable Export가 섞여서 값이 확인되는 경우였다. 동일한 이름의 지역 변수가 생기면 다른 값을 볼 수도 있기 때문에 생략하지 않는 것이 안전하다.
// params.BRANCH = 'develop' // params는 읽기 전용이므로 변경하지 않는다.
env.SOMETHING = 'HELLO WORLD'
def something = 'hello world'
echo env.SOMETHING
echo params.BRANCH
echo something대문자 환경 변수를 ${SOMETHING}으로 사용해도 동작하는 경우가 있지만 env.SOMETHING으로 사용하는 것이 어디에서 나온 값인지 확인하기 쉽다.
특징
그렇다면 이 3개의 차이점은 무엇일까.
- params
- Build Parameter로 Jenkins Job 또는
parameters에서 정의한다. - 읽기 전용으로 변경할 수 없다.
- Build 전체에서 사용할 수 있다.
- 원래 Parameter Type을 유지한다.
- Build Parameter로 Jenkins Job 또는
- env
- Jenkins System,
environment,env.[변수명],withEnv를 통해 정의한다. - Script 내부에서 변경할 수 있다.
- 값은 String으로 사용된다.
- 정의한 위치에 따라 Pipeline 전체, Stage, Block 안에서 사용할 수 있다.
- Jenkins System,
- def
- 일반적인 Groovy 지역 변수이다.
- Script 내부에서 변경할 수 있다.
- 선언한 Scope 안에서만 사용할 수 있다.
- Shared Library에서 필요하다면 Parameter로 전달해야한다.
위 특징들을 표로 표현하면 다음과 같다.
| 구분 | params | env | def |
|---|---|---|---|
| 정체 | 빌드 파라미터 Map | 환경 변수 namespace | Groovy 지역 변수 |
| 정의 | Job 설정 또는 parameters | Jenkins 기본값, environment, env.VAR, withEnv | def VAR |
| 변경 | 읽기 전용 | 변경 가능 | 변경 가능 |
| 범위 | 빌드 전체 | 정의 위치에 따라 전체 Pipeline·stage·block | 선언된 lexical scope |
| 타입 | 파라미터 타입 유지 | String | 임의의 Groovy 타입 |
| shared library | Pipeline context에서 접근 가능하지만 명시적 전달 권장 | Pipeline context에서 접근 가능하지만 명시적 전달 권장 | scope 밖에서는 직접 접근 불가, 인자로 전달 |
Shared Library에서 Jenkinsfile의 지역 변수를 자동으로 확인할 수 있다고 생각하면 안된다. 필요한 값은 아래와 같이 Parameter로 전달하는 것이 좋다.
// Jenkinsfile
deployApp(params.REQUEST_TYPE, env.APP_ENV)
// vars/deployApp.groovy
def call(String requestType, String appEnv) {
echo "requestType=${requestType}, appEnv=${appEnv}"
}선택 기준
이런 특징들이 있다보니, 상황에 맞게 변수 설정을 선택해서 진행해야 한다.
- 사용자가 빌드 시작 시 선택해야 하는 값:
params - shell, tool, 하위 process에 전달해야 하는 문자열 값:
env - 계산 중간값, List/Map, 객체, 함수 내부 상태:
def - secret: 평문
env할당 대신 Jenkins Credentials와credentials()또는withCredentials사용