内容

自动发布包到 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 才能发布您的包。

Configuration of publishing from GitHub Actions on pub.dev

示例:类似于v{{version}}标签模式允许 GitHub Actions(由git tag v1.2.3 && git push v1.2.3触发)发布您的包的版本1.2.3。因此,pubspec.yamlversion键与该版本号匹配也很重要。

如果您的存储库包含多个包,请为每个包分别指定一个标签模式。对于名为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: Publish to pub.dev

on:
  push:
    tags:
    # must align with the tag-pattern configured on pub.dev, often just replace
      # {{version}} with [0-9]+.[0-9]+.[0-9]+
    - 'v[0-9]+.[0-9]+.[0-9]+' # tag-pattern on pub.dev: 'v{{version}}'
    # If you prefer tags like '1.2.3', without the 'v' prefix, then use:
    # - '[0-9]+.[0-9]+.[0-9]+' # tag-pattern on pub.dev: '{{version}}'
    # If your repository contains multiple packages consider a pattern like:
    # - 'my_package_name-v[0-9]+.[0-9]+.[0-9]+'

# Publish using the reusable workflow from dart-lang.
jobs:
  publish:
    permissions:
      id-token: write # Required for authentication using 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: Publish to pub.dev

on:
  push:
    tags:
    - 'v[0-9]+.[0-9]+.[0-9]+' # tag pattern on pub.dev: 'v{{version}'

# Publish using custom workflow
jobs:
  publish:
    permissions:
      id-token: write # Required for authentication using OIDC
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: dart-lang/setup-dart@v1
      - name: Install dependencies
        run: dart pub get
      # Here you can insert custom steps you need
      # - run: dart tool/generate-code.dart
      - name: Publish
        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
package: my_package_name
version: 1.2.3            # must match the version number used in the git tag
environment:
  sdk: ^2.19.0
$ git tag v1.2.3          # assuming my tag pattern is: 'v{{version}}'
$ git push origin v1.2.3  # triggers the action that publishes my package.

推送后,请在https://github.com/<organization>/<repository>/actions处查看工作流日志。

如果 Action 未触发,请检查.github/workflows/publish.yml中配置的模式是否与推送的git 标签匹配。如果 Action 失败,日志可能包含导致其失败的线索。

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

Audit log after publishing from GitHub Actions

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

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

#

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

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

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

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

#

当从 GitHub Actions 自动发布到 pub.dev 时,您可以要求使用一个GitHub Actions 环境。要要求发布时使用GitHub Actions 环境,您必须执行以下操作:

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

Configure pub.dev to require a GitHub deployment environment

当在 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: Publish to pub.dev

on:
  push:
    tags:
    - 'v[0-9]+.[0-9]+.[0-9]+' # for tags like: 'v1.2.3'

jobs:
  publish:
    permissions:
      id-token: write # Required for authentication using OIDC
    uses: dart-lang/setup-dart/.github/workflows/publish.yml@v1
    with:
      # Specify the github actions deployment environment
      environment: pub.dev
      # working-directory: path/to/package/within/repository

环境反映在用于与 pub.dev 进行身份验证的临时GitHub 签名的 OIDC 令牌中。因此,具有推送权限的用户无法通过修改工作流文件来规避环境保护规则

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

GitHub Action waiting for deployment review

从 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='Service account to be impersonated when publishing to 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

Configuration that allows service account to publish on pub.dev

完成此过程后,任何可以模拟该服务账户的人都可以发布该包的新版本。请务必检查谁有权模拟该服务账户,并在需要时更改云项目中的权限。

授予 Cloud Build 发布权限

#

要从 Cloud Build 发布,您必须授予默认 Cloud Build 服务账户模拟为发布创建的服务账户的权限(如上一节所述)。

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

    # Enable IAM Service Account Credentials API
    $ gcloud services enable iamcredentials.googleapis.com
  2. 查找项目编号。

    # The PROJECT_NUMBER can be obtained as follows:
    $ gcloud projects describe $PROJECT_ID --format='value(projectNumber)'
  3. 授予模拟发布服务账户的权限。

    # Grant default cloud
    $ 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 令牌。
  • 将临时 OIDC 令牌提供给 dart pub 以在发布时使用。
  • 调用 dart pub publish 发布包。

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

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

yaml
# cloudbuild.yaml
steps:
- id: Create temporary token
  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: Publish to 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 小时内过期。受众参数让 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 触发器类型配置为“Cloud Build 配置”,该配置位于仓库中 /cloudbuild.yaml 文件中。**不要**为要触发的构建指定服务账户。相反,您应该使用 Cloud Build 的默认服务账户。

Configuration for trigger

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

使用 Cloud Build 批准增强安全性

#

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

Enabling approvals in configuration of the Cloud Build trigger

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

Cloud Build run waiting for approval to run

您还可以配置挂起的批准的通知。要了解更多信息,请查看构建批准

使用服务账户从任何地方发布

#

要允许在 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