首页 > 解决方案 > Docker Jenkins Pipeline 安装全局 NPM 包

问题描述

我是 Docker/Jenkins 的新手。

Jenkins 通过以下方式触发容器

docker run -t -d -u 995:315 -w /workspace/projectname -v /workspace/projectname:/workspace/projectname:rw,z -v /workspace/projectname@tmp:/workspace/projectname@tmp:rw,z  circleci/node:latest

我的管道

pipeline {
    agent {
        docker {
            image 'circleci/node:latest'
        }
    }
    environment { 
        HOME="."
        NPM_CONFIG_PREFIX="${pwd()}/.npm-global"
        PATH="$PATH:${pwd()}/.npm-global/bin:${pwd tmp: true}/.npm-global/bin"
    }
    stages {
        stage('NPM Config') {
            steps {
                sh 'npm install -g @angular/cli'
                echo "PATH is: $PATH"
                sh '.npm-global/bin/ng version'
                sh '/workspace/projectname/.npm-global/bin/ng version'
                sh 'ng version'
            }
        }
    }
}

echo "PATH is: $PATH"打印出来

PATH is: /sbin:/usr/sbin:/bin:/usr/bin;/usr/bin/;/etc/;/etc/ssh/ssh/:/workspace/projectname/.npm-global/bin:/workspace/projectname@tmp/.npm-global/bin

这两个

sh '.npm-global/bin/ng version'
sh '/workspace/projectname/.npm-global/bin/ng version'

做我期望sh 'ng version'做的事。但是,sh 'ng version'给了我以下错误

ng version
/workspace/projectname@tmp/durable-9f9bc04a/script.sh: 2: /workspace/projectname@tmp/durable-9f9bc04a/script.sh: ng: not found

我试图避免建立自己的形象,下一步该怎么做?

我也只会使用npx,但我需要更改很多 repos 和他们的脚本才能使这项工作正常工作,我不想那样做。

更新:看起来管道正在忽略更改下的 PATH 环境变量

environment { 
   HOME="."
   NPM_CONFIG_PREFIX="${pwd()}/.npm-global"
   PATH="/foo/bar"
}

修改PATH是否有特殊的可能?或者可能是权限问题?

标签: node.jsdockerjenkinsnpm

解决方案


这是一个格式化的,希望有用的答案,在尝试使用他们的详细文档进行整理之后。

首先,该environment块声明了 Jenkins 级别的键值对:

  • Jenkins级别不是工作区级别,变量插值级别是根据引号的类型选择的,所以如果我理解正确的话:

    echo '$PATH'将显示工作区PATH(在您的情况下为“默认”)

    echo "$PATH"将由詹金斯解释,因此显示“修改”PATH

  • 仅键值对有效:即使它看起来像 shell 环境变量设置,您也可以编写PATH = something而周围的空格=在 shell 中不起作用

似乎主要是在工作区不知道参数的情况下公开参数,就像用户会交互式地提供信息(他们谈论了很多关于凭据)。

其次,只有有限的步骤列表进行有效调用,并且没有export步骤。

但是有一个withEnv步骤可以完成这项工作。我没有在声明性中找到任何示例pipeline { ... },仅在脚本node { ... }块中,声明性版本的定义指出所有步骤都是有效的。我发现了一个包装stage块的步骤示例(node虽然),所以我们希望它是相同的stages(否则你必须withEnv在每个上指定stage- 或者作为 a 内的另一个包装器stage- 这需要你的环境 mods:当然可行还是很无聊)。

像这样的东西应该可以工作,或者至少值得一试:

  pipeline {
    agent { ... }
    environment { 
      HOME="."
      NPM_CONFIG_PREFIX="${pwd()}/.npm-global"
      PATH="$PATH:${pwd()}/.npm-global/bin:${pwd tmp: true}/.npm-global/bin"
    }
    withEnv(["PATH=$PATH", /*or*/ "PATH=${PATH}", /*or*/ "PATH+NPM=${pwd()}/.npm-global/bin:${pwd tmp: true}/.npm-global/bin"]) {
      stages {
        stage('NPM Config') {
          steps { ... }
        }
        stage('something else that needs ng') { ... }
      }
    }
  }

反正你懂这个意思。

最后,如果这PATH件事不起作用并且比重写管道更困扰您,那么使用带有node块的脚本替代方案可能会更有趣并且更灵活。

我希望从 OP 或周围的任何 Jenkins 大师那里得到一些反馈!


推荐阅读