当前位置: 首页 > 知识库问答 >
问题:

如何跨阶段重用以前创建的工作区

宋翔
2023-03-14

我面临一个问题,在我的管道中定义了两个阶段,它们都在同一个节点上运行,需要在同一个工作区中运行。

这些阶段中的第一个阶段最初在我的主节点上运行,但在定义的步骤即将结束时,必须将一些文件解压缩到另一个节点上。

然后,第二阶段只需要在我的主程序上继续,并且依赖于从第一阶段安装的一些模块。

以下是我要更好地解释的管道:

#!groovy
pipeline {
  agent { label 'master' }
  stages {
    stage('Build') { // 1. Running on master in /var/lib/jenkins/workspace/_Pipelines_IACT-Jenkinsfile-UL3RGRZZQD3LOPY2FUEKN5XCY4ZZ6AGJVM24PLTO3OPL54KTJCEQ
      steps {
        sh '''
          npm install
          bower install
          gulp set-staging-node-env
          gulp prepare-staging-files
          gulp webpack
        '''
        stash includes: 'dist/**/*', name: 'builtSources'
        stash includes: 'config/**/*', name: 'appConfig'
        node('Protractor') { // 2. Running on vnccentos7 in /var/jenkins/workspace/_Pipelines_IACT-Jenkinsfile-UL3RGRZZQD3LOPY2FUEKN5XCY4ZZ6AGJVM24PLTO3OPL54KTJCEQ
          dir('/opt/foo/deploy/') {
            unstash 'builtSources'
            unstash 'appConfig'
          }
        }        
      }
    }
    stage('Unit Tests') {
      agent { label 'master' } // 3. Running on master in /var/lib/jenkins/workspace/_Pipelines_IACT-Jenkinsfile-UL3RGRZZQD3LOPY2FUEKN5XCY4ZZ6AGJVM24PLTO3OPL54KTJCEQ@2
      steps {
        parallel (
          "Jasmine": {
            sh 'gulp karma-tests-ci'
          },
           "Mocha": {
            sh 'gulp mocha-tests'
          }
        )
      }
    }
  }
}

如您所见,我在每个阶段\节点的开始处添加了注释,用于显示我看到的分配了哪些工作空间的詹金斯输出。

我面临的问题是,单元测试阶段失败了,因为它试图使用一些找不到的节点模块。这些都存在于创建的第一个工作区中,这是我希望此阶段继续使用的工作区,因此不要使用新的“@2”后缀工作区。

有没有办法告诉Jenkins在管道中保留以前创建的工作区?

编辑

我猜,因为我在下一个阶段再次指定了代理{label:'master'},这就是要创建新工作区的情况?我应该改用节点方法吗?这会允许使用相同的工作区吗?

实际上,我已经尝试在我的单元测试阶段的每个并行步骤周围使用节点('master'){...},但是这些步骤仍然使用@2后缀的工作区,而不是原来的工作区。

我见过其他线程谈论如何不重复使用相同的工作空间,因为你可能会遇到文件锁的问题。他们建议将步骤之间的工作空间归档\unArchive

我还看到过一些方法,可以将工作区路径存储在变量中,稍后再使用,这对我的情况来说很好,但我没有找到任何声明性语法示例,只有groovy示例。

编辑2

我现在尝试了几种方法,包括将第一阶段分配的工作区保存到变量中,并在ws(…)中使用 指令:

pipeline {
  agent { label 'master' }
  stages {
    stage('Build') {
      steps {
        script {
          def workspace = pwd()
        }
        sh '''
          npm install
          bower install
          gulp set-staging-node-env
          gulp prepare-staging-files
          gulp webpack
        '''
        stash includes: 'dist/**/*', name: 'builtSources'
        stash includes: 'config/**/*', name: 'appConfig'
        node('Protractor') {
          dir('/opt/foo/deploy/') {
            unstash 'builtSources'
            unstash 'appConfig'
          }
        }        
      }
    }
    stage('Unit Tests') {
      steps {
        parallel (
          "Jasmine": {
            node('master') {
              ws("${workspace}"){
                sh 'gulp karma-tests-ci'
              }
            }
          },
          "Mocha": {
            node('master') {
              ws("${workspace}"){
                sh 'gulp mocha-tests'
              }
            }
          }
        )
      }
      post {
        success {
          sh 'gulp combine-coverage-reports'
          sh 'gulp clean-lcov'
          publishHTML(target: [
            allowMissing: false,
            alwaysLinkToLastBuild: false,
            keepAll: false,
            reportDir: 'test/coverage',
            reportFiles: 'index.html',
            reportName: 'Test Coverage Report'
          ])
        }
      }
    }
    }
}

我确实尝试过从单元测试阶段删除第二个代理声明,但该阶段仍然保留在我的量角器节点上,这是我不希望它做的。按照这里的答案\注释,我在每个并行步骤周围使用了节点块,并使用了ws块,如您所见,

阶段失败,我可以从日志中看到它没有使用从第一阶段分配的工作空间(没有@后缀):

[Jasmine] Running on master in /var/lib/jenkins/workspace/_Pipelines_IACT-Jenkinsfile-UL3RGRZZQD3LOPY2FUEKN5XCY4ZZ6AGJVM24PLTO3OPL54KTJCEQ@2
[Pipeline] [Jasmine] {
[Pipeline] [Jasmine] ws
[Jasmine] Running in /var/lib/jenkins/workspace/_Pipelines_IACT-Jenkinsfile-UL3RGRZZQD3LOPY2FUEKN5XCY4ZZ6AGJVM24PLTO3OPL54KTJCEQ@2@2
[Pipeline] [Jasmine] {
[Pipeline] [Jasmine] sh
[Jasmine] [_Pipelines_IACT-Jenkinsfile-UL3RGRZZQD3LOPY2FUEKN5XCY4ZZ6AGJVM24PLTO3OPL54KTJCEQ@2@2] Running shell script
[Jasmine] + gulp karma-tests-ci
[Jasmine] [08:27:01] No gulpfile found

它甚至可以用@2作为双后缀,所以我不确定它现在在做什么。


共有3个答案

赫连宏伯
2023-03-14

您可以指定一个全局代理,但必须记住,对于每个底层agent指令,将使用一个新的工作区。

docker代理有一个有用的选项,告诉reuseNode继续使用相同的节点/工作区。

示例1:使用“代理无”,2个阶段使用一些工作区

pipeline {
    agent none // <- the difference is here
    stages {
        stage('prep') {
            agent { docker { image 'yourdockerimage' }}
            steps {
                sh 'pwd' // same workspace, without @2
            }
        }
        stage('build') {
            agent { label 'master' }
            steps {
                sh 'pwd' // same workspace, without @2
            }
        }
    }
}

示例2:使用全局代理

pipeline {
    agent { label 'master' } // <- specify the global agent
    stages {
        stage('prep') {
            agent { docker { image 'yourdockerimage' }} // <- do not ask to reuse the node/workspace
            steps {
                sh 'pwd' // different workspace, with @2 appended
            }
        }
        stage('build') {
            // no agent specified, use global agent
            steps {
                sh 'pwd' // same workspace, without @2
            }
        }
        stage('publish') {
            agent { docker { image 'yourdockerimage' reuseNode true }}
            steps {
                sh 'echo "published"' // same workspace, without @2
            }
        }
    }
}
强承望
2023-03-14

使用dir而不是ws

ws当要使用的工作区已被其他生成作业占用时,自动修改前缀“@NUMBER”。

dir只需将当前工作目录移动到您指定的位置即可。

pipeline {
    agent none
    environment {
        WIN_WORKSPACE = ""
        MAC_WORKSPACE = ""
    }
    stages {
        stage("Build") {
            parallel {
                stage("Build on Windows") {
                    agent {
                        label "windows"
                    }
                    steps {
                        script {
                            WIN_WORKSPACE = WORKSPACE
                        }
                        // steps...
                    }
                }
                stage("Build on macOS") {
                    agent {
                        label "macos"
                    }
                    steps {
                        script {
                            MAC_WORKSPACE = WORKSPACE
                        }
                        // steps...
                    }
                }
            }
        }
        stage("Deploy") {
            parallel {
                stage("Deploy on Windows") {
                    agent {
                        label "windows"
                    }
                    steps {
                        dir(WIN_WORKSPACE) {
                            // steps...
                        }
                    }
                }
                stage("Deploy on macOS") {
                    agent {
                        label "macos"
                    }
                    steps {
                        dir(MAC_WORKSPACE) {
                            // steps...
                        }
                    }
                }
            }
        }
    }
}

你想要的工作得很好。

赖俊
2023-03-14

不确定它是否适合您的用例,但是这个示例脚本展示了如何在不同阶段之间共享相同的节点/工作空间

此外,如果您正在为特定阶段运行Docker代理,同时在顶层指定代理{label'whatever'},则可以确保此阶段将使用与管道其余部分相同的节点和工作区:

pipeline {
  agent {
    label 'whatever'
  }
  stages {
    stage('build') {
      steps {
        sh "./build-artifact.sh"
      }
    }
    stage('test in docker') {
      agent {
        docker {
          image 'ubuntu:16.04'
          reuseNode true
        }
      }
      steps {
        sh "./run-tests-in-docker.sh"
      }
    }
  }
}

https://github.com/jenkinsci/pipeline-model-definition-plugin/wiki/Controlling-your-build-environment#reusing-具有每阶段docker代理的nodeworkspace

 类似资料:
  • 问题内容: 想象一下一个使用Maven构建的Java项目,我为此: 一些快速运行的单元测试: 开发人员应在提交之前运行 我的CI服务器(Hudson,FWIW)应在检测到新提交后运行,以防出现故障时几乎立即给出反馈 一些运行缓慢的自动验收测试: 开发人员可以选择运行,例如重现和修复故障 成功运行单元测试后,我的CI服务器应运行 这似乎是一种典型的情况。目前,我正在跑步: 在“测试”阶段进行单元测试

  • 我无法使用 apache poi eclipse 在我创建的 java excel 中创建工作表

  • 问题:在构建阶段,我使用一个shell执行器来“zip helloworld.zip helloworld.txt”,然后,我“docker build-t myproject/myapp.”,我希望在其中复制helloworld.zip/“,但似乎我创建的zip文件在docker构建上下文中不可用。我没有将helloworld.zip文件保存到正确的位置吗?还是别的什么?我的长期目标是编写一个p

  • 每个工作流都应在单独的工作流类中实现? 是否建议实现一个通用工作流类,在该类中,我们将使用传递给工作流的参数调用活动和触发计时器? 在我们的用例中,我们将从UI创建工作流,它将由最终用户创建。所以我们不能一开始就定义我们的工作流程。 这是推荐的方法吗?

  • 我正试着为一个客户做一个录音应用程序。其中的两个要求是,它需要使用VUE运行并以无损格式记录,所以我将使用FLAC方法。我在Github上找到了一个Speech to-FLAC库,并试图将其移植到Vue中,但在任何时候都要引用工作代码时,我都无法编译Vue。 一种方法是尝试导入它,这与我使用功能的WAV编码器的工作示例相同: (不是我的代码,我只是知道它适用于WAV编码器。) 如果我尝试使用FLA

  • 我已经运行了,然后 退货 我知道我的当前有问题。下面是从 我真的不知道该怎么设置,因为我目前对终端非常陌生。任何帮助都将不胜感激。非常感谢。