node.js - 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是否有特殊的可能?或者可能是权限问题?
解决方案
这是一个格式化的,希望有用的答案,在尝试使用他们的详细文档进行整理之后。
首先,该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 大师那里得到一些反馈!
推荐阅读
- sqlite - 如何从表中选择唯一值并仅选择每个条目之间的时间高于 10 秒的时间戳
- javascript - Webpack - 如何使 HTML 文档中的编译函数可用?
- java - jvm options -XX:+SafepointTimeout -XX:SafepointTimeoutDelay 看起来不起作用
- python - 如何在 tf.keras 中设置 Conv2D 的默认参数?
- join - codeigniter 如何连接两个表以拥有两个 Id 列
- python - 我怎样才能修复协程从未等待过?
- swift - 我想在自定义 UITableViewCell 中创建一个包含 n 个 UITextField 的注册表单
- android - 问题:Google 违反权限政策删除应用
- javascript - 流畅刷新页面
- angular - Angular、TypeScript 中的实时 HTML 表单验证 (onBlur)