问题描述
在 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