npm install 在 Jenkins 管道中失败,即使我配置了 withNpm step 以使用自定义 .nrpmrc 文件

npm install fails in Jenkins pipeline even though I configured withNpm step to use a custom .nrpmrc file

这是我的管道:

pipeline {
    agent any
    tools {nodejs "node10"}

    stages {
        stage('Build') {
            steps {
                withNPM(npmrcConfig: 'xxx') {
                sh "npm config ls"
                sh "npm install"
                sh "ng build"
                }
            }
        }
    }
}

Jenkins 服务器没有互联网连接。它必须从 Nexus 服务器下载 npm 工件。

我已经使用 npm 配置上传了这个托管文件:

registry=http://xxxx:8081/nexus/repository/central-npm-registry/

central-npm-registry 是 npm 注册表的代理。

注意:如果我从我的本地机器上使用这个 .npmrc 文件,它工作正常。

从 Jenkins 构建时,我看到显然 npm 配置文件设置正确但安装失败,有什么线索吗?

Using settings config with name central-npm-registry
A workscape local .npmrc already exists and will be overwrriten for the build.
Writing .npmrc file: /root/.jenkins/workspace/central-npm-registry/myapp/.npmrc
[Pipeline] {
[Pipeline] sh
[myapp] Running shell script
+ npm config ls
; cli configs
metrics-registry = "http://xxxxx:8081/nexus/repository/central-npm-registry/"
scope = ""
user-agent = "npm/6.4.1 node/v11.0.0 linux x64"

; project config /root/.jenkins/workspace/central-npm-registry/myapp/.npmrc
registry = "http://xxxxx:8081/nexus/repository/central-npm-registry/"

; node bin location = /root/.jenkins/tools/jenkins.plugins.nodejs.tools.NodeJSInstallation/node10/bin/node
; cwd = /root/.jenkins/workspace/central-npm-registry/myapp
; HOME = /root
; "npm config ls -l" to show all defaults.

[Pipeline] sh
[myapp] Running shell script
+ npm install

> node-sass@4.10.0 install /root/.jenkins/workspace/central-npm-registry/myapp/node_modules/node-sass
> node scripts/install.js

Downloading binary from https://github.com/sass/node-sass/releases/download/v4.10.0/linux-x64-67_binding.node
Cannot download "https://github.com/sass/node-sass/releases/download/v4.10.0/linux-x64-67_binding.node": 

connect ECONNREFUSED 140.82.118.3:443

Hint: If github.com is not accessible in your location
      try setting a proxy via HTTP_PROXY, e.g. 

      export HTTP_PROXY=http://example.com:1234

or configure npm proxy via

      npm config set proxy http://example.com:8080

> node-sass@4.10.0 postinstall /root/.jenkins/workspace/central-npm-registry/myapp/node_modules/node-sass
> node scripts/build.js

Building: /root/.jenkins/tools/jenkins.plugins.nodejs.tools.NodeJSInstallation/node10/bin/node /root/.jenkins/workspace/central-npm-registry/myapp/node_modules/node-gyp/bin/node-gyp.js rebuild --verbose --libsass_ext= --libsass_cflags= --libsass_ldflags= --libsass_library=
gyp info it worked if it ends with ok
gyp verb cli [ '/root/.jenkins/tools/jenkins.plugins.nodejs.tools.NodeJSInstallation/node10/bin/node',
gyp verb cli   '/root/.jenkins/workspace/central-npm-registry/myapp/node_modules/node-gyp/bin/node-gyp.js',
gyp verb cli   'rebuild',
gyp verb cli   '--verbose',
gyp verb cli   '--libsass_ext=',
gyp verb cli   '--libsass_cflags=',
gyp verb cli   '--libsass_ldflags=',
gyp verb cli   '--libsass_library=' ]
gyp info using node-gyp@3.8.0
gyp info using node@11.0.0 | linux | x64
gyp verb command rebuild []
gyp verb command clean []
gyp verb clean removing "build" directory
gyp verb command configure []
gyp verb check python checking for Python executable "python2" in the PATH
gyp verb `which` succeeded python2 /usr/bin/python2
gyp verb check python version `/usr/bin/python2 -c "import sys; print "2.6.6
gyp verb check python version .%s.%s" % sys.version_info[:3];"` returned: %j
gyp verb get node dir no --target version specified, falling back to host node version: 11.0.0
gyp verb command install [ '11.0.0' ]
gyp verb install input version string "11.0.0"
gyp verb install installing version: 11.0.0
gyp verb install --ensure was passed, so won't reinstall if already installed
gyp verb install version not already installed, continuing with install 11.0.0
gyp verb ensuring nodedir is created /root/.node-gyp/11.0.0
gyp verb created nodedir /root/.node-gyp/11.0.0
gyp http GET https://nodejs.org/download/release/v11.0.0/node-v11.0.0-headers.tar.gz
gyp WARN install got an error, rolling back install
gyp verb command remove [ '11.0.0' ]
gyp verb remove using node-gyp dir: /root/.node-gyp
gyp verb remove removing target version: 11.0.0
gyp verb remove removing development files for version: 11.0.0
gyp ERR! configure error 
gyp ERR! stack Error: connect ECONNREFUSED 104.20.23.46:443
gyp ERR! stack     at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1117:14)
gyp ERR! System Linux 2.6.32-754.3.5.el6.x86_64
gyp ERR! command "/root/.jenkins/tools/jenkins.plugins.nodejs.tools.NodeJSInstallation/node10/bin/node" "/root/.jenkins/workspace/central-npm-registry/myapp/node_modules/node-gyp/bin/node-gyp.js" "rebuild" "--verbose" "--libsass_ext=" "--libsass_cflags=" "--libsass_ldflags=" "--libsass_library="
gyp ERR! cwd /root/.jenkins/workspace/central-npm-registry/myapp/node_modules/node-sass
gyp ERR! node -v v11.0.0
gyp ERR! node-gyp -v v3.8.0
gyp ERR! not ok 
Build failed with error code: 1
npm WARN lifecycle poc-polizas@0.0.0~postinstall: cannot run in wd poc-polizas@0.0.0 node node-internals-webpack.js (wd=/root/.jenkins/workspace/central-npm-registry/myapp)
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@1.2.4 (node_modules/fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@1.2.4: wanted {"os":"darwin","arch":"any"} (current: {"os":"linux","arch":"x64"})
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: node-sass@4.10.0 (node_modules/node-sass):
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: node-sass@4.10.0 postinstall: `node scripts/build.js`
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: Exit status 1

up to date in 17.414s
[Pipeline] sh
[myapp] Running shell script
+ ng build
Your global Angular CLI version (7.1.4) is greater than your local
version (7.1.0). The local Angular CLI version is used.

To disable this warning use "ng config -g cli.warnings.versionMismatch false".

Date: 2018-12-21T12:00:06.525Z
Hash: 7e41e1c4bdf3d4157b68
Time: 25382ms
chunk {app-domain-list-list-module} app-domain-list-list-module.js, app-domain-list-list-module.js.map (app-domain-list-list-module) 46.1 kB  [rendered]
chunk {app-domain-login-login-module} app-domain-login-login-module.js, app-domain-login-login-module.js.map (app-domain-login-login-module) 14.3 kB  [rendered]
chunk {main} main.js, main.js.map (main) 198 kB [initial] [rendered]
chunk {polyfills} polyfills.js, polyfills.js.map (polyfills) 410 kB [initial] [rendered]
chunk {runtime} runtime.js, runtime.js.map (runtime) 8.91 kB [entry] [rendered]
chunk {scripts} scripts.js, scripts.js.map (scripts) 220 kB  [rendered]
chunk {styles} styles.js, styles.js.map (styles) 451 kB [initial] [rendered]
chunk {vendor} vendor.js, vendor.js.map (vendor) 4.15 MB [initial] [rendered]

ERROR in ./node_modules/jwa/index.js
Module not found: Error: Can't resolve 'crypto' in '/root/.jenkins/workspace/central-npm-registry/myapp/node_modules/jwa'
ERROR in ./node_modules/jws/lib/sign-stream.js
Module not found: Error: Can't resolve 'stream' in '/root/.jenkins/workspace/central-npm-registry/myapp/node_modules/jws/lib'
ERROR in ./node_modules/jws/lib/verify-stream.js
Module not found: Error: Can't resolve 'stream' in '/root/.jenkins/workspace/central-npm-registry/myapp/node_modules/jws/lib'
ERROR in ./node_modules/jws/lib/data-stream.js
Module not found: Error: Can't resolve 'stream' in '/root/.jenkins/workspace/central-npm-registry/myapp/node_modules/jws/lib'
[Pipeline] }
[Pipeline] // withNPM
[Pipeline] }
[Pipeline] // withEnv
[Pipeline] }
[Pipeline] // stage
[Pipeline] }
[Pipeline] // withEnv
[Pipeline] }
[Pipeline] // withEnv
[Pipeline] }
[Pipeline] // node
[Pipeline] End of Pipeline
ERROR: Unable to notify JIRA: [403] Forbidden
ERROR: Failed to notify JIRA at http://192.6.4.13:8080 on this builds completion -> java.net.ConnectException: Conexión rehusada (Connection refused)
ERROR: script returned exit code 1
Finished: FAILURE

我没用过Jenkins,经验谈不上。尽管如此,您收到一条 ECONNREFUSED 消息,让我认为问题出在您的网络设置中,而不是在您的脚本中。 curl www.google.comgit <any repo>ping 140.82.118.3 是否适用于 Jenkins?

只是为了解释这里发生了什么:

您(或您的客户)不希望从这台机器进行任何外部互联网访问,因此您已将 npm 配置为访问代理服务器。这似乎有效,大概您的 package.json 文件中有一堆依赖项,并且它们正在处理而没有问题。

但是,一些更大的 and/or 更复杂的软件包有自定义安装脚本,仅设置 npm 代理不会对这些安装脚本产生任何影响。例如,这些脚本可能会为节点编译扩展库,或者从 GitHub 下载本机二进制文件并使用它。

(事实上,针对速度优化的节点库的一个非常常见的模式是它们需要编译,并且在安装时,它们将首先查看是否可以从项目的 GitHub 页面;如果没有,他们会下载源码并编译。这就是本例中发生的情况,当然下载二进制文件失败,然后再次下载源码进行编译失败,所以安装中止。)

一些可能性:

  • 如果按照Travenin的建议提前在机器上预装麻烦的包,就可以避免这个错误。

  • 如果客户端正在做一些繁重的内部网络,并且有自定义 DNS,他们可以强制 DNS 解析 github.com(以及任何其他需要的域)解析到另一个代理你设置,这将根据需要将请求转发给 GitHub。

  • 您也可以使用 /etc/hosts 项在机器本身上强制解析。