====== Jenkins Pipeline ======
* [[ci:jenkins|Jenkins]] [[https://jenkins.io/doc/book/pipeline/|Pipeline]]
* **Declarative**와 Scripted 파이프라인 두 종류가 있는데, 최신 버전이고 가독성이 더 높은 **Declarative**를 사용하는 것이 좋다.
* [[https://jenkins.io/doc/book/pipeline/|Jenkins Pipeline Documentation]]
* [[https://jenkins.io/solutions/pipeline/|Pipeline as Code with Jenkins]]
* [[https://dzone.com/storage/assets/413450-rc218-cdw-jenkins-workflow.pdf|Jenkins Pipeline RefCards]]
* [[https://jenkins.io/doc/pipeline/steps/|Pipeline Steps]] : 각종 Step 설명서
* [[https://jenkins.io/doc/pipeline/examples/|Pipeline Examples]]
* [[https://jenkins.io/doc/book/pipeline/syntax/|Pipeline 문법]]
===== Snippet Generator =====
* ''$JENKINS_URL/pipeline-syntax/'' 에서 각 스텝별로 UI로 구성해서 pipeline script snippet 을 만들수있다.
===== lint =====
* [[https://www.youtube.com/watch?v=9IjKUGn2TIk|How to Lint Jenkins Declarative Pipelines From the Command Line - YouTube]]
* [[https://www.jenkins.io/doc/book/pipeline/development/|Pipeline Development Tools]]
* [[ci:jenkins:cli|Jenkins CLI]] 에서 ''declarative-linter'' 명령으로 lint
===== 기본 환경변수 =====
* ''env.JOB_NAME''
* ''env.BUILD_NUMBER''
* ''env.BUILD_URL''
===== Build Parameter =====
* [[https://www.cyotek.com/blog/using-parameters-with-jenkins-pipeline-builds|Using parameters with Jenkins pipeline builds - Articles and information on C# and .NET development topics • Cyotek]]
* ''params.PARAMETER_NAME''
* ''env.PARAMETER_NAME''
===== Notification =====
* [[https://jenkins.io/blog/2017/02/15/declarative-notifications/|Declarative Pipeline: Notifications and Shared Libraries]] 선언적 형태에서 notification
* [[https://jenkins.io/blog/2016/07/18/pipeline-notifications/|Sending Notifications in Pipeline]] : 코드 형태에서 notification
===== Archive Artifact =====
* [[https://jenkins.io/doc/pipeline/tour/tests-and-artifacts/|Recording tests and artifacts]]
post {
always {
archiveArtifacts artifacts: 'build/libs/**/*.jar', fingerprint: true
junit 'build/reports/**/*.xml'
}
}
===== 변수 및 Script in Declarative =====
* Scripted pipeline 은 자유롭게 스크립팅할 수 있지만 선언적 방식은 제약이 있어서 변수 선언등을 함부로 할 수 없다.
* [[https://stackoverflow.com/questions/39832862/jenkins-cannot-define-variable-in-pipeline-stage|groovy - Jenkins: Cannot define variable in pipeline stage - Stack Overflow]]
pipeline {
agent any
environment {
MY_ENV = "${env.BRANCH_NAME}"
}
// 아래에서 MY_ENV 변수로 사용
}
* Scripting을 하려면 ''steps''에서 ''script'' 블록을 둔다.
steps {
echo 'Building Container..'
script {
if (ENVIRONMENT_NAME == 'development') {
ENV_NAME = 'Development'
} else if (ENVIRONMENT_NAME == 'release') {
ENV_NAME = 'Production'
}
}
echo 'Building Branch: ' + env.BRANCH_NAME
echo 'Build Number: ' + env.BUILD_NUMBER
echo 'Building Environment: ' + ENV_NAME
echo "Running your service with environemnt ${ENV_NAME} now"
}
===== 강제 상태변경 =====
* 상태를 ''SUCCESS'', ''UNSTABLE'', ''FAILURE''로 변경가능하다.
* ''error "메시지"'' : 상태를 ''FAILURE''로 변경하면서 메시지 출력
혹은 직접 지정
currentBuild.result = 'UNSTABLE' // SUCCESS, UNSTABLE, FAILURE
===== Git Branch Parameter =====
* Git Branch 를 Job Parameter로 지정하고자 한다면, **Lightweight checkout**을 꺼야 한다.
* ''GIT_BRANCH''가 Job 파라미터 이름
stage('Git Checkout') {
steps {
git poll: true,
changelog: true,
url: 'git@github.com:....git',
branch: params.GIT_BRANCH
credentialsId: '...'
}
}
===== Pipeline 에서 입력 값 받기 =====
* [[https://www.youtube.com/channel/UCKlF3GIFy9KVUefVbycx_vw|What Is an Input in Jenkins? - YouTube]]
* **입력 값은 ''agent none'' 으로 받고, 후속 작업에 대해서 ''agent''를 지정**해야 해당 agent가 입력에 의해 blocking 되는 것을 막을 수 있다.
===== JUnit 테스트 결과 메일/Slack 발송 =====
* [[https://stackoverflow.com/questions/39920437/how-to-access-junit-test-counts-in-jenkins-pipeline-project|groovy - How to access Junit test counts in Jenkins Pipeline project - Stack Overflow]] 참조. 테스트 필요.
* 호출하는 메소드가 금지돼 있어서 whitelist 에 추가 필요해 보임. Build 로그 메시지를 잘 보면, whitelist에 추가 시킬수 있는 admin 페이지로의(''http://jenkinshost/scriptApproval/'') 링크가 출력됨. 이것을 클릭하고서 추가한다.
* 그 뒤에 계속해서 메소드 하나하나마다 추가하라고 나오므로 ''$JENKINS_HOME/scriptApproval.xml''을 다음과 같이 편집하고 Jenkins를 재시작한다.
method hudson.model.Actionable getAction java.lang.Class
method hudson.model.Cause getShortDescription
method hudson.model.Run getCauses
method hudson.tasks.test.AbstractTestResultAction getFailCount
method hudson.tasks.test.AbstractTestResultAction getFailureDiffString
method hudson.tasks.test.AbstractTestResultAction getSkipCount
method hudson.tasks.test.AbstractTestResultAction getTotalCount
method org.jenkinsci.plugins.workflow.support.steps.build.RunWrapper getRawBuild
* 선언적 파이프라인 구성시에 최상단에(''pipeline' 블록 전에) import와 테스트 메시지용 변수를 미리 선언한다.
import jenkins.model.*
import hudson.tasks.test.AbstractTestResultAction
String testResultMessage = '테스트가 올바로 실행되지 못했음' // 이 변수에 테스트 메시지 저장
pipeline {
stages {
stage('Test Reports') {
steps {
junit '**/build/test-results/**/*.xml'
script {
AbstractTestResultAction testResultAction = currentBuild.rawBuild.getAction(AbstractTestResultAction.class)
if (testResultAction != null) {
def totalNumberOfTests = testResultAction.totalCount
def failedNumberOfTests = testResultAction.failCount
def failedDiff = testResultAction.failureDiffString
def skippedNumberOfTests = testResultAction.skipCount
def passedNumberOfTests = totalNumberOfTests - failedNumberOfTests - skippedNumberOfTests
testResultMessage = "Passed: ${passedNumberOfTests}; Failed: ${failedNumberOfTests} ${failedDiff}; Skipped: ${skippedNumberOfTests} out of ${totalNumberOfTests}"
}
}
}
}
}
post {
failure {
slackSend(channel: '#build-ci', color: '#FF0000', message: """빌드 실패: Job ${env.JOB_NAME} [${env.BUILD_NUMBER}] TargetBranch: ${params.GIT_BRANCH} (${env.BUILD_URL})
- 테스트 실패 : ${testResultMessage}
""")
}
}
}
===== parallel pipeline =====
* [[https://www.youtube.com/watch?v=6wNbjP2WUMo|How Do You Run Jenkins Steps in Parallel? - YouTube]]
* 여러 장비를 [[ci:jenkins:agent|Jenkins Agent ( slave )]]로 연결해서, 각 에이전트에서 동시에 pipeline을 실행할 수 있다.
* [[https://www.jenkins.io/doc/book/pipeline/syntax/#parallel|Pipeline Syntax]]
===== 참조 =====
* [[https://reidweb.com/2017/02/01/what-ive-learnt-about-jenkins-pipelines/|What I've learnt about Jenkins Pipelines]]