如何跨阶段重复使用先前创建的工作区

时间:2017-05-30 09:56: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'
          }
        )
      }
    }
  }
}

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

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

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

修改

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

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

我已经看到其他线程在讨论如何重新使用相同的工作区,因为您可能遇到文件锁的问题。他们建议在步骤之间存档\取消归档工作空间。

我也看到了一些方法,你可以将工作空间路径存储在一个变量中,稍后再使用它,这对我的情况有好处,但我没有找到任何声明性语法样本,只有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'
          ])
        }
      }
    }
    }
}

我确实尝试从Unit Tests阶段删除第二个代理声明,但是舞台仍然在我的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

它甚至用@ 2加倍后缀,所以我不确定它现在在做什么。

7 个答案:

答案 0 :(得分:9)

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

  

此外,如果您在指定代理{标签'无论什么'在顶层,您可以确保此阶段将使用与管道的其余部分相同的节点和工作空间:

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-nodeworkspace-with-per-stage-docker-agents

答案 1 :(得分: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...
                        }
                    }
                }
            }
        }
    }
}

随心所欲地运作。

答案 2 :(得分:2)

指定自定义工作区。 从Pipeline语法:“ws:Allocate workspace”

ws("/usr/local/jenkins/jobs/custom_workspace") {
    stage . . . 
    stage . . . 
}

。 。这有用吗?

答案 3 :(得分:2)

对于我来说,我将全局代理设置为“无代理”,然后这些阶段将使用相同的工作空间。

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

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' } // <- the difference is here
    stages {
        stage('prep') {
            agent { docker { image 'yourdockerimage' }}
            steps {
                sh 'pwd' // different workspace, with @2 appended
            }
        }
        stage('build') {
            // no agent specified
            steps {
                sh 'pwd' // same workspace, without @2
            }
        }
    }
}

很高兴能解释为什么会这样。我的猜测是,整个管道的全局代理,无论何时指定,都将使用“原始”工作空间(不带@ 2),使用其他代理的任何其他步骤都将需要使用@ 2工作空间。因此,如果不使用全局代理,则所有阶段共享相同的工作空间

答案 4 :(得分:1)

我使用节点语法来解决它。

为了确定我会使用dir范围来设置你自己的工作区

答案 5 :(得分:1)

External Workspace Manager Plugin可能会解决您的问题。

  

[...]它定义了工作区的本地路径,并切换到它。

// Basic usage:

def extWorkspace = exwsAllocate diskPoolId: 'diskpool1'
node ('linux') {
    exws (extWorkspace) {
        scm checkout
        sh 'mvn clean install -DskipTests'
    }
}
node ('test') {
    exws (extWorkspace) {
        sh 'mvn test'
    }
}

答案 6 :(得分:0)

我很高兴地说,詹金斯现在可以共享工作空间。

您可以指定嵌套在其他阶段中的阶段以共享工作空间。

新功能称为Sequential Stages

我将使用您的原始代码来实现它。

#!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') { // 3. Running on master in /var/lib/jenkins/workspace/_Pipelines_IACT-Jenkinsfile-UL3RGRZZQD3LOPY2FUEKN5XCY4ZZ6AGJVM24PLTO3OPL54KTJCEQ@2
        parallel {
            stage("Unit Tests@") {
                agent {label 'master'}
                stages {
                    stage("Jasmine") {
                        steps {
                            sh 'gulp karma-tests-ci'
                        }
                    }
                    stage(Mocha") {
                        steps {
                            sh 'gulp mocha-tests'
                        }
                    }
                }
            }
        }
    }
  }
}