# 发布 Node.js 包

在本教程中，你将了解如何在持续集成 (CI) 工作流中将 Node.js 包发布到注册表。

## 简介

本指南介绍如何创建一个工作流程，以在持续集成 (CI) 测试通过后将 Node.js 包发布到 GitHub Packages 和 npm 注册表。

## 先决条件

建议基本了解工作流程配置选项和如何创建工作流程文件。 有关详细信息，请参阅“[撰写工作流程](/zh/actions/learn-github-actions)”。

有关为 Node.js 项目创建 CI 工作流的详细信息，请参阅“[构建和测试 Node.js](/zh/actions/automating-builds-and-tests/building-and-testing-nodejs)”。

你可能还发现基本了解以下内容是有帮助的：

* [在 npm 注册表上工作](/zh/packages/working-with-a-github-packages-registry/working-with-the-npm-registry)
* [在变量中存储信息](/zh/actions/learn-github-actions/variables)
* [在 GitHub Actions 中使用机密](/zh/actions/security-guides/using-secrets-in-github-actions)
* [在工作流中使用 GITHUB\_TOKEN 进行身份验证](/zh/actions/security-guides/automatic-token-authentication)

## 关于包配置

```
          `name` 文件中的 `version` 和 `package.json` 字段创建一个唯一标识符，注册表使用该标识符将包链接到注册表。 可以通过在 `description` 文件中包含一个 `package.json` 字段来添加软件包列表页面的摘要。 有关详细信息，请参阅 npm 文档中的“[创建 package.json 文件](https://docs.npmjs.com/creating-a-package-json-file)”和“[创建 Node.js 模块](https://docs.npmjs.com/creating-node-js-modules)”。
```

当本地 `.npmrc` 文件存在并指定了 `registry` 值时，`npm publish` 命令将使用在 `.npmrc` 文件中配置的注册表。 可使用 `setup-node` 操作在运行器上创建本地 `.npmrc` 文件以配置默认注册表和范围。 `setup-node` 操作也接受身份验证令牌作为输入，用于访问私人注册表或发布节点包。 有关详细信息，请参阅 [`setup-node`](https://github.com/actions/setup-node/)。

可以使用 `setup-node` 操作指定运行器上安装的 Node.js 版本。

如果在工作流中添加步骤来配置 `publishConfig` 文件中的 `package.json` 字段，则无需使用 `setup-node` 操作指定 registry-url，但是只能将包发布到一个注册表。 有关详细信息，请参阅 npm 文档中的“[publishConfig](https://docs.npmjs.com/cli/v9/configuring-npm/package-json#publishconfig)”。

## 发布包到 npm 注册表

每次发布新版本时，都可以触发工作流来发布包。 当触发类型 `published` 的发布事件时，执行下例中的过程。 如果 CI 测试通过，该过程会将包上传到 npm 注册表。 有关详细信息，请参阅“[管理存储库中的发行版](/zh/repositories/releasing-projects-on-github/managing-releases-in-a-repository#creating-a-release)”。

要在您的工作流程中针对 npm 注册表执行经过身份验证的操作，您需要将 npm 身份验证令牌存储为机密。 例如，创建名为 `NPM_TOKEN` 的存储库机密。 有关详细信息，请参阅“[在 GitHub Actions 中使用机密](/zh/actions/security-guides/using-secrets-in-github-actions)”。

默认情况下，npm 使用 `name` 文件的 `package.json` 字段来确定已发布包的名称。 当发布到全局命名空间时，您只需要包含包名称。 例如，将名为 `my-package` 的包发布到 `https://www.npmjs.com/package/my-package`。

如果要发布包含范围前缀的包，请在 `package.json` 文件的名称中包含范围。 例如，如果 npm 范围前缀是“octocat”并且包名称是“hello-world”，那么 `name` 文件中的 `package.json` 应为 `@octocat/hello-world`。 如果 npm 包使用范围前缀并且包是公共的，则需要使用选项 `npm publish --access public`。 这是 npm 需要用来防止有人无意中发布私有包的选项。

如果要发布具有证明的包，请将 `--provenance` 标志包含在命令 `npm publish` 中。 这样，你就可以公开且可验证地确定包的生成位置和方式，从而增加使用包的人员的供应链安全性。 有关详细信息，请参阅 npm 文档中的[生成来源语句](https://docs.npmjs.com/generating-provenance-statements)。

此示例将 `NPM_TOKEN` 机密存储在 `NODE_AUTH_TOKEN` 环境变量中。 当 `setup-node` 操作创建 `.npmrc` 文件时，会引用来自 `NODE_AUTH_TOKEN` 环境变量的令牌。

```yaml copy
name: Publish Package to npmjs
on:
  release:
    types: [published]
jobs:
  build:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      id-token: write
    steps:
      - uses: actions/checkout@v5
      # Setup .npmrc file to publish to npm
      - uses: actions/setup-node@v4
        with:
          node-version: '20.x'
          registry-url: 'https://registry.npmjs.org'
      - run: npm ci
      - run: npm publish --provenance --access public
        env:
          NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
```

在上面的示例中，`setup-node` 操作在运行器上创建了一个具有以下内容的 `.npmrc` 文件：

```shell
//registry.npmjs.org/:_authToken=${NODE_AUTH_TOKEN}
registry=https://registry.npmjs.org/
always-auth=true
```

请注意，需要在 `registry-url` 中将 `https://registry.npmjs.org/` 设置为 `setup-node` 才能正确配置凭据。

## 将包发布到 GitHub Packages

每次发布新版本时，都可以触发工作流来发布包。 当触发类型 `published` 的发布事件时，执行下例中的过程。 如果 CI 测试通过，该过程会将包上传到 GitHub Packages。 有关详细信息，请参阅“[管理存储库中的发行版](/zh/repositories/releasing-projects-on-github/managing-releases-in-a-repository#creating-a-release)”。

### 配置目标仓库

使用 `repository` 键将包链接到 GitHub Packages 是可选操作。 如果你选择不在 `repository` 文件中提供 `package.json` 密钥，则你的包在发布时不会链接到存储库，但你可以选择稍后将包连接到存储库。

如果您在 `repository` 文件中确实提供了 `package.json` 密钥，那么该密钥中的存储库将用作 GitHub Packages 的目标 npm注册表。 例如，发布以下 `package.json` 结果将导致名为 `my-package` 的包发布到 `octocat/my-other-repo` GitHub 存储库。

```json
{
  "name": "@octocat/my-package",
  "repository": {
    "type": "git",
    "url": "https://github.com/octocat/my-other-repo.git"
  },
}
```

### 向目标仓库进行认证

要在工作流中对 GitHub Packages 注册表执行经过身份验证的操作，可以使用 `GITHUB_TOKEN`。 每当工作流中的作业开始时，`GITHUB_TOKEN` 机密都会设置为存储库的访问令牌。 应在工作流文件中设置此访问令牌的权限，以授予 `contents` 权限的读取访问权限，并授予 `packages` 权限的写入访问权限。 有关详细信息，请参阅“[在工作流中使用 GITHUB\_TOKEN 进行身份验证](/zh/actions/security-guides/automatic-token-authentication)”。

如果要将包发布到其他存储库，必须使用对目标存储库中的包具有写入权限的 personal access token (classic)。 有关详细信息，请参阅 [管理个人访问令牌](/zh/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token) 和 [在 GitHub Actions 中使用机密](/zh/actions/security-guides/using-secrets-in-github-actions)。

### 示例工作流

此示例将 `GITHUB_TOKEN` 机密存储在 `NODE_AUTH_TOKEN` 环境变量中。 当 `setup-node` 操作创建 `.npmrc` 文件时，会引用来自 `NODE_AUTH_TOKEN` 环境变量的令牌。

```yaml copy
name: Publish package to GitHub Packages
on:
  release:
    types: [published]
jobs:
  build:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      packages: write
    steps:
      - uses: actions/checkout@v5
      # Setup .npmrc file to publish to GitHub Packages
      - uses: actions/setup-node@v4
        with:
          node-version: '20.x'
          registry-url: 'https://npm.pkg.github.com'
          # Defaults to the user or organization that owns the workflow file
          scope: '@octocat'
      - run: npm ci
      - run: npm publish
        env:
          NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
```

```
          `setup-node` 操作在运行器上创建一个 `.npmrc` 文件。 当对 `scope` 操作使用 `setup-node` 输入时，`.npmrc` 文件包含范围前缀。 默认情况下，`setup-node` 操作会将 `.npmrc` 文件中的范围设置为包含该工作流文件的帐户。
```

```shell
//npm.pkg.github.com/:_authToken=${NODE_AUTH_TOKEN}
@octocat:registry=https://npm.pkg.github.com
always-auth=true
```

## 使用 Yarn 发布软件包

如果您使用 Yarn 包管理器，可以使用 Yarn 安装和发布包。

```yaml copy
name: Publish Package to npmjs
on:
  release:
    types: [published]
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v5
      # Setup .npmrc file to publish to npm
      - uses: actions/setup-node@v4
        with:
          node-version: '20.x'
          registry-url: 'https://registry.npmjs.org'
          # Defaults to the user or organization that owns the workflow file
          scope: '@octocat'
      - run: yarn
      - run: yarn npm publish // for Yarn version 1, use `yarn publish` instead
        env:
          NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
```

要在发布期间进行注册表身份验证，请确保在 `yarnrc.yml` 文件中也定义了你的身份验证令牌。 有关详细信息，请参阅 Yarn 文档中的[设置](https://yarnpkg.com/configuration/yarnrc#npmAuthToken)一文。