极狐 GitLab

软件包仓库中的 npm 软件包

Tier: 基础版,专业版,旗舰版

Offering: JihuLab.com,私有化部署

Node Package Manager (npm) 是 JavaScript 和 Node.js 的默认软件包管理器。开发者使用 npm 共享和复用代码、管理依赖项并简化项目工作流。在极狐GitLab 中,npm 软件包在软件开发生命周期中发挥着至关重要的作用。

有关 npm 端点的信息,请参见 API。

向软件包仓库进行身份验证#

要从私有项目或私有群组发布或安装软件包,您必须向软件包仓库进行身份验证。如果项目或群组是公开的,则无需进行身份验证。如果项目是内部项目,您必须是极狐GitLab 实例上的注册用户。匿名用户无法从内部项目拉取软件包。

要进行身份验证,您可以使用以下任一方式:

如果您的组织使用双因素认证 (2FA),则必须使用作用域设置为 api的个人访问令牌。有关更多信息,请查看令牌指南。

请勿使用此处记录之外的身份验证方法。未记录的身份验证方法可能会在未来被移除。

使用 .npmrc 文件#

在与 package.json 相同的目录中创建或编辑 .npmrc 文件。在 .npmrc 文件中包含以下行:

shell
//<domain_name>/api/v4/projects/<project_id>/packages/npm/:_authToken="${NPM_TOKEN}"

切勿将极狐GitLab 令牌(或任何令牌)直接硬编码到 .npmrc 文件或任何其他可能 提交到代码仓库的文件中。

例如:

shell
//<domain_name>/api/v4/packages/npm/:_authToken="${NPM_TOKEN}"

将 <domain_name> 替换为您的域名。例如,gitlab.com。

使用 npm config set#

为此:

shell
npm config set -- //<domain_name>/:_authToken=<token>

根据您的 npm 版本,您可能需要更改 URL:

  • 在 npm 7 或更早版本中,使用端点的完整 URL。
  • 在 8 及更高版本中,对于 _authToken 参数,您可以使用 URI 片段而不是完整 URL。有关更多信息,请参见与认证相关的配置。

如果您使用 Yarn Classic 1.x,则在设置认证令牌时必须指定完整的端点路径。 Yarn Classic 不支持分层认证匹配,因此在父路径(如 //gitlab.com/api/v4/)上设置的令牌不会应用于子路径(如 //gitlab.com/api/v4/groups/<group_id>/-/packages/npm/)。请始终使用完整的 群组或项目路径。有关更多信息,请参见 Yarn Classic 在使用缩短的认证路径时返回 401 Unauthorized。

例如:

shell
npm config set -- //<domain_name>/api/v4/packages/npm/:_authToken=<token>

请确保替换:

  • <domain_name> 替换为您的域名。例如,gitlab.com。
  • <token> 替换为您的部署令牌、群组访问令牌、项目访问令牌或个人访问令牌。

设置仓库 URL#

要从极狐GitLab 软件包仓库发布或安装软件包,您需要将 npm 配置为使用正确的仓库 URL。配置方法和 URL 结构取决于您是发布还是安装软件包。

在配置仓库 URL 之前,了解不同配置方法的作用范围很重要:

  • .npmrc 文件:配置仅对包含该文件的文件夹生效。
  • npm config set 命令:这会修改全局 npm 配置,并影响您系统上运行的所有 npm 命令。
  • package.json中的 publishConfig:此配置特定于该软件包,仅在发布该软件包时适用。

运行 npm config set 会更改全局 npm 配置。该更改会影响您系统上 运行的所有 npm 命令,无论当前工作目录是什么。使用此方法时请谨慎, 尤其是在共享系统上。

用于发布软件包#

发布软件包时,请使用项目端点:

shell
https://gitlab.example.com/api/v4/projects/<project_id>/packages/npm/

将 gitlab.example.com 替换为您的极狐GitLab 实例的域名,将 <project_id> 替换为您的项目 ID。要配置此 URL,请使用以下方法之一:

在项目根目录中创建或编辑 .npmrc 文件:

plaintext
@scope:registry=https://gitlab.example.com/api/v4/projects/<project_id>/packages/npm/ //gitlab.example.com/api/v4/projects/<project_id>/packages/npm/:_authToken="${NPM_TOKEN}"

将 @scope 替换为您的软件包作用域。

用于安装软件包#

安装软件包时,您可以使用项目、群组或实例端点。URL 结构会相应地有所不同。要配置这些 URL,请使用以下方法之一:

在项目根目录中创建或编辑 .npmrc 文件。根据您的需求使用相应的 URL:

  • 对于项目:

    shell
    @scope:registry=https://gitlab.example.com/api/v4/projects/<project_id>/packages/npm/
  • 对于群组:

    shell
    @scope:registry=https://gitlab.example.com/api/v4/groups/<group_id>/-/packages/npm/
  • 对于实例:

    shell
    @scope:registry=https://gitlab.example.com/api/v4/packages/npm/

将 gitlab.example.com、<project_id>、<group_id> 和 @scope 替换为适用于您的极狐GitLab 实例和软件包的值。

配置仓库 URL 后,您就可以向软件包仓库进行身份验证了。

发布到极狐GitLab 软件包仓库#

要将 npm 软件包发布到极狐GitLab 软件包仓库,您必须经过身份验证。

命名约定#

根据软件包的安装方式,您可能需要遵循命名约定。

您可以使用三种 API 端点之一来安装软件包:

  • 实例:当您在不同极狐GitLab 群组中或各自命名空间中有许多 npm 软件包时使用。
  • 群组:当您在同一群组或子群组下的不同项目中有许多 npm 软件包时使用。
  • 项目:当您的 npm 软件包很少且它们不在同一极狐GitLab 群组中时使用。

如果您计划从项目或群组安装软件包,则不必遵循命名约定。

如果您计划从实例安装软件包,则必须为软件包命名并带有作用域。带作用域的软件包以 @ 开头,格式为 @owner/package-name。您可以在 .npmrc 文件中设置软件包的作用域,并通过在 package.json中使用 publishConfig 选项来设置。

  • @scope 使用的值是承载这些软件包的项目根,而不是 软件包自身源代码所在项目的根。作用域应使用小写。
  • 软件包名称可以是您想要的任何内容。

有关更多信息,请参见带作用域的软件包。

项目 URL软件包仓库位于作用域完整软件包名称
https://gitlab.com/my-org/engineering-group/analyticsAnalytics@my-org@my-org/package-name

请确保 package.json 文件中的软件包名称符合此约定:

shell
"name": "@my-org/package-name"

使用命令行发布软件包#

配置身份验证后,使用以下命令发布 NPM 软件包:

shell
npm publish

如果您使用 .npmrc 文件进行身份验证,请设置预期的环境变量:

shell
NPM_TOKEN=<token> npm publish

如果上传的软件包有多个 package.json 文件,则只使用找到的第一个,其他文件将被忽略。

使用 CI/CD 流水线发布软件包#

使用 CI/CD 流水线发布时,您可以使用预定义变量 ${CI_PROJECT_ID} 和 ${CI_JOB_TOKEN} 向您项目的软件包仓库进行身份验证。您可以使用这些变量创建一个 .npmrc 文件,以便在 CI/CD 作业执行期间进行身份验证。

生成 .npmrc 文件时,如果 ${CI_SERVER_HOST} 后面是默认端口,请勿指定该端口。 http URL 默认为 80,https URL 默认为 443。

在包含 package.json的极狐GitLab 项目中,编辑或创建 .gitlab-ci.yml 文件。例如:

yaml
1default: 2 image: node:latest 3 4stages: 5 - deploy 6 7publish-npm: 8 stage: deploy 9 script: 10 - echo "@scope:registry=https://${CI_SERVER_HOST}/api/v4/projects/${CI_PROJECT_ID}/packages/npm/" > .npmrc 11 - echo "//${CI_SERVER_HOST}/api/v4/projects/${CI_PROJECT_ID}/packages/npm/:_authToken=${CI_JOB_TOKEN}" >> .npmrc 12 - npm publish

将 @scope 替换为正在发布的软件包的作用域。

当流水线中的 publish-npm 作业运行时,您的软件包即发布到软件包仓库。

安装软件包#

如果多个软件包具有相同的名称和版本,当您安装软件包时,将检索最近发布的软件包。

您可以从极狐GitLab 项目、群组或实例安装软件包:

  • 实例:当您在不同极狐GitLab 群组中或各自命名空间中有许多 npm 软件包时使用。
  • 群组:当您在同一极狐GitLab 群组中的不同项目中有许多 npm 软件包时使用。
  • 项目:当您的 npm 软件包很少且它们不在同一极狐GitLab 群组中时使用。

从实例安装#

先决条件:

  • 该软件包是按照带作用域的命名约定发布的。
  1. 向软件包仓库进行身份验证。

  2. 设置仓库:

    shell
    npm config set @scope:registry https://<domain_name>.com/api/v4/packages/npm/
    • 将 @scope 替换为您要安装软件包所在项目的顶级群组。
    • 将 <domain_name> 替换为您的域名,例如 gitlab.com。
  3. 安装软件包:

    shell
    npm install @scope/my-package

从群组安装#

  1. 向软件包仓库进行身份验证。

  2. 设置仓库:

    shell
    npm config set @scope:registry=https://<domain_name>/api/v4/groups/<group_id>/-/packages/npm/
    • 将 @scope 替换为您要安装软件包所在群组的顶级群组。
    • 将 <domain_name> 替换为您的域名,例如 gitlab.com。
    • 将 <group_id> 替换为您的群组 ID,可在群组主页上找到。
  3. 安装软件包:

    shell
    npm install @scope/my-package

从项目安装#

  1. 向软件包仓库进行身份验证。

  2. 设置仓库:

    shell
    npm config set @scope:registry=https://<domain_name>/api/v4/projects/<project_id>/packages/npm/
    • 将 @scope 替换为您要安装软件包所在项目的顶级群组。
    • 将 <domain_name> 替换为您的域名,例如 gitlab.com。
    • 将 <project_id> 替换为您的项目 ID,可在项目概览页面上找到。
  3. 安装软件包:

    shell
    npm install @scope/my-package

在 CI/CD 流水线中安装软件包#

在 CI/CD 流水线中安装软件包时,您可以使用预定义变量 ${CI_PROJECT_ID} 和 ${CI_JOB_TOKEN} 向您项目的软件包仓库进行身份验证。您可以使用这些变量创建一个 .npmrc 文件,以便在 CI/CD 作业执行期间进行身份验证。

生成 .npmrc 文件时,如果 ${CI_SERVER_HOST} 后面是默认端口,请勿指定该端口。 http URL 默认为 80,https URL 默认为 443。

在包含 package.json的极狐GitLab 项目中,编辑或创建 .gitlab-ci.yml 文件。例如:

yaml
1default: 2 image: node:latest 3 4stages: 5 - deploy 6 7publish-npm: 8 stage: deploy 9 script: 10 - echo "@scope:registry=https://${CI_SERVER_HOST}/api/v4/projects/${CI_PROJECT_ID}/packages/npm/" > .npmrc 11 - echo "//${CI_SERVER_HOST}/api/v4/projects/${CI_PROJECT_ID}/packages/npm/:_authToken=${CI_JOB_TOKEN}" >> .npmrc 12 - npm install @scope/my-package

将 @scope 替换为正在安装的软件包的作用域,以及软件包名称。

上一个示例使用项目级端点。要使用群组级或实例级端点,请按照从群组安装或从实例安装中所述配置仓库和身份验证令牌 URL。

软件包转发到 npmjs.com#

当在软件包仓库中找不到 npm 软件包时,极狐GitLab 会以 HTTP 重定向进行响应,以便请求客户端可以将请求重新发送到 npmjs.com。

管理员可以在持续集成设置中禁用此行为。

群组所有者可以在群组的软件包和镜像仓库设置中禁用此行为。

相关改进在史诗 3608中跟踪。

弃用软件包#

您可以弃用软件包,以便在获取该软件包时显示弃用警告。

先决条件:

  • 您拥有删除软件包所需的权限。
  • 您已向软件包仓库进行身份验证。

从命令行运行:

shell
npm deprecate @scope/package "Deprecation message"

CLI 还接受 @scope/package的版本范围。例如:

shell
npm deprecate @scope/package "All package versions are deprecated" npm deprecate @scope/package@1.0.1 "Only version 1.0.1 is deprecated" npm deprecate @scope/package@"< 1.0.5" "All package versions less than 1.0.5 are deprecated"

当软件包被弃用时,其状态将更新为 deprecated。

移除弃用警告#

要移除软件包的弃用警告,请为消息指定 ""(空字符串)。例如:

shell
npm deprecate @scope/package ""

当软件包的弃用警告被移除时,其状态将更新为 default。

删除软件包#

先决条件:

  • 您必须具有维护者或所有者角色。

在删除软件包之前,请确保您了解相关的安全风险。

要删除软件包,您可以:

实用提示#

从其他组织安装 npm 软件包#

您可以将软件包请求路由到极狐GitLab 之外的组织和用户。

为此,请向您的 .npmrc 文件添加行。将 @my-other-org 替换为拥有您项目代码仓库的命名空间或群组,并使用您组织的 URL。名称区分大小写,并且必须与您的群组或命名空间的名称完全匹配。

shell
@scope:registry=https://my_domain_name.com/api/v4/packages/npm/ @my-other-org:registry=https://my_domain_name.example.com/api/v4/packages/npm/

npm 元数据#

极狐GitLab 软件包仓库向 npm 客户端公开以下属性:

  • name
  • versions
    • name
    • version
    • deprecated
    • dependencies
    • devDependencies
    • bundleDependencies
    • peerDependencies
    • bin
    • directories
    • dist
    • engines
    • _hasShrinkwrap
    • hasInstallScript:true(如果此版本具有安装脚本)

有关更多信息,请参见简略版本对象。

添加 npm 分发标签#

您可以为新发布的软件包添加分发标签。标签是可选的,一次只能分配给一个软件包。

当您发布不带标签的软件包时,默认会添加 latest 标签。当您安装软件包而未指定标签或版本时,将使用 latest 标签。

支持的 dist-tag 命令示例:

shell
npm publish @scope/package --tag # Publish a package with new tag npm dist-tag add @scope/package@version my-tag # Add a tag to an existing package npm dist-tag ls @scope/package # List all tags under the package npm dist-tag rm @scope/package@version my-tag # Delete a tag from the package npm install @scope/package@my-tag # Install a specific tag

从 CI/CD#

您可以使用以下任一令牌在极狐GitLab CI/CD 作业中运行 npm dist-tag 命令:

先决条件:

  • 您的 npm 版本为 6.9.1 或更高版本。在更早的版本中,由于 npm 6.9.0 中的错误,删除分发标签会失败。

例如:

yaml
npm-deploy-job: script: - echo "//${CI_SERVER_HOST}/api/v4/projects/${CI_PROJECT_ID}/packages/npm/:_authToken=${CI_JOB_TOKEN}">.npmrc - npm dist-tag add @scope/package@version my-tag

审计 npm 软件包#

极狐GitLab 支持 npm audit 命令,允许您检查软件包是否存在已知漏洞。

使用 npm audit#

先决条件:

  • 配置向软件包仓库的身份验证。
  • 设置仓库 URL。

要运行安全审计,您可以运行以下命令:

shell
npm audit --registry=https://gitlab.example.com/api/v4/packages/npm/

或者,如果您已经设置了仓库配置:

shell
npm audit

npm audit 命令会检查您的依赖项是否存在已知漏洞并提供报告。

npm audit 工作流#

当您针对极狐GitLab 软件包仓库运行 npm audit 时,会出现以下两种情况之一:

  1. 如果启用了软件包转发(默认),极狐GitLab 会将审计请求转发到 npmjs.com,以检索公共和私有软件包的漏洞信息。
  2. 如果禁用了软件包转发,极狐GitLab 会返回空结果集。极狐GitLab 不会独立扫描软件包的漏洞。

重要安全注意事项#

如果您未将极狐GitLab 指定为软件包仓库(通过 --registry 标志或在 .npmrc 文件中将其设置为默认仓库),则审计请求会发送到公共 npm 仓库。

在这种情况下,请求正文会包含您项目中所有软件包的信息,包括您的私有极狐GitLab 软件包。

为确保您的私有软件包信息保留在极狐GitLab 内,在运行 npm audit 命令时请始终确保指定极狐GitLab 仓库。

已知问题#

  • 审计结果取决于是否启用了软件包转发。如果管理员或群组所有者禁用了转发,npm audit 不会返回漏洞信息。
  • 审计请求包含您项目中所有软件包的信息,包括私有软件包。

支持的 CLI 命令#

极狐GitLab npm 仓库支持以下用于 npm CLI(npm)和 yarn CLI (yarn)的命令:

  • npm install:安装 npm 软件包。
  • npm publish:将 npm 软件包发布到仓库。
  • npm dist-tag add:为 npm 软件包添加 dist-tag。
  • npm dist-tag ls:列出软件包的 dist-tag。
  • npm dist-tag rm:删除 dist-tag。
  • npm ci:直接从您的 package-lock.json 文件安装 npm 软件包。
  • npm view:显示软件包元数据。
  • npm pack:从软件包创建 tarball。
  • npm deprecate:弃用软件包的某个版本。
  • npm audit:检查项目依赖项中的漏洞。

故障排除#

npm 日志无法正确显示#

您可能会遇到如下错误:

shell
npm ERR! A complete log of this run can be found in: .npm/_logs/<date>-debug-0

如果日志未出现在 .npm/_logs/ 目录中,您可以将日志复制到根目录并在那里查看:

yaml
1 script: 2 - npm install --loglevel verbose 3 - cp -r /root/.npm/_logs/ . 4 artifacts: 5 paths: 6 - './_logs'

npm 日志会作为产物复制到 /root/.npm/_logs/。

在 npm install 或 yarn 时出现 404 Not Found 错误#

使用 CI_JOB_TOKEN 安装依赖项位于另一个项目中的 npm 软件包时,会出现 404 Not Found 错误。您需要使用一个有权访问该软件包及其所有依赖项的令牌进行身份验证。

当您使用 Yarn Classic 从群组仓库安装软件包时,软件包解析可能会成功,但 tarball 下载可能会失败并出现 404 Not Found 错误。出现此错误是因为群组端点返回的软件包元数据包含指向项目端点的 tarball URL。您必须为群组和项目端点都配置身份验证令牌:

toml
//gitlab.example.com/api/v4/groups/<group_id>/-/packages/npm/:_authToken=<token> //gitlab.example.com/api/v4/projects/<project_id>/packages/npm/:_authToken=<token>

有关更多信息,请参见 Yarn Classic 在从群组安装获取 tarball 时返回 404 Not Found。

如果软件包及其依赖项位于不同项目但属于同一群组,您可以使用群组部署令牌:

toml
//gitlab.example.com/api/v4/packages/npm/:_authToken=<group-token> @group-scope:registry=https://gitlab.example.com/api/v4/packages/npm/

如果软件包及其依赖项分布在多个群组中,您可以使用某个用户的个人访问令牌,该用户有权访问所有群组或各个项目:

toml
//gitlab.example.com/api/v4/packages/npm/:_authToken=<personal-access-token> @group-1:registry=https://gitlab.example.com/api/v4/packages/npm/ @group-2:registry=https://gitlab.example.com/api/v4/packages/npm/

个人访问令牌必须谨慎对待。请阅读我们的令牌安全注意事项, 了解有关管理个人访问令牌的指南(例如,设置较短的过期时间并使用最小作用域)。

npm publish 指向默认 npm 仓库(registry.npmjs.org)#

请确保您的软件包作用域在 package.json 和 .npmrc 文件中设置一致。

例如,如果您在极狐GitLab 中的项目名称为 @scope/my-package,那么您的 package.json 文件应如下所示:

json
{ "name": "@scope/my-package" }

而 .npmrc 文件应如下所示:

shell
@scope:registry=https://your_domain_name/api/v4/projects/your_project_id/packages/npm/ //your_domain_name/api/v4/projects/your_project_id/packages/npm/:_authToken="${NPM_TOKEN}"

npm install 返回 npm ERR! 403 Forbidden#

如果您遇到此错误,请确保:

  • 您的项目设置中已启用软件包仓库。虽然软件包仓库默认启用,但也可以将其禁用。
  • 您的令牌未过期且具有适当的权限。
  • 在给定作用域内尚不存在具有相同名称或版本的软件包。
  • 带作用域的软件包 URL 包含尾部斜杠:
    • 正确://gitlab.example.com/api/v4/packages/npm/
    • 错误://gitlab.example.com/api/v4/packages/npm

npm publish 返回 npm ERR! 400 Bad Request#

如果您遇到此错误,可能是由以下问题之一引起的。

软件包名称不符合命名约定#

您的软件包名称可能不符合 @scope/package-name 软件包命名约定。

请确保名称完全符合约定,包括大小写。然后尝试再次发布。

软件包已存在#

您的软件包已发布到同一根命名空间中的另一个项目,因此无法使用相同名称再次发布。

即使先前发布的软件包名称相同但版本不同,也是如此。

软件包 JSON 文件过大#

请确保您的 package.json 文件不超过 20,000 个字符。