You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Jenkins非声明式流水线中跳过无变更子目录的阶段?

解决方案:非声明式Jenkins流水线跳过无变更的Linux内核构建阶段

这问题太常见了——编译Linux内核这种重型任务,能省一次是一次!结合Git变更检测和Artifactory的缓存能力,完全可以实现指定子目录无变更时跳过构建、直接复用缓存产物的逻辑,下面给你一套可落地的非声明式流水线实现方案:

核心思路

  1. 变更检测:对比当前构建的Git提交与上一次成功构建的提交,检查linux/目录(或你指定的子目录)是否有文件变更
  2. 分支逻辑:
    • 若目录有变更:执行内核构建,将产物上传到Artifactory并标记为"最新版本"
    • 若目录无变更:直接从Artifactory拉取之前缓存的最新内核产物,跳过构建阶段

具体实现代码

以下是完整的非声明式流水线示例,包含所有关键步骤:

node {
    // 1. 拉取仓库代码
    stage('Checkout Source Code') {
        git url: '你的Git仓库URL', branch: 'main'
    }

    // 定义全局变量,方便后续阶段复用
    def linuxSubDir = 'linux/'
    def artifactoryServerId = 'your-artifactory-server' // Jenkins配置的Artifactory服务ID
    def artifactoryRepo = 'generic-local' // 存储内核产物的Artifactory仓库名
    def artifactName = 'linux-kernel.tar.gz'
    def artifactStorePath = "builds/linux/${BRANCH_NAME}" // 按分支隔离缓存,避免冲突
    def hasLinuxChanges = false

    // 2. 检测Linux目录是否有变更
    stage('Detect Linux Directory Changes') {
        script {
            // 获取上一次成功构建的Git提交哈希,处理第一次构建的特殊情况
            def lastSuccessCommit = ''
            if (currentBuild.previousSuccessfulBuild) {
                lastSuccessCommit = currentBuild.previousSuccessfulBuild.getScmRevision()
            } else {
                // 第一次构建时,用仓库的根提交作为对比基准
                lastSuccessCommit = sh(script: 'git rev-list --max-parents=0 HEAD', returnStdout: true).trim()
            }

            // 高效检测指定目录的变更:用git diff --quiet返回状态码,0=无变更,1=有变更
            def changeStatus = sh(
                script: "git diff --quiet ${lastSuccessCommit} HEAD -- ${linuxSubDir}",
                returnStatus: true
            )
            hasLinuxChanges = (changeStatus != 0)

            echo "Linux目录变更状态:${hasLinuxChanges ? '✅ 存在变更,将执行构建' : '❌ 无变更,将复用缓存'}"
        }
    }

    // 3. 有变更时执行内核构建并上传Artifactory
    stage('Build & Upload Linux Kernel') {
        when {
            expression { hasLinuxChanges }
        }
        steps {
            script {
                // 替换为你的实际内核构建命令
                sh """
                    cd ${linuxSubDir}
                    make defconfig
                    make -j$(nproc)
                """
                // 打包构建产物(示例打包bzImage,根据你的需求调整)
                sh "tar -czf ${artifactName} -C ${linuxSubDir} arch/x86_64/boot/bzImage"

                // 上传产物到Artifactory
                rtUpload(
                    serverId: artifactoryServerId,
                    spec: """{
                        "files": [
                            {
                                "pattern": "${artifactName}",
                                "target": "${artifactoryRepo}/${artifactStorePath}/${BUILD_NUMBER}-${artifactName}"
                            }
                        ]
                    }"""
                )
                // 更新"latest"标记,方便后续直接拉取最新版本
                rtCopy(
                    serverId: artifactoryServerId,
                    spec: """{
                        "files": [
                            {
                                "pattern": "${artifactoryRepo}/${artifactStorePath}/${BUILD_NUMBER}-${artifactName}",
                                "target": "${artifactoryRepo}/${artifactStorePath}/latest-${artifactName}"
                            }
                        ]
                    }"""
                )
            }
        }
    }

    // 4. 无变更时从Artifactory拉取缓存产物
    stage('Fetch Cached Linux Kernel') {
        when {
            expression { !hasLinuxChanges }
        }
        steps {
            script {
                // 拉取最新缓存的内核产物
                rtDownload(
                    serverId: artifactoryServerId,
                    spec: """{
                        "files": [
                            {
                                "pattern": "${artifactoryRepo}/${artifactStorePath}/latest-${artifactName}",
                                "target": "./"
                            }
                        ]
                    }"""
                )
                // 解压产物到指定位置
                sh "tar -xzf latest-${artifactName}"
            }
        }
    }

    // 后续阶段可以直接使用构建/拉取的内核产物
    stage('Continue with Pipeline') {
        steps {
            echo "已准备好Linux内核产物,进入后续阶段..."
            // 这里添加你的后续任务逻辑
        }
    }
}

关键注意事项

  • 插件依赖:确保Jenkins已安装Artifactory插件和Git插件,并且配置好了Artifactory服务器连接
  • 分支隔离:示例中通过${BRANCH_NAME}在Artifactory路径中区分分支,避免不同分支的缓存互相覆盖
  • 权限配置:确保Jenkins服务账号拥有Artifactory对应仓库的上传/下载权限
  • 变更检测优化:用git diff --quiet比解析diff输出更高效,适合流水线场景
  • 第一次构建处理:当没有上一次成功构建时,用仓库的根提交作为对比基准,确保第一次构建会执行内核编译并上传缓存

内容的提问来源于stack exchange,提问作者Eloff

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 06:57:43