「Jenkins Pipeline」- 暂存文件,以用于之后的构建

  CREATE BY JENKINSBOT
原文链接:「Jenkins Pipeline」- 暂存文件,以用于之后的构建
文章分类:「Continuous_Delivery:Jenkins_Pipeline:Plugins_and_Programming:x.Stash_some_files」
文章标识:「cbb027ff」

问题描述

在 Jenkins Pipeline 中,我们的构建将产生各种新文件,在而后的构建又会使用这些文件。

但是 Jenkins 的构建目录并不总是在同一个目录中、也不能保持不变:
1)当作业被重命名之后,构建目录也会发生变更。它会新建与作业同名的构建目录,而不是重命名旧的构建目录,因此无法读取旧的制品;
2)对于相同作业,有时会创建 JOB_NAME@2、JOB_NAME@3 等形式的构建目录(我们没有深究内部实现),导致新构建无法在当前目录读取之前的制品;
3)多项目之间共享制品时,由于构建是 Jenkins 内部实现,未来有可能发生变更,因此我们不能“直接地”读取主机中的目录(不具有可移植性);
4)如果 pipeline 的多个阶段在不同的节点上执行,我们还需要在多个节点之间共享文件,很显然直接操作主机目录是不可行的;

因此我们应该使用 Jenkins Pipeline 提供的制品管理方法,以在相同构建或者不同构建之间传递制品文件。

解决办法

方法一、使用 stash/unstash 步骤

stash: Stash some files to be used later in the build
unstash: Restore files previously stashed

stash,用于保存文件。unstash,用于提取 stash 暂存的文件。但是使用 stash/unstash 具有以下局限性:
1)只能用在同一次构建中,在构建结束后将被丢弃 => 因此可以用在:相同构建的 多节点 或 多工作目录 之间传递文件;
2)通过选项 preserveStashes() 可以在重启之后继续读取暂存文件,但依旧限制在单次构建运行中;
3)只适合小数量的文件(5-100 MB),因为文件暂存需要压缩,而压缩需要消耗 Master 的资源;

由于 stash/unstash 并不能解决我们的问题(我们需要在同个项目的多次构建中传递制品),因此不再深入研究与探讨。

方法二、使用 archiveArtifacts/copyArtifacts 步骤

archiveArtifacts – Jenkins Core
Copy Artifact | Jenkins plugin

archiveArtifacts,用于归档制品,是 Jenkins 默认(自带)提供的步骤。copyArtifacts,用于从其他构建中复制制品,是 Copy Artifact 插件提供的功能。

该方法能够处理大多数使用场景,参考 groovy – How can I use the Jenkins Copy Artifacts Plugin from within the pipelines (jenkinsfile)? 示例:

pipeline {
    agent any
    stages {
        stage ('push artifact') {
            steps {
                sh 'mkdir archive'
                sh 'echo test > archive/test.txt'
                zip zipFile: 'test.zip', archive: false, dir: 'archive'
                archiveArtifacts artifacts: 'test.zip', fingerprint: true
            }
        }

        stage('pull artifact') {
            steps {
                copyArtifacts filter: 'test.zip', fingerprintArtifacts: true, projectName: '${JOB_NAME}', selector: specific('${BUILD_NUMBER}')
                unzip zipFile: 'test.zip', dir: './archive_new'
                sh 'cat archive_new/test.txt'
            }
        }
    }
}

// 注意事项:
// 为了简化问题,这个示例将 保存制品 与 获取制品 放在同个示例中,
// 在时间使用中,可以将 stage ('push artifact') 与 stage('pull artifact') 放在不同的作业中

虽然 archiveArtifacts/copyArtifacts 能够解决我们的问题,但是比较繁琐。我们没有采用这种方案,因此不再深入研究与探讨。

方法三、使用 External Workspace Manager 插件

External Workspace Manager | Jenkins plugin

External Workspace Manager,该插件促成 Worksapce 的共享和多作业之间的再次使用,简单说是“开辟出新的工作目录”,并提供配套的管理方法。

使用方法可以参考 external-workspace-manager-plugin/README.md at master 文档。

该插件给我们解决问题的灵感(我们依旧没有使用该插件,但确实提供问题解决思路),因此不再深入研究与探讨。

参考文献

stash: Stash some files to be used later in the build
https://stackoverflow.com/questions/9483126/can-jenkins-store-artifacts-outside-the-job-directory
groovy – How can I use the Jenkins Copy Artifacts Plugin from within the pipelines (jenkinsfile)? – Stack Overflow
Copy Artifact | Jenkins plugin