-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Writing Jenkinsfiles #148
Labels
Comments
Parallel StagesDeclarative Pipeline#!/usr/bin/env groovy
pipeline {
agent any
tools {
nodejs "nodejs12.13.0"
jdk "jdk11"
}
environment {
HOME = "${env.WORKSPACE}"
YARN_CACHE_FOLDER = "${env.HOME}/.yarn-cache"
/**
defined internal env
*/
npmCommand = "yarn"
}
options {
buildDiscarder(logRotator(
artifactDaysToKeepStr: '1',
artifactNumToKeepStr: '10',
daysToKeepStr: '3',
numToKeepStr: "10")
)
timestamps()
timeout(time: 30, unit: 'MINUTES')
}
stages {
stage('Checkout') {
steps {
echo "Branch: ${env.BRANCH_NAME}, PrBranch: ${env.CHANGE_BRANCH}"
sh "which node; npm --version; node --version; yarn -version"
sh 'which java; java -version; echo $JAVA_HOME'
sh "printenv"
}
}
stage('Install packages') {
steps {
sh "${npmCommand} install"
}
}
stage('Lint') {
steps {
sh "${npmCommand} run lint -- -f json -o eslint.json"
}
}
stage('parallel test') {
parallel {
stage('parallel-1') {
steps {
script {
sh "ls -al ${env.JAVA_HOME}/bin"
sh "which java; java -version; echo ${env.JAVA_HOME}
}
}
}
stage('parallel-2') {
steps {
script {
sh "ls -al ${env.JAVA_HOME}/bin"
sh "which java; java -version; echo ${env.JAVA_HOME}
}
}
}
}
}
}
} Scripted Pipelinenode {
/**
set tools
**/
env.NODEJS_HOME = tool name: 'nodejs12.13.0'
env.JAVA_HOME=tool name: 'jdk11'
env.PATH="${env.JAVA_HOME}/bin:${env.NODEJS_HOME}/bin:${env.PATH}"
/**
set cache node_modules
**/
env.YARN_CACHE_FOLDER = "${env.WORKSPACE}/.yarn-cache"
/**
defined internal env vars
**/
npmCommand = "yarn"
properties([
// 오래된 빌드 삭제
buildDiscarder(logRotator(
artifactDaysToKeepStr: '1',
artifactNumToKeepStr: '10',
daysToKeepStr: '3',
numToKeepStr: '10'
)),
])
timestamps {
timeout(time: 30, unit: 'MINUTES') {
stage ('Env') {
echo "Branch: ${env.BRANCH_NAME}, PrBranch: ${env.CHANGE_BRANCH}"
sh "which node; npm --version; node --version; yarn -version"
sh "which java; java -version; echo $JAVA_HOME"
sh "printenv"
}
stage ('Checkout') {
checkout scm
}
stage ('Install Dependencies') {
sh "${npmCommand} install"
}
stage ('Lint') {
sh "${npmCommand} run lint -- -f json -o eslint.json"
}
stage ('parallel test') {
def stages = [:]
stages['parallel-1'] = {
sh "ls -al ${env.JAVA_HOME}/bin"
sh "which java; java -version; echo ${env.JAVA_HOME}"
}
stages['parallel-2'] = {
sh "ls -al ${env.JAVA_HOME}/bin"
sh "which java; java -version; echo ${env.JAVA_HOME}"
}
parallel(stages)
}
}
}
} |
Declarative Pipeline Examples#!/usr/bin/env groovy
void setBuildStatus(String context, String message, String state, String url) {
if (state == 'PENDING') {
backref = "${env.RUN_DISPLAY_URL}"
} else {
backref = url
}
// step([
// $class: "GitHubCommitStatusSetter",
// reposSource: [$class: "ManuallyEnteredRepositorySource", url: "${env.GIT_URL}"],
// contextSource: [$class: "ManuallyEnteredCommitContextSource", context: "ci/jenkins/${context}"],
// errorHandlers: [[$class: "ChangingBuildStatusErrorHandler", result: "UNSTABLE"]],
// statusBackrefSource: [$class: "ManuallyEnteredBackrefSource", backref: backref],
// statusResultSource: [ $class: "ConditionalStatusResultSource", results: [[$class: "AnyBuildResult", message: message, state: state]] ]
// ]);
// To set publishChecks
title = 'Build Check'
if (state == 'PENDING') {
publishChecks title: title,
name: context,
status: 'IN_PROGRESS',
detailsURL: url
} else if (state != 'SUCCESS') {
publishChecks title: title,
name: context,
status: 'COMPLETED',
conclusion: 'FAILURE',
detailsURL: url
} else {
publishChecks title: title,
name: context,
detailsURL: url
}
}
void notifySlack(String message, String color) {
slackSend (channel: '#*******', color: color, message: message + ": Job '${env.JOB_NAME} [${env.BUILD_NUMBER}]' (${env.BUILD_URL})")
}
pipeline {
agent {
dockerfile { filename './build/Dockerfile' }
}
environment {
// npm_config_cache = "npm-cache"
HOME = "${env.WORKSPACE}"
// NPM_CONFIG_PREFIX = "${env.HOME}/.npm"
YARN_CACHE_FOLDER = "${env.HOME}/.yarn-cache"
/**
defined internal env
*/
npmCommand = "yarn"
isDevelop = "${env.BRANCH_NAME ==~ /(develop)/}"
isMainBranch = "${env.BRANCH_NAME ==~ /(master|develop|release.*)/}"
isPrBranch= "${env.BRANCH_NAME ==~ /^PR-\d+$/}"
isSonarCoverage= "${isMainBranch || env.isPrBranch && env.CHANGE_TARGET ==~ /(develop)/}"
coverageReportDir = "tests/coverages/reports"
junitReportFilename = 'test-junit-report.xml'
sonarReportFilename = 'test-sonar-report.xml'
buildUrl ="${env.BUILD_URL}"
storybookUrl = "*******"
// sonarQubeUrl = "http://*******/dashboard?id=*******&${isPrBranch == 'true' ? 'pullRequest=' + env.CHANGE_ID : 'branch=' + env.BRANCH_NAME.replaceAll('/', '%2F')}"
repository= "*******"
githubEndpoint= "*******"
}
options {
buildDiscarder(logRotator(artifactDaysToKeepStr: '1', artifactNumToKeepStr: '10', daysToKeepStr: '3',numToKeepStr: "10"))
timestamps()
timeout(time: 30, unit: 'MINUTES')
}
stages {
stage('Checkout') {
steps {
echo "Branch: ${env.BRANCH_NAME}, PrBranch: ${env.CHANGE_BRANCH}"
sh "which node; npm --version; node --version; yarn -version"
sh 'which java; java -version'
sh "printenv"
}
}
stage('Install dependencies') {
steps {
echo 'Installing dependencies...'
// sh "npm config set registry *******"
// sh "npm install"
// sh "npm ci --prefer-offline --no-audit"
sh "yarn config set registry *******"
sh "yarn install"
}
}
stage('Lint') {
environment {
context="lint"
}
steps {
script {
try {
sh "${npmCommand} run lint -- -f json -o eslint.json"
sh "${npmCommand} run lint -- -f checkstyle -o checkstyle-eslint.xml"
} catch (e) {
sh "${npmCommand} run lint"
}
}
}
post {
always {
recordIssues enabledForFailure: true, aggregatingResults: true, tool: checkStyle(pattern: 'checkstyle-eslint.xml')
}
}
}
stage('Build') {
parallel {
stage('App') {
environment {
context="build"
}
steps {
setBuildStatus("${context}", "${context} Progressing...", "PENDING", "${buildUrl}");
sh "${npmCommand} run build"
}
post {
always {
script {
if (currentBuild.currentResult != 'FAILURE') {
setBuildStatus("${context}", "${env.STAGE_NAME} Success", "SUCCESS", "${buildUrl}");
} else {
setBuildStatus("${context}", "${env.STAGE_NAME} Failed", "FAILURE", "${buildUrl}");
}
}
}
}
}
stage('Storybook') {
when {
expression { isMainBranch == 'true' }
}
environment {
context="storybook/build"
}
steps {
setBuildStatus("${context}", "${context} Progressing...", "PENDING", "${buildUrl}");
script {
withCredentials([string(credentialsId: 'ZEPLIN_TOKEN', variable: 'TOKEN')]) {
sh "STORYBOOK_ZEPLIN_TOKEN=${TOKEN} ${npmCommand} run storybook:build"
}
}
}
post {
always {
script {
if (currentBuild.currentResult != 'FAILURE') {
setBuildStatus("${context}", "${env.STAGE_NAME} Success", "SUCCESS", "${buildUrl}");
} else {
setBuildStatus("${context}", "${env.STAGE_NAME} Failed", "FAILURE", "${buildUrl}");
}
}
}
}
}
}
}
// stage('Test') {
// parallel {
stage('Unit Test') {
environment {
context="unit"
}
steps {
sh "${npmCommand} run test:unit:coverage --detectOpenHandles"
}
post {
always {
script {
junit "${coverageReportDir}/${context}/${junitReportFilename}"
}
}
}
}
stage('Storyshot') {
environment {
context="storybook/snapshot-test"
}
steps {
// setBuildStatus(context, "${context} Progressing...", "PENDING", "${buildUrl}");
catchError(buildResult: 'UNSTABLE', stageResult: 'FAILURE') {
script {
try {
// sh "${npmCommand} run test:storybook:coverage"
sh "${npmCommand} run test:storybook"
} catch (e) {
// setBuildStatus("${context}", "${context} Failed", "FAILURE", "${buildUrl}");
error e.message
}
}
}
}
post {
always {
script {
junit "${coverageReportDir}/storybook/${junitReportFilename}"
}
}
// success {
// setBuildStatus("${context}", "${context} Pass", "SUCCESS", "${buildUrl}");
// }
}
}
// }
// }
stage('Report') {
parallel {
stage('Coverage Report to CI') {
steps {
sh "${npmCommand} run combine-coverage"
script {
step([$class: 'CoberturaPublisher', coberturaReportFile: "${coverageReportDir}/combined/cobertura-coverage.xml"])
}
}
}
stage('SonarQube Analysis') {
when {
expression { isSonarCoverage == 'true' }
}
environment {
scannerHome = tool 'SonarQubeScanner'
}
steps {
script{
withCredentials([string(credentialsId: '*******', variable: 'TOKEN')]) {
withSonarQubeEnv('SonarQubeServer') {
def args = ''
if (isPrBranch == 'true') {
args = args + " \
-Dsonar.pullrequest.key=${env.CHANGE_ID} \
-Dsonar.pullrequest.branch=${env.CHANGE_BRANCH} \
-Dsonar.pullrequest.base=${env.CHANGE_TARGET} \
-Dsonar.pullrequest.provider=github \
-Dsonar.pullrequest.github.repository=${repository} \
-Dsonar.pullrequest.github.endpoint=${githubEndpoint} \
"
} else {
args = args + " \
-Dsonar.branch.name=${env.BRANCH_NAME} \
"
}
// -Dsonar.testExecutionReportPaths='${coverageReportDir}/unit/test-sonar-report.xml,${coverageReportDir}/storybook/test-sonar-report.xml' \
sh "BROWSERSLIST_IGNORE_OLD_DATA=true ${scannerHome}/bin/sonar-scanner \
-Dsonar.projectKey=******* \
-Dsonar.projectName=******* \
-Dsonar.sources=./src \
-Dsonar.exclusions='./build,./cypress,./tests,./src/assets,./src/xlt,./src/lib,./src/config,./src/languages,**/*.stories.js,**/*.stories.tsx,**/__snapshots__,**/*.snap.js' \
-Dsonar.tests=./src \
-Dsonar.test.inclusions='**/*.test.tsx,**/*.test.ts,**/*.test.js,**/*.spec.ts,**/*.spec.tsx' \
-Dsonar.testExecutionReportPaths='${coverageReportDir}/unit/${sonarReportFilename},${coverageReportDir}/storybook/${sonarReportFilename}' \
-Dsonar.javascript.lcov.reportPaths=${coverageReportDir}/combined/lcov.info \
-Dsonar.eslint.reportPaths=eslint.json \
-Dsonar.typescript.tsconfigPath=tsconfig.json \
${args} \
"
}
}
}
}
}
}
}
stage('Deploy') {
parallel {
stage('Storybook image snapshot Test') {
when {
expression { isMainBranch == 'true' }
}
environment {
context="storybook/snapshot-image-test"
}
steps {
setBuildStatus(context, "${context} Progressing...", "PENDING", "${buildUrl}");
catchError(buildResult: 'UNSTABLE', stageResult: 'FAILURE') {
script {
try {
sh "${npmCommand} run test:image-snapshot"
} catch (e) {
setBuildStatus("${context}", "${context} Failed", "FAILURE", "${buildUrl}");
error e.message
}
}
}
}
post {
success {
setBuildStatus("${context}", "${context} Pass", "SUCCESS", "${buildUrl}");
}
}
}
stage('Deploy Storybook') {
when {
expression { isMainBranch == 'true' }
}
environment {
context="storybook/deploy"
host = "*******"
outputDir = ".out"
branchName = "${env.BRANCH_NAME.split("/")[0]}"
deployTempDir = "/tmp/jenkins_tmp/*******/${env.GIT_BRANCH}"
deployTargetDir = "~/deploy/storybook-*******/${env.branchName}"
}
steps {
setBuildStatus(context, "${context} Progressing...", "PENDING", "${buildUrl}");
script {
def remote = [:]
remote.name = "*******"
remote.host = "*******"
remote.allowAnyHosts = true
withCredentials([sshUserPrivateKey(credentialsId: 'jenkins-private-key', keyFileVariable: 'identity')]) {
remote.user = '*******'
remote.identityFile = identity
remote.logLevel = 'INFO'
sshCommand remote: remote, command: "mkdir -p ${deployTempDir}"
sshPut remote: remote, from: "./${outputDir}", into: "${deployTempDir}"
sshCommand remote: remote, command: "rsync -avzh ${deployTempDir}/${outputDir}/* ${deployTargetDir}/ --delete"
sshRemove remote: remote, path: "${deployTempDir}", failOnError: false
}
}
}
post {
always {
script {
if (currentBuild.currentResult != 'FAILURE') {
setBuildStatus("${context}", "${env.STAGE_NAME} Success", "SUCCESS", "${storybookUrl}/${branchName}");
} else {
setBuildStatus("${context}", "${env.STAGE_NAME} Failed", "FAILURE", "${storybookUrl}/${branchName}");
}
}
}
}
}
}
}
stage('SonarQube Quality Gate') {
when {
expression { isSonarCoverage == 'true' }
}
// environment {
// context="SonarQube"
// }
steps {
// setBuildStatus(context, "${context} Progressing...", "PENDING", "${buildUrl}");
script{
timeout(time: 10, unit: 'MINUTES') {
waitForQualityGate abortPipeline: false
// def qg = waitForQualityGate()
// if (qg.status != 'OK') {
// echo "Pipeline aborted due to quality gate failure: ${qg.status}"
// // setBuildStatus("${context}", "${context} Failed", "UNSTABLE", "${sonarQubeUrl}");
// }
}
}
}
// post {
// always {
// script {
// if (currentBuild.currentResult != 'FAILURE') {
// setBuildStatus("${context}", "${env.STAGE_NAME} Success", "SUCCESS", "${sonarQubeUrl}");
// } else {
// setBuildStatus("${context}", "${env.STAGE_NAME} Failed", "FAILURE", "${sonarQubeUrl}");
// }
// }
// }
// }
}
// stage('PR Comment') {
// when {
// expression { isPrBranch == 'true' }
// }
// steps {
// step([
// $class: 'ViolationsToGitHubRecorder',
// config: [
// gitHubUrl: 'https://*******.git',
// repositoryOwner: '*******',
// repositoryName: '*******',
// pullRequestId: "${env.CHANGE_ID}",
// credentialsId: 'githubApp',
// createCommentWithAllSingleFileComments: true,
// createSingleFileComments: true,
// commentOnlyChangedContent: true,
// commentOnlyChangedFiles: true,
// minSeverity: 'INFO',
// maxNumberOfViolations: 99999,
// keepOldComments: false,
// commentTemplate: """
// *Reporter**: {{violation.reporter}}{{#violation.rule}}
// **Rule**: {{violation.rule}}{{/violation.rule}}
// **Severity**: {{violation.severity}}
// **File**: {{violation.file}} L{{violation.startLine}}{{#violation.source}}
// **Source**: {{violation.source}}{{/violation.source}}
// {{violation.message}}
// """,
// violationConfigs: [
// [ pattern: '.*/checkstyle-*\\.xml$', parser: 'CHECKSTYLE', reporter: 'Checkstyle' ],
// // [ pattern: '.*/findbugsXml\\.xml$', parser: 'FINDBUGS', reporter: 'Findbugs' ],
// // [ pattern: '.*/pmd\\.xml$', parser: 'PMD', reporter: 'PMD' ],
// ]
// ]
// ])
// }
// }
}
post {
cleanup {
cleanWs(
deleteDirs: true,
patterns: [
[pattern: 'dist', type: 'INCLUDE'],
[pattern: '.out', type: 'INCLUDE'],
]
)
}
success {
script {
def previousResult = currentBuild.previousBuild?.result
if (!previousResult || (previousResult && previousResult != currentBuild.result)) {
notifySlack ('SUCCESS', '#00FF00')
}
}
}
unstable {
notifySlack ('UNSTABLE', '#FFFF00')
}
failure {
notifySlack ('FAILED', '#FF0000')
}
}
} |
Scripted Pipeline Examples |
GitHubCommitStatusSetter & publishChecksdef setBuildStatus(String context, String message, String state, String url) {
if (state == 'PENDING') {
backref = "${env.RUN_DISPLAY_URL}"
} else {
backref = url
}
step([
$class: "GitHubCommitStatusSetter",
reposSource: [$class: "ManuallyEnteredRepositorySource", url: "${env.GIT_URL}"],
contextSource: [$class: "ManuallyEnteredCommitContextSource", context: "ci/jenkins/${context}"],
errorHandlers: [[$class: "ChangingBuildStatusErrorHandler", result: "UNSTABLE"]],
statusBackrefSource: [$class: "ManuallyEnteredBackrefSource", backref: backref],
statusResultSource: [ $class: "ConditionalStatusResultSource", results: [[$class: "AnyBuildResult", message: message, state: state]] ]
]);
// To set publishChecks
// title = 'Build Check'
// if (state == 'PENDING') {
// publishChecks title: title,
// name: context,
// status: 'IN_PROGRESS',
// detailsURL: url
// } else if (state != 'SUCCESS') {
// publishChecks title: title,
// name: context,
// status: 'COMPLETED',
// conclusion: 'FAILURE',
// detailsURL: url
// } else {
// publishChecks title: title,
// name: context,
// detailsURL: url
// }
}
def setBuildProcessingStatus(String context, String url) {
setBuildStatus(context, "${context} Progressing...", "PENDING", url)
}
def setBuildResultStatus(String context, Boolean isSuccess, String url) {
if (isSuccess) {
setBuildStatus(context, "${context} Success", "SUCCESS", url)
} else {
setBuildStatus(context, "${context} Failed", "FAILURE", url)
}
} |
Notification// |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
TL;DR;
Declarative Pipeline
Scripted Pipleline
Reference
The text was updated successfully, but these errors were encountered: