为什么这个 Jenkins 构建脚本两次分配相同的节点 ID?

Why does this Jenkins build script assign the same node ID twice?

我正在使用 Knapsack Pro 拆分单元测试并 运行 它们并行进行,我最近注意到有时它会将相同的节点索引分配给多个节点。

构建脚本如下所示(为简洁起见进行了删减):

def num_nodes = 10;
def nodes = [:]

env.total_nodes = num_nodes

for (i in [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) {
    int index = i
    nodes["ci_node_${i}"] = {
        node('ec2-slave') {
            ...
            env.new_index = index
            stage('Build & run rspec') {
                dir("$WORKSPACE") {
                    sh '''#!/bin/bash
                        cd $WORKSPACE
                        export NODE_ENV=production
                        export KNAPSACK_PRO_CI_NODE_TOTAL=${total_nodes}
                        export KNAPSACK_PRO_CI_NODE_BUILD_ID=${BUILD_TAG}
                        export KNAPSACK_PRO_CI_NODE_INDEX=${new_index}
                        export KNAPSACK_PRO_COMMIT_HASH=${commithash}
                        export KNAPSACK_PRO_BRANCH=${BRANCH_NAME}
                        export KNAPSACK_PRO_TEST_FILE_EXCLUDE_PATTERN="spec/smokes/*_spec.rb"
                        env
                        ...
                    '''
                }
            }
        }
    }
}
try {
    parallel nodes // run CI nodes in parallel
} catch (err) {
    echo "Build Failed - ${err.getMessage()}"
} finally {
    ...
}

但是,当我对 env 打印的 KNAPSACK_PRO_CI_NODE_INDEX 的所有值进行 grep 日志时,我有时(但不总是)看到类似这样的内容:

KNAPSACK_PRO_CI_NODE_INDEX=0
KNAPSACK_PRO_CI_NODE_INDEX=2
KNAPSACK_PRO_CI_NODE_INDEX=1
KNAPSACK_PRO_CI_NODE_INDEX=5
KNAPSACK_PRO_CI_NODE_INDEX=3
KNAPSACK_PRO_CI_NODE_INDEX=8
KNAPSACK_PRO_CI_NODE_INDEX=6
KNAPSACK_PRO_CI_NODE_INDEX=6
KNAPSACK_PRO_CI_NODE_INDEX=7
KNAPSACK_PRO_CI_NODE_INDEX=9

节点 4 从未被分配,节点 6 被分配了两次。这是怎么回事?

注意:那个可怕的硬编码 for 循环试图解决这个问题,这可能是相关的:

env.new_index = index

env 是一个全局对象,是主脚本的一部分。 env.new_index 是全局 属性.

示例:

node {
    env.VAR1 = "value"
}

println(env.VAR1)

将打印

[Pipeline] Start of Pipeline
[Pipeline] node
[Pipeline] {
[Pipeline] }
[Pipeline] // node
[Pipeline] echo
value
[Pipeline] End of Pipeline
Finished: SUCCESS

如果你想为每个节点定义环境变量,那么最好使用 withEnv

            withEnv(["new_index=$index"]) {
                stage('Build & run rspec') {
                    dir("$WORKSPACE") {
                        sh '''#!/bin/bash
                            cd $WORKSPACE
                            export NODE_ENV=production
                            export KNAPSACK_PRO_CI_NODE_TOTAL=${total_nodes}
                            export KNAPSACK_PRO_CI_NODE_BUILD_ID=${BUILD_TAG}
                            export KNAPSACK_PRO_CI_NODE_INDEX=${new_index}
                            export KNAPSACK_PRO_COMMIT_HASH=${commithash}
                            export KNAPSACK_PRO_BRANCH=${BRANCH_NAME}
                            export KNAPSACK_PRO_TEST_FILE_EXCLUDE_PATTERN="spec/smokes/*_spec.rb"
                            env
                            ...
                        '''
                    }
                }
            }