Skip to content

Continuous Integration

Jenkins Jobs

Use Job DSL to define Jenkins jobs in a programmatic way. Refer to DSL API reference. Jobs are defined in gitops-gitops/jenkins-jobs.

Example

pipelineJob('gitops/docker-jenkins') {
  definition {
    cpsScm {
      scm {
        git {
          remote {
            url('https://github.com/goldginkgo/jenkins-docker.git')
          }
          branch('*/master')
        }
      }
      lightweight()
    }
  }

  triggers {
    githubPush()
  }
}

Jenkinsfile

Agents

Currently we recommend to use the maven38 agent. It has severl containers: kaniko, maven, trivy.

Build Images

We should use kaniko to build container images from Dockerfile, inside a container.

Security Scanning

An example pipeline.

pipeline {
    agent { label "maven38" }

    options {
        // timestamps()    // 日志会有时间
        skipDefaultCheckout()   // 删除隐式checkout scm语句
        disableConcurrentBuilds()   //禁止并行
        timeout(time:10, unit:'MINUTES') //设置流水线超时时间
    }

    // environment {
    //     ACR_REGISTRY_CREDS = credentials('acepi001cr01_username_pass')
    // }

    stages {
        stage('VulnerabilityScan') {
            steps {
                container("trivy"){
                    script{
                        sh '''
                            # export TRIVY_USERNAME=${ACR_REGISTRY_CREDS_USR}
                            # export TRIVY_PASSWORD=${ACR_REGISTRY_CREDS_PSW}
                            trivy client --remote http://trivy.gitops-system:4954 -f json -o trivy-report.json goldginkgo/jenkins:0.1
                        '''
                    }
                }
            }
        }
    }

    post {
        always {
            recordIssues(tools: [trivy(pattern: 'trivy-report.json')])
        }
    }
}

Remote Command Execution to VMs

Under development.

Full Jenkinsfile Example

@Library("jenkins-library")

def tools = new org.devops.v1.tools()
def sendEmail = new org.devops.v1.sendEmail()

pipeline {
    agent { label "maven38"}

    options {
        //timestamps()    // 日志会有时间
        skipDefaultCheckout()   // 删除隐式checkout scm语句
        disableConcurrentBuilds()   //禁止并行
        timeout(time:10, unit:'MINUTES') //设置流水线超时时间
    }

    environment {
        GIT_URL = "goldgingo/jenkins-demo.git"
        GIT_BRANCH = "master"
        BUILD_SHELL = "mvn clean package -Dmaven.tet.skip=true"
        IMAGE = "goldginkgo/jenkins-demo"
        IMAGE_TAG = "0.1"
        TO_EMAIL_USER = "frank.dai@test.cn"

        GITHUB_CREDS = credentials('github_username_pass')
        ACR_REGISTRY_CREDS = credentials('acepi001cr01_username_pass')
    }

    stages {
        stage('GetCode') {
            steps {
                checkout([$class: 'GitSCM', branches: [[name: "${GIT_BRANCH}"]],
                    doGenerateSubmoduleConfigurations: false,
                    extensions: [],
                    submoduleCfg: [],
                    userRemoteConfigs: [[credentialsId: 'github_username_pass', url: "http://${GIT_URL}"]]])
            }
        }

        stage('Build&Test') {
            steps {
                container('maven') {
                    script{
                        tools.PrintMes("编译打包", "blue")
                        sh """
                            ${BUILD_SHELL}
                        """
                    }
                }
            }
        }

        stage('CodeScanner') {
            steps{
                container('maven') {
                    withSonarQubeEnv(installationName: 'SonarQube') {
                        script{
                            tools.PrintMes("静态扫描", "blue")
                            sh 'mvn org.sonarsource.scanner.maven:sonar-maven-plugin:3.7.0.1746:sonar'
                        }

                    }
                }

            }
        }

        stage("QualityGate") {
            steps {
                script{
                    tools.PrintMes("质量门", "blue")
                }
                timeout(time: 1, unit: 'HOURS') {
                    waitForQualityGate abortPipeline: true
                }
            }
        }

        stage('BuildImage') {
            steps {
                container("kaniko") {
                    script{
                        tools.PrintMes("创建镜像", "blue")
                        sh "/kaniko/executor -f `pwd`/Dockerfile -c `pwd` --destination=${IMAGE}:${IMAGE_TAG} --cache=true --cache-dir=/kanikocache --skip-tls-verify"
                    }
                }
            }
        }

        stage('VulnerabilityScan') {
            steps {
                container("trivy"){
                    script{
                        tools.PrintMes("漏洞扫描", "blue")
                        sh '''
                            export TRIVY_USERNAME=${ACR_REGISTRY_CREDS_USR}
                            export TRIVY_PASSWORD=${ACR_REGISTRY_CREDS_PSW}
                            trivy client --remote http://trivy.gitops-system:4954 -f json -o trivy-report.json ${IMAGE}:${IMAGE_TAG}
                        '''
                    }
                }
            }
        }

        stage('Deploy') {
            when { branch 'master' }
            input {
                message 'Should we continue?'
                ok 'Yes, we should.'
                parameters {
                    string(name: 'input', defaultValue: 'yes', description: 'continue deployment?')
                }
            }

            steps {
                script{
                    tools.PrintMes("是否部署?", "blue")
                    isDeploy = "${input}"

                    if ("${isDeploy}" == 'yes' && "${GIT_BRANCH}" == 'master') {
                        tools.PrintMes("开始部署", "blue")
                        sh """
                            git remote set-url origin http://${GITHUB_CREDS_USR}:${GITHUB_CREDS_PSW}@${GIT_URL}
                            git checkout ${GIT_BRANCH}
                            git config --global user.email "jenkins2@gitops.cn"
                            git config --global user.name "Jenkins Bot"
                            git pull origin master
                            # sed -i 's/{IMAGE}:[0-9]*\\.[0-9]*/{IMAGE}:${IMAGE_TAG}/g' application-demo.yaml
                            # git status
                            # git commit -am 'Bump up image version'
                            # git tag -a ${IMAGE_TAG} -m "version ${IMAGE_TAG}"
                            # git push origin master --tags
                        """
                    } else {
                        tools.PrintMes("不部署", "blue")
                    }
                }
            }
        }
    }

    post {
        success {
            script{
                tools.PrintMes("Success:构建成功", "green")
                currentBuild.description += "\n构建成功!"
                sendEmail.SendEmail("构建成功", TO_EMAIL_USER)
            }
        }
        failure {
            script{
                tools.PrintMes("Failure:构建失败", "red")
                currentBuild.description += "\n构建失败!"
                sendEmail.SendEmail("构建失败", TO_EMAIL_USER)
            }
        }
        aborted {
            script{
                tools.PrintMes("Aborted:构建取消", "red")
                currentBuild.description += "\n构建取消!"
                sendEmail.SendEmail("构建取消", TO_EMAIL_USER)
            }
        }
        always {
            recordIssues(tools: [trivy(pattern: 'trivy-report.json')])
        }
    }
}