目录

自动将软件包发布到 pub.dev

您可以通过以下方式自动化发布:

以下部分解释了如何配置自动化发布,以及如何根据您的偏好自定义发布流程。

配置自动化发布时,您无需创建长期存在的密钥并将其复制到您的自动化部署环境中。相反,身份验证依赖于由 GitHub Actions(参见 GitHub Actions 的 OIDC )或 Google Cloud IAM 签署的临时 OpenID Connect 令牌。

对于没有身份服务的环境,您可以使用 导出的服务帐号密钥 进行部署。此类导出的服务帐号密钥是长期存在的密钥,在某些环境中可能更容易使用,但如果意外泄露,也会带来更大的风险。

使用 GitHub Actions 发布软件包

#

您可以使用 GitHub Actions 配置自动化发布。这包括:

  • 在 pub.dev 上启用自动化发布,指定:

    • GitHub 仓库和
    • 必须匹配才能允许发布的 标签模式
  • 创建用于发布到 pub.dev 的 GitHub Actions 工作流

  • 推送要发布的版本的_git 标签_。

以下部分概述了如何完成这些步骤。

在 pub.dev 上配置来自 GitHub Actions 的自动化发布

#

要启用从 GitHub Actions 到 pub.dev 的自动化发布,您必须是:

  • 软件包的 上传者 ,或
  • 发布者的 管理员 (如果软件包由发布者拥有)。

如果您拥有足够的权限,您可以通过以下步骤启用自动化发布:

  1. 导航到 管理 选项卡( pub.dev/packages/<package>/admin )。

  2. 找到 自动化发布 部分。

  3. 点击 启用来自 GitHub Actions 的发布 ,这将提示您指定:

    • 仓库( <organization>/<repository> ,例如: dart-lang/pana ),
    • 标签模式 (包含 {{version}} 的字符串)。

仓库 是 GitHub 上的 <organization>/<repository> 。例如,如果您的仓库是 https://github.com/dart-lang/pana ,则必须在仓库字段中指定 dart-lang/pana

标签模式 是一个必须包含 {{version}} 的字符串。只有由匹配此 标签模式 的标签推送触发的 GitHub Actions 才允许发布您的软件包。

在 pub.dev 上配置来自 GitHub Actions 的发布

示例:v{{version}} 这样的 标签模式 允许 GitHub Actions(由 git tag v1.2.3 && git push v1.2.3 触发)发布您的软件包的版本 1.2.3 。因此, pubspec.yaml 中的 version 密钥与这个版本号匹配也很重要。

如果您的仓库包含多个软件包,请为每个软件包指定一个单独的 标签模式 。对于名为 my_package_name 的软件包,请考虑使用类似 my_package_name-v{{version}}标签模式

配置用于发布到 pub.dev 的 GitHub Action 工作流

#

在 pub.dev 上启用来自 GitHub Actions 的自动化发布后,您可以创建用于发布的 GitHub Actions 工作流。这可以通过创建如下所示的 .github/workflows/publish.yml 文件来完成:

yaml
# .github/workflows/publish.yml
name: 发布到 pub.dev

on:
  push:
    tags:
    # 必须与 pub.dev 上配置的标签模式对齐,通常只需将
      # {{version}} 替换为 [0-9]+.[0-9]+.[0-9]+
    - 'v[0-9]+.[0-9]+.[0-9]+' # pub.dev 上的标签模式:'v{{version}}'
    # 如果您更喜欢像 '1.2.3' 这样的标签,没有 'v' 前缀,则使用:
    # - '[0-9]+.[0-9]+.[0-9]+' # pub.dev 上的标签模式:'{{version}}'
    # 如果您的仓库包含多个软件包,请考虑使用以下模式:
    # - 'my_package_name-v[0-9]+.[0-9]+.[0-9]+'

# 使用 dart-lang 的可重用工作流进行发布。
jobs:
  publish:
    permissions:
      id-token: write # 使用 OIDC 进行身份验证所需
    uses: dart-lang/setup-dart/.github/workflows/publish.yml@v1
    # with:
    #   working-directory: path/to/package/within/repository

确保 on.push.tags 中的模式与 pub.dev 上指定的 标签模式 匹配。否则,GitHub Action 工作流将无法工作。如果从同一个仓库发布多个软件包,请使用每个软件包的 标签模式 ,例如 my_package_name-v{{version}} ,并为每个软件包创建一个单独的工作流文件。

上面的工作流文件使用 dart-lang/setup-dart/.github/workflows/publish.yml 来发布软件包。这是一个 可重用工作流 ,它允许 Dart 团队维护发布逻辑,并使 pub.dev 能够知道软件包是如何发布的。强烈建议使用此 可重用工作流

如果您的软件包中需要生成的代码,则最好将此生成的代码检入您的仓库。这简化了验证 pub.dev 上发布的文件与您仓库中的文件匹配的过程。如果将生成的或构建的工件检入您的仓库不合理,您可以创建类似以下内容的自定义工作流:

yaml
# .github/workflows/publish.yml
name: 发布到 pub.dev

on:
  push:
    tags:
    - 'v[0-9]+.[0-9]+.[0-9]+' # pub.dev 上的标签模式:'v{{version}}'

# 使用自定义工作流进行发布
jobs:
  publish:
    permissions:
      id-token: write # 使用 OIDC 进行身份验证所需
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: dart-lang/setup-dart@v1
      - name: 安装依赖项
        run: dart pub get
      # 在此处您可以插入所需的自定义步骤
      # - run: dart tool/generate-code.dart
      - name: 发布
        run: dart pub publish --force

该工作流使用临时 GitHub 签名的 OIDC 令牌pub.dev 进行身份验证,该令牌在 dart-lang/setup-dart 步骤中创建和配置。要发布到 pub.dev,后续步骤可以运行 dart pub publish --force

触发来自 GitHub Actions 的自动化发布

#

在您配置了 pub.dev 上的自动化发布并创建了 GitHub Actions 工作流后,您可以发布软件包的新版本。要发布,请推送与已配置的 标签模式 匹配的_git 标签_。

$ cat pubspec.yaml
yaml
name: my_package_name
version: 1.2.3            # 必须与 git 标签中使用的版本号匹配
environment:
  sdk: ^2.19.0
$ git tag v1.2.3          # 假设我的标签模式是:'v{{version}}'
$ git push origin v1.2.3  # 触发发布我的软件包的操作。

推送后,请查看 https://github.com/<organization>/<repository>/actions 处的 workflow 日志。

如果操作未触发,请检查 .github/workflows/publish.yml 中配置的模式是否与推送的_git 标签_匹配。如果操作失败,日志可能包含导致失败的原因。

发布后,您可以在 pub.dev 上的 audit-log 中查看发布事件。 audit-log 条目应包含指向发布软件包版本的 GitHub Action 运行的链接。

从 GitHub Actions 发布后的审核日志

如果您不喜欢使用 git CLI 创建标签,您可以从 https://github.com/<organization>/<repository>/releases/new 在 GitHub 上创建 发布 。要了解更多信息,请查看 GitHub 的 在仓库中管理发布

使用 GitHub 标签保护规则增强安全性

#

配置来自 GitHub Actions 的自动化发布允许任何可以将标签推送到您的仓库的人触发发布到 pub.dev。您可以使用 GitHub 上的 标签保护规则 来限制谁可以推送标签到您的仓库。

通过限制可以创建与您的 标签模式 匹配的标签的人员,您可以限制谁可以发布软件包。

目前, 标签保护规则 缺乏灵活性。您可能希望使用 GitHub 部署环境来限制谁可以触发发布,如下一节所述。

使用 GitHub 部署环境增强安全性

#

在 pub.dev 上配置来自 GitHub Actions 的自动化发布时,您可以要求使用 GitHub Actions 环境 。要要求使用_GitHub Actions 环境_进行发布,您必须:

  1. 导航到 管理 选项卡( pub.dev/packages/<package>/admin )。
  2. 找到 自动化发布 部分。
  3. 点击 要求 GitHub Actions 环境
  4. 指定一个 环境 名称( pub.dev 通常是一个不错的名称)

配置 pub.dev 以要求 GitHub 部署环境

当 pub.dev 上需要环境时,除非 GitHub Actions 具有 environment: pub.dev ,否则它们将无法发布。因此,您必须:

  1. 创建 环境 在 GitHub 上使用相同的名称(通常为 pub.dev
  2. 更改您的 .github/workflows/publish.yml 工作流文件以指定 environment: pub.dev ,如下所示:
yaml
# .github/workflows/publish.yml
name: 发布到 pub.dev

on:
  push:
    tags:
    - 'v[0-9]+.[0-9]+.[0-9]+' # 用于类似 'v1.2.3' 的标签

jobs:
  publish:
    permissions:
      id-token: write # 使用 OIDC 进行身份验证所需
    uses: dart-lang/setup-dart/.github/workflows/publish.yml@v1
    with:
      # 指定 github actions 部署环境
      environment: pub.dev
      # working-directory: path/to/package/within/repository

环境 反映在用于使用 pub.dev 进行身份验证的临时 GitHub 签名的 OIDC 令牌 中。因此,拥有对…的推送权限的用户

您的仓库无法通过修改工作流文件来规避 环境保护规则

在 GitHub 仓库设置中,您可以使用 环境保护规则 来配置 必需的审阅者 。如果您配置此选项,则 GitHub 会阻止具有该环境的操作运行,直到其中一位 必需的审阅者 批准了运行。

GitHub Action 等待部署审核

从 Google Cloud Build 发布

#

您可以配置从 Google Cloud Build 进行自动化发布。这包括:

  • 注册 Google Cloud 项目(或使用现有项目),
  • 创建用于发布到 pub.dev 的 服务帐号
  • 在 pub.dev 上软件包的管理选项卡中启用自动化发布,指定为发布创建的服务帐号的电子邮件地址。
  • 授予默认 Cloud Build 服务帐号模拟为发布创建的服务帐号的权限。
  • 创建一个 cloudbuild.yaml 文件,该文件获取临时 OIDC id_token 并将其用于发布到 pub.dev。
  • 配置 Cloud Build 触发器,以便在 Google Cloud Build 上的项目中运行 cloudbuild.yaml 中的步骤。

以下部分概述了如何完成这些步骤。

创建用于发布的服务帐号

#

为了发布到 pub.dev,您将创建一个 服务帐号 ,该帐号被授予在 pub.dev 上发布您的软件包的权限。然后,您将授予 Cloud Build 模拟此服务帐号的权限。

  1. 如果您没有现有项目,请 创建云项目

  2. 按如下所示创建 服务帐号

    $ gcloud iam service-accounts create pub-dev \
      --description='发布到 pub.dev 时要模拟的服务帐号' \
      --display-name='pub-dev'

    这将创建一个名为 pub-dev@$PROJECT_ID.iam.gserviceaccount.com 的服务帐号。

  3. 授予服务帐号发布您的软件包的权限。

    要完成此步骤,您必须拥有软件包的 上传者 权限,或者是由拥有该软件包的发布者的 管理员

    a. 导航到 管理 选项卡( pub.dev/packages/<package>/admin )。 a. 点击 使用 Google Cloud 服务帐号启用发布 。 a. 将服务帐号的电子邮件地址键入 服务帐号电子邮件 字段中。您在上一步中创建了此帐号: pub-dev@$PROJECT_ID.iam.gserviceaccount.com

允许服务帐号在 pub.dev 上发布的配置

完成此过程后,任何可以模拟服务帐号的人都可以发布软件包的新版本。请务必检查谁有权限模拟服务帐号,并根据需要更改云项目中的权限。

授予 Cloud Build 发布权限

#

要从 Cloud Build 发布,您必须授予 默认 Cloud Build 服务帐号 模拟上一节中为发布创建的服务帐号的权限。

  1. 在云项目中启用 IAM 服务帐号凭据 API 。如果没有此 API,则尝试模拟服务帐号将会失败。

    # 启用 IAM 服务帐号凭据 API
    $ gcloud services enable iamcredentials.googleapis.com
  2. 查找项目编号。

    # PROJECT_NUMBER 可以按如下方式获取:
    $ gcloud projects describe $PROJECT_ID --format='value(projectNumber)'
  3. 授予模拟发布服务帐号的权限。

    # 授予默认云
    $ gcloud iam service-accounts add-iam-policy-binding \
      pub-dev@$PROJECT_ID.iam.gserviceaccount.com \
      --member=serviceAccount:[email protected] \
      --role=roles/iam.serviceAccountTokenCreator

编写 Cloud Build 配置文件

#

要从 Cloud Build 发布,您必须为 Cloud Build 指定以下步骤:

  • 模拟服务帐号以获取临时 OIDC 令牌。
  • dart pub 提供临时 OIDC 令牌,以便在发布时使用。
  • 调用 dart pub publish 来发布软件包。

Google Cloud Build 的步骤在 cloudbuild.yaml 文件中提供,有关格式的完整文档,请参见 构建配置文件架构

要从 Google Cloud Build 发布到 pub.dev,可以使用以下 cloudbuild.yaml 文件:

yaml
# cloudbuild.yaml
steps:
- id: 创建临时令牌
  name: gcr.io/cloud-builders/gcloud
  volumes:
  - name: temporary-secrets
    path: /secrets
  script: |
    gcloud auth print-identity-token \
      --impersonate-service-account=pub-dev@$PROJECT_ID.iam.gserviceaccount.com \
      --audiences=https://pub.dev \
      --include-email > /secrets/temporary-pub-token.txt
  env:
  - PROJECT_ID=$PROJECT_ID
- id: 发布到 pub.dev
  name: dart
  volumes:
  - name: temporary-secrets
    path: /secrets
  script: |
    cat /secrets/temporary-pub-token.txt | dart pub token add https://pub.dev
    dart pub publish --force

gcloud auth print-identity-token 创建一个模拟指定服务帐号的 OIDC id_token 。此 id_token 由 Google 签名,签名在 1 小时内过期。audiences 参数让 pub.dev 知道它是令牌的预期接收者。 --include-email 选项对于 pub.dev 识别服务帐号是必要的。

创建 id_token 后,它将写入驻留在 中的文件中;此机制用于 在步骤之间传递数据 。不要将令牌存储在 /workspace 中。因为 /workspace 是您希望从中发布的仓库签出的位置。不使用 /workspace 存储令牌可以降低您在发布时意外将其包含在软件包中的风险。

创建 Cloud Build 触发器

#

在仓库中配置服务帐号和 cloudbuild.yaml 文件后,您可以使用 console.cloud.google.com 仪表板创建_Cloud Build 触发器_。要创建构建触发器,您需要连接到 源代码仓库 并指定哪些事件应该触发构建。您可以使用 GitHubCloud Source Repository 或其他 选项 之一。要了解如何配置_Cloud Build 触发器_,请查看 创建和管理构建触发器

要使用上一步中的 cloudbuild.yaml ,请将_Cloud Build 触发器_类型配置为位于仓库 /cloudbuild.yaml 文件中的“Cloud Build 配置”。 不要 为要触发的构建指定 服务帐号 。相反,您应该使用 Cloud Build 的默认服务帐号。

触发器的配置

配置 Cloud Build 触发器时,请考虑谁可以触发构建。 因为触发构建可能会发布软件包的新版本 。请考虑只允许手动构建,或者使用 Cloud Build 批准 来控制构建,如下一节所述。

使用 Cloud Build 批准增强安全性

#

配置 Cloud Build 触发器时,您可以选择 在构建执行前需要批准 。如果 Cloud Build 触发器需要批准,则在触发时不会运行。相反,它将等待批准。这可以用于限制谁可以发布软件包的新版本。

在 Cloud Build 触发器的配置中启用批准

只有具有 Cloud Build 批准者 角色的用户才能给予批准。在给予批准时,批准者可以指定 URL 和注释。

Cloud Build 运行等待批准运行

您还可以配置待处理批准的通知。要了解更多信息,请查看 在批准时控制构建

使用服务帐号从任何地方发布

#

为了允许在 GitHub Actions 之外进行自动化发布,您可以使用类似于_Cloud Build_的方式使用服务帐号进行身份验证。

这通常包括:

Cloud Build 部分概述了如何 创建用于发布的服务帐号 。这应该提供一个服务帐号,例如 pub-dev@$PROJECT_ID.iam.gserviceaccount.com

使用工作负载身份联合发布

#

在支持 OIDC 或 SAML 的云服务上运行时,您可以使用 工作负载身份联合 模拟 GCP 服务帐号。这使您可以利用云提供商的身份服务。

例如,如果在 EC2 上部署,您可以 使用 AWS 配置工作负载身份联合 ,允许来自 EC2 元数据服务的临时 AWS 令牌模拟服务帐号。要了解如何配置这些流程,请查看

工作负载身份联合

使用导出的服务帐号密钥发布

#

在没有身份服务的自定义系统上运行时,您可以导出服务帐号密钥。导出的服务帐号密钥允许您以所述 服务帐号 的身份进行身份验证。要了解更多信息,请查看如何 创建和管理服务帐号密钥

导出服务帐号密钥

#
  1. 为现有服务帐号创建导出的服务帐号密钥。

    $ gcloud iam service-accounts keys create key-file.json \
      --iam-account=pub-dev@$PROJECT_ID.iam.gserviceaccount.com
  2. 保存 key-file.json 文件以备后用。

使用导出的服务帐号密钥发布软件包

#

要使用导出的服务帐号密钥发布软件包:

  1. 设置 gcloud 以使用 key-file.json (在上一步中创建)进行身份验证

    $ gcloud auth activate-service-account --key-file=key-file.json
  2. 为 pub.dev 创建临时令牌并将其传递给 dart pub token add https://pub.dev 。要模拟服务帐号,请包含 --include-email 选项。

    $ gcloud auth print-identity-token \
      --audiences=https://pub.dev \
      | dart pub token add https://pub.dev
  3. 使用临时令牌发布。添加 --force 选项以跳过 yes/no 提示。

    $ dart pub publish --force