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

min*_*rse 20 jenkins jenkins-pipeline

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

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

然后第二阶段只需继续我的主人,并依赖从第一阶段安装的一些模块.

这是我的管道,以更好地解释:

#!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'
          }
        )
      }
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,我在每个stage \node的开头添加了注释,用于显示jenkins输出,我看到了哪些工作空间被分配.

我面临的问题是单元测试阶段失败,因为它试图使用它找不到的一些节点模块.它们存在于创建的第一个工作空间中,这是我希望此阶段继续使用的位置,因此不使用新的"@ 2"后缀工作空间.

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

编辑

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

我实际上已尝试node('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'
          ])
        }
      }
    }
    }
}
Run Code Online (Sandbox Code Playgroud)

我确实尝试从单元测试阶段删除第二个代理声明,但该阶段仍然在我的Protractor节点上,我不希望它这样做.所以按照这里的答案\评论我然后在我的每个并行步骤周围使用节点块并使用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
Run Code Online (Sandbox Code Playgroud)

它甚至带有@ 2的双后缀,所以我不确定它现在在做什么.

kon*_*oro 13

不确定它是否适合您的用例,但此示例脚本显示了如何在不同的阶段和容器之间共享相同的节点/工作区:

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

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"
      }
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

https://github.com/jenkinsci/pipeline-model-definition-plugin/wiki/Controlling-your-build-environment#reusing-nodeworkspace-with-per-stage-docker-agents

  • `reuseNode` 不应该在 `agent` 级别吗?没有人谈论“docker” (3认同)
  • 不错的`reuseNode true` (2认同)

pha*_*152 8

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

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

示例 1:使用“agent none”,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
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

示例 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
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


Jin*_*Heo 7

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...
                        }
                    }
                }
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

随心所欲地工作.

  • 对我来说工作得很好!谢谢! (2认同)

era*_*iri 1

我认为使用节点语法可以解决这个问题。

为了确定我会使用目录范围来设置您自己的工作区