Jenkins工作流pipeline(groovy)常用操作记录

//主要用于记录工作流中操作,如从git仓库拉取代码、编译其他项目的job任务、编译docker镜像、推送镜像到仓库、操作json数组、从接口中读取数据等操作。

pipeline{
    agent {
        label "${NODE_LABELS}"  //jenkins服务器节点,不同操作系统使用
    }
    environment {
    //该步骤的变量下面操作无法进行修改
        PROJECT_API_URL = "..." //获取项目列表api接口地址
        UPDATE_DOCKER_API_URL = "..." //更新镜像api接口地址
        DOWNLOAD_URL_BASE = "..." //下载程序代码url地址
        OPS_GIT_URL = "..." //下载dockerfile的git地址
        DOCKER_IMAGE_BASE_URL = '...' //docker镜像仓库地址
        DOCKER_CREDENTIALS_ID = '...' //docker授权ID,需在jenkins凭证中进行添加
        NEXUS_URL = "..." //制品库地址
        NEXUS_CREDENTIALS_ID = '...' //制品库授权ID,需在jenkins凭证中进行添加
    }
    stages{
        stage('清空当前工作目录') {
            steps {
                script {
                    // 移除当前工作的目录中的所有文件和子目录
                    sh 'rm -rf ./*'
                    
                    // 输出一个确认信息
                    echo "当前工作目录已清空"
                }
            }
        }
        stage('初始化变量') {
            steps {
                script {
                    // 声明全局变量,此处变量后续可修改
                    def frontendProjects = []
                    def backendProjects = []

                    env.DOCKERFILE_NAME = 'Dockerfile'
                    env.BUILD_PROJECTS = '[]'
                    env.buildCount = 0
                    env.buildStaticCount = 0

                    //使用非凭证方式下载代码,可修改为使用凭证方式
                    def GIT_CONFIG_USER_NAME = 'git_user'
                    def GIT_CONFIG_USER_PASSWORD = 'git_password'
                    env.STATIC_CONTIG_GIT_URL = "http://$GIT_CONFIG_USER_NAME:$GIT_CONFIG_USER_PASSWORD@服务器ip:端口号/config.git"
                }
            }
        }
        
        stage('登录Docker镜像仓库') {
            steps {
                script {
                    //使用凭证ID登录docker
                    withCredentials([usernamePassword(credentialsId: env.DOCKER_CREDENTIALS_ID, usernameVariable: 'DOCKER_USERNAME', passwordVariable: 'DOCKER_PASSWORD')]) {
                        sh """
                            docker login $DOCKER_IMAGE_BASE_URL -u "$env.DOCKER_USERNAME" -p "$env.DOCKER_PASSWORD"
                        """
                    }
                }
            }
        }

        stage('获取项目列表'){
            steps {
                script {
                    // 从接口获取项目json项目列表,结构为{"project_name":"aa","build_tag":"test_aa_...."}
                    def response = httpRequest url: "${env.PROJECT_API_URL}?id=${upgradeListId}", validResponseCodes: '200:499'
                    // 转换为json数组
                    def jsonData = readJSON text: response.content
                    // 提取项目列表
                    frontendProjects = jsonData.data.frontends ?: []
                    backendProjects = jsonData.data.backends ?: []

                }
            }
        }
        
        stage('从git仓库中获取Dockerfile'){
            steps {
                git url: "${env.OPS_GIT_URL}", branch: "master"
            }
        }
        
        stage('编译关联的其他job任务') {
            when {
                expression { backendProjects.any { it['project_name'] == 'extra_project' } }
            }
            steps {
                script {
                    #从项目列表读取关联job的tag
                    def extraBuildTag = findTagValueFromVariable(backendProjects,'extra_project')
                    // 编译extra_project项目
                    build job: 'extra_project',
                          parameters: [
                              string(name: 'Tag', value: extraBuildTag),
                              string(name: 'NODE_LABELS', value: NODE_LABELS)
                          ]
                }
            }
        }
        
        stage('处理后端程序包'){
            when {
                expression { backendProjects != null && !backendProjects.isEmpty() && buildBackend == 'true' }
            }
            steps {
                script {
                    backendProjects.each{ project ->
                        script {
                            handleBackendProject(project)
                            env.buildCount = env.buildCount.toInteger() + 1
                        }
                    }
                }
            }
        }
        
        stage('下载前端程序包'){
            when {
                expression { frontendProjects != null && !frontendProjects.isEmpty() && buildFrontend == 'true' }
            }
            steps {
                script {
                    frontendProjects.each{ project ->
                        script {
                            handleFrontendProject(project)
                            env.buildStaticCount = env.buildStaticCount.toInteger() + 1
                        }
                    }

            //判断项目是否少于15个,否则返回错误
                    if( env.buildStaticCount.toInteger() <=15 ){
                        error "项目不完整,请检查升级方案。"
                    }
                }
            }
        }

        stage('生成metadata.json文件'){
            when {
                expression { frontendProjects != null && !frontendProjects.isEmpty() && buildFrontend == 'true' }
            }
            steps {
                script {
                    //将前端项目列表输出到文件,用于后续进行查看
                    def formatFrontProject = groovy.json.JsonOutput.prettyPrint(frontendProjects.toString())
                    def metadataFile = "frontend_metadata.json"
                    
                    //写入文件
                    writeFile file: metadataFile, text: formatFrontProject
                }
            }
        }

        stage('从git获取配置文件'){
            when {
                expression { frontendProjects != null && !frontendProjects.isEmpty() && buildFrontend == 'true' }
            }
            steps {
                    sh """
                        git clone --branch master --depth 1 ${env.STATIC_CONTIG_GIT_URL}
                    """
            }
        }

        stage('编译前端程序包'){
            when {
                expression { frontendProjects != null && !frontendProjects.isEmpty() && buildFrontend == 'true' }
            }
            steps {
                script {
                    projectName = 'frontend'
                    print("--------------开始编译前端项目: ${projectName}--------------")
                    def now = new Date()
                    def dockerBuildDir = "${WORKSPACE}/dockerfile/app/${projectName}/"
                    def dockerPushImageVersion = "${env.IMAGE_PREFIX}_${now.format('yyyyMMdd')}_V0.0.0_${now.format('HHmm')}"
                    def dockerPackagePushUrl = "${env.DOCKER_IMAGE_BASE_URL}/${projectName}:${dockerPushImageVersion}"
                    sh """
                        #编译镜像
                        docker build -f ${env.DOCKERFILE_NAME} -t ${dockerPackagePushUrl} . && docker push ${dockerPackagePushUrl}
                    """
                    print("--------------编译前端完成项目--------------")
                    
                    appendToList("${dockerPackagePushUrl}")
                }
            }
        }
        stage('打包离线镜像归档并上传到制品库'){
            when {
                expression { env.BUILD_PROJECTS != null && !env.BUILD_PROJECTS.isEmpty() && saveOfflineImage == 'true' }
            }
            steps {
                script {
                        print("--------------开始打包离线镜像--------------")

                        def buildProjectArray = []
                        def buildProjects = new groovy.json.JsonSlurper().parseText(env.BUILD_PROJECTS)
                        buildProjects.each{ project ->
                            buildProjectArray = buildProjectArray + project
                        }
                        
                        def buiildProjectString = buildProjectArray.join(' ')
                        def buildImageOfflineName = "test-app-${upgradeListId}.jar"
                        
                        sh """
                            docker save -o $buildImageOfflineName ${buiildProjectString}
                        """

                  //归档镜像,可在点击项目进行下载
                        archiveArtifacts artifacts: buildImageOfflineName, fingerprint: true 

                        //上传到nexus
                        withCredentials([usernamePassword(credentialsId: env.NEXUS_CREDENTIALS_ID, usernameVariable: 'NEXUS_USER', passwordVariable: 'NEXUS_PASSWORD')]) {
                            sh """
                                curl -X POST "${env.NEXUS_URL}/service/rest/v1/components?repository=buildpackage" \
    -H "accept: application/json" \
    -H "Content-Type: multipart/form-data" \
    -F "raw.directory=/build_packages/dockerImages/" \
    -F "raw.asset1=@${buildImageOfflineName};type=application/java-archive" \
    -F "raw.asset1.filename=${buildImageOfflineName}" \
    -u ${NEXUS_USER}:${NEXUS_PASSWORD}
                            """
                        }
                        
                        print("--------------打包离线镜像完成--------------")

                        def downloadImageLink = "${env.NEXUS_URL}/repository/buildpackage/build_packages/dockerImages/${buildImageOfflineName}"

                        echo "--------------下载离线镜像URL: ${downloadImageLink} ----------"
                }
            }
        }
        stage('删除本地镜像'){
            when {
                expression { env.BUILD_PROJECTS != null && !env.BUILD_PROJECTS.isEmpty() }
            }
            steps {
                script {
                    def buildProjects = new groovy.json.JsonSlurper().parseText(env.BUILD_PROJECTS)

                    buildProjects.each{ project ->

                        print("--------------开始删除本地镜像: ${project}--------------")
                        sh """
                            docker rmi "${project}"
                        """
                    }

                    print("--------------删除本地镜像完成--------------")
                }
            }
        }

        stage('更新记录'){
            when {
                expression { env.BUILD_PROJECTS != null && !env.BUILD_PROJECTS.isEmpty() && updateListDockerImage == 'true' }
            }
            steps {
                script {
                    def dokcerImageUrls = java.net.URLEncoder.encode(env.BUILD_PROJECTS, "UTF-8")
                    // 调用接口更新镜像
                    def response = httpRequest url: "${env.UPDATE_DOCKER_API_URL}?id=${upgradeListId}&image_urls=${dokcerImageUrls}", validResponseCodes: '200:499'
                    
                    def jsonData = readJSON text: response.content
                }
            }
        }
        
    }

    post {
        always {
            outputBuildProjects()
        }
    }
}

// 追加元素到全局列表
def appendToList(String element) {
    def list = new groovy.json.JsonSlurper().parseText(env.BUILD_PROJECTS)
    list.add(element)
    env.BUILD_PROJECTS = new groovy.json.JsonBuilder(list).toString()
}

//输出编译项目列表
def outputBuildProjects() {
    stage('输出编译的镜像列表'){
        def buildProjectString = ""
        def buildProjects = new groovy.json.JsonSlurper().parseText(env.BUILD_PROJECTS)
        buildProjects.each{ project ->
            buildProjectString = buildProjectString + "\r\n" + project
        }
        
        print("docker image push list【${buildProjects.size()}个】:")
        print("${buildProjectString}")
    }
}

// 处理前端项目
def handleFrontendProject(project) {
    def projectName = project.project_name
    print("--------------开始复制前端项目: ${projectName}--------------")
    
    dir(projectName) {
        // 下载构建包
        def downloadUrl = "..."
        try {

            sh """
                //下载项目
                mkdir -p ${WORKSPACE}/static && wget -q -O ${WORKSPACE}/static/${projectName}.zip ${downloadUrl}
            """
        } catch (Exception e) {
                // 捕获异常并在控制台输出错误信息
                error "下载项目${projectName}失败: ${e.message}"
        }
    }
}

// 处理后端项目
def handleBackendProject(project) {
    def projectName = project.project_name
    print("--------------开始后端处理项目: ${projectName}--------------")
    
    dir(projectName) {
        // 下载构建包
        def downloadUrl = "..."
        def dockerBuildDir = "..."
        
        // 跳过
        if (skipCount.toInteger() > 0 && env.buildCount.toInteger() <= skipCount.toInteger() ){
            print("${projectName} skipped")
            return
        }
        try {
            //
            dockerPackagePushUrl = "..."
            sh """
                mkdir -p ${dockerBuildDir}
                wget -q -O "${dockerBuildDir}/app/${buildFilename}" ${downloadUrl}
            """
        } catch (Exception e) {
                // 捕获异常并在控制台输出错误信息
                error "下载项目${projectName}失败: ${e.message}"
        }
        
        print("--------------开始编译项目: ${projectName}--------------")

        sh """
            cd ${dockerBuildDir}
            docker build -f ${env.DOCKERFILE_NAME} -t ${dockerPackagePushUrl} . && docker push ${dockerPackagePushUrl}
        """

        print("--------------项目编译完成--------------")
        
        appendToList("${dockerPackagePushUrl}")
    }
}

//从变量中获取项目对应的tag
def findTagValueFromVariable(projectVariable, key) {
    for (def item in projectVariable) {
        if (item['project_name'] == key) {
            return item['build_tag']
        }
    }
    return null // 如果没有找到匹配的值,返回 null
}
  
  

  

posted @ 2025-07-23 18:49  雪洁  阅读(46)  评论(0)    收藏  举报