将软件包自动化发布到 pub.dev
你可以从以下位置自动化发布:
- GitHub Actions,
- Google Cloud Build,或
- 使用 GCP Service Account 从任何其他位置发布。
以下章节解释了如何配置自动化发布,以及如何根据你的偏好定制发布流程。
配置自动化发布时,无需创建并复制到自动化部署环境中的长期存在的密钥。相反,认证依赖于由 GitHub Actions (参阅 GitHub Actions OIDC) 或 Google Cloud IAM 签发的临时 OpenID-Connect 令牌。
对于没有身份服务的部署环境,你可以使用导出的 Service Account 密钥。这类导出的 Service Account 密钥是长期存在的密钥,在某些环境中可能更容易使用,但也存在意外泄露的更大风险。
使用 GitHub Actions 发布软件包
#你可以使用 GitHub Actions 配置自动化发布。这包括:
在 pub.dev 上启用自动化发布,并指定:
- GitHub 仓库,以及
- 一个用于匹配以允许发布的标签模式。
创建用于发布到 pub.dev 的 GitHub Actions 工作流。
推送待发布版本的git 标签。
以下章节概述了如何完成这些步骤。
在 pub.dev 上配置通过 GitHub Actions 实现的自动化发布
#要启用从 GitHub Actions 到 pub.dev
的自动化发布,你必须是:
- 该软件包的上传者,或者,
- 发布者的管理员(如果软件包归发布者所有)。
如果你有足够的权限,可以通过以下步骤启用自动化发布:
导航到管理选项卡 (
pub.dev/packages/<package>/admin
)。找到自动化发布部分。
点击启用从 GitHub Actions 发布,这将提示你指定:
- 仓库 (
<organization>/<repository>
,例如:dart-lang/pana
), - 一个标签模式(包含
{{version}}
的字符串)。
- 仓库 (
仓库 是 GitHub 上的 <organization>/<repository>
。例如,如果你的仓库是 https://github.com/dart-lang/pana
,则必须在仓库字段中指定 dart-lang/pana
。
标签模式 是一个必须包含 {{version}}
的字符串。只有由与此标签模式匹配的标签推送触发的 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
文件
# .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 上发布的与你的仓库中的文件是否匹配。如果将生成或构建的产物提交到仓库不合理,你可以按照以下方式创建自定义工作流:
# .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
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 运行的链接。
如果你不喜欢使用 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 环境,你必须:
- 导航到管理选项卡 (
pub.dev/packages/<package>/admin
)。 - 找到自动化发布部分。
- 点击要求 GitHub Actions 环境。
- 指定一个环境名称(
pub.dev
通常是一个不错的名称)
当 pub.dev 上要求环境时,除非 GitHub Actions 包含 environment: pub.dev
,否则无法发布。因此,你必须:
- 在 GitHub 上创建一个同名环境(通常是
pub.dev
) - 修改你的
.github/workflows/publish.yml
工作流文件,指定environment: pub.dev
,如下所示
# .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 令牌中。因此,具有向仓库 push 权限的用户无法通过修改工作流文件来绕过环境保护规则。
在 GitHub 仓库设置中,你可以使用环境保护规则来配置必需的评审者。如果你配置此选项,GitHub 会阻止使用该环境的 action 运行,直到其中一个必需的评审者批准运行。
通过 Google Cloud Build 发布
#你可以从Google Cloud Build 配置自动化发布。这包括:
- 注册一个 Google Cloud 项目(或使用现有项目),
- 创建一个用于发布到 pub.dev 的Service Account,
- 在 pub.dev 上的软件包管理选项卡中启用自动化发布,指定为发布创建的 Service Account 的电子邮件。
- 授予默认的 Cloud Build Service Account 权限,使其能够模拟(impersonate)为发布创建的 Service Account。
- 创建一个
cloudbuild.yaml
文件,该文件获取临时 OIDCid_token
并用于发布到 pub.dev - 配置一个 Cloud Build 触发器,用于在 Google Cloud Build 上的项目中运行
cloudbuild.yaml
中的步骤。
以下章节概述了如何完成这些步骤。
创建用于发布的 Service Account
#要发布到 pub.dev,你将创建一个被授予在 pub.dev 上发布你的软件包权限的Service Account。然后,你将授予 Cloud Build 模拟此 Service Account 的权限。
如果你没有现有项目,创建一个云项目。
创建Service Account 如下:
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
的 Service Account。授予该 Service Account 发布你的软件包的权限。
要完成此步骤,你必须拥有该软件包的上传者权限,或者拥有该软件包的发布者的管理员权限。
a. 导航到管理选项卡 (
pub.dev/packages/<package>/admin
)。 a. 点击使用 Google Cloud Service account 启用发布。 a. 在Service account 电子邮件字段中输入 Service Account 的电子邮件。你在上一步中创建了此帐户:pub-dev@$PROJECT_ID.iam.gserviceaccount.com
完成此流程后,任何能够模拟此 Service Account 的人都可以发布软件包的新版本。务必审查谁拥有模拟 Service Account 的权限,并根据需要更改云项目中的权限。
授予 Cloud Build 发布权限
#要从 Cloud Build 发布,你必须授予默认的 Cloud Build Service Account 模拟上一节中为发布创建的 Service Account 的权限。
在云项目中启用IAM Service Account Credentials API。如果没有此 API,尝试模拟 Service Account 将会失败。
# Enable IAM Service Account Credentials API gcloud services enable iamcredentials.googleapis.com
查找项目编号。
# The PROJECT_NUMBER can be obtained as follows: gcloud projects describe $PROJECT_ID --format='value(projectNumber)'
授予模拟发布 Service Account 的权限。
# Grant default cloud gcloud iam service-accounts add-iam-policy-binding \ pub-dev@$PROJECT_ID.iam.gserviceaccount.com \ --member=serviceAccount:$PROJECT_NUMBER@cloudbuild.gserviceaccount.com \ --role=roles/iam.serviceAccountTokenCreator
编写 Cloud Build 配置文件
#要从 Cloud Build 发布,你必须为 Cloud Build 指定以下步骤:
- 模拟 Service Account 以获取临时 OIDC 令牌。
- 将临时 OIDC 令牌提供给
dart pub
,以便在发布时使用。 - 调用
dart pub publish
发布软件包。
Google Cloud Build 的步骤在 cloudbuild.yaml
文件中提供,请参阅构建配置文件架构了解此格式的完整文档。
要从 Google Cloud Build 发布到 pub.dev,以下 cloudbuild.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
,用于模拟指定的 Service Account。此 id_token
由 Google 签名,签名在 1 小时内过期。audiences 参数让 pub.dev 知道它是此令牌的预期接收者。--include-email
选项对于 pub.dev 识别 Service Account 是必需的。
创建 id_token
后,它会写入一个驻留在卷中的文件;此机制用于在步骤之间传递数据。不要将令牌存储在 /workspace
中。因为 /workspace
是你想要发布软件包的仓库检出位置。不使用 /workspace
存储令牌可以降低在发布时意外将其包含在软件包中的风险。
创建 Cloud Build 触发器
#配置好 Service Account 并在仓库中有了 cloudbuild.yaml
文件后,你可以使用 console.cloud.google.com 控制台创建Cloud Build 触发器。要创建构建触发器,你需要连接到源代码仓库并指定哪些事件应触发构建。你可以使用GitHub、Cloud Source Repository 或其他选项之一。要了解如何配置Cloud Build 触发器,请查看创建和管理构建触发器。
要使用上一步中的 cloudbuild.yaml
,请将Cloud Build 触发器类型配置为“Cloud Build 配置”,其位于仓库中的 /cloudbuild.yaml
文件。不要为触发构建指定一个Service Account。相反,你将使用 Cloud Build 的默认 Service Account。
配置 Cloud Build 触发器时,考虑谁可以触发构建。因为触发构建可能会发布你的软件包的新版本。考虑只允许手动构建或使用Cloud Build 审批来门控构建,如下一节所述。
使用 Cloud Build 审批增强安全性
#配置 Cloud Build 触发器时,你可以选择在构建执行前需要审批。如果 Cloud Build 触发器需要审批,则在触发时不会运行。相反,它会等待审批。这可以用来限制谁可以发布软件包的新版本。
只有拥有Cloud Build 审批者角色的用户才能进行审批。进行审批时,审批者可以指定 URL 和评论。
你还可以配置待处理审批的通知。要了解更多信息,请查看门控构建上的审批。
使用 Service Account 从任何位置发布
#要在 GitHub Actions 之外实现自动化发布,你可以使用 Service Account 进行认证,方式类似于Cloud Build。
这通常包括:
- 创建用于发布的 Service Account,
- 通过以下两种方式之一模拟发布 Service Account:
- Workload Identity Federation
- 导出的 Service Account 密钥
Cloud Build 一节概述了如何创建用于发布的 Service Account。这应该提供一个 Service Account,例如 pub-dev@$PROJECT_ID.iam.gserviceaccount.com
。
使用 Workload Identity Federation 发布
#当在支持 OIDC 或 SAML 的云服务上运行时,你可以使用Workload Identity Federation 模拟 GCP Service Account。这使你能够利用云提供商的身份服务。
例如,如果在 EC2 上部署,你可以配置与 AWS 的 Workload Identity Federation,允许 EC2 元数据服务提供的临时 AWS 令牌模拟 Service Account。要了解如何配置这些流程,请查看Workload Identity Federation。
使用导出的 Service Account 密钥发布
#当在没有身份服务的自定义系统上运行时,你可以导出 Service Account 密钥。导出的 Service Account 密钥允许你以所述的Service Account 进行认证。要了解更多信息,请查看如何创建和管理 Service Account 密钥。
导出 Service Account 密钥
#为现有 Service Account 创建导出的 Service Account 密钥。
gcloud iam service-accounts keys create key-file.json \ --iam-account=pub-dev@$PROJECT_ID.iam.gserviceaccount.com
保存
key-file.json
文件以备后用。
使用导出的 Service Account 密钥发布软件包
#要使用导出的 Service Account 密钥发布软件包,请执行以下步骤:
设置 gcloud 使用
key-file.json
(在上一步中创建)进行认证gcloud auth activate-service-account --key-file=key-file.json
为 pub.dev 创建临时令牌,并将其传递给
dart pub token add https://pub.dev
。要模拟 Service Account,请包含--include-email
选项。gcloud auth print-identity-token \ --audiences=https://pub.dev \ | dart pub token add https://pub.dev
使用临时令牌发布。添加
--force
选项以跳过yes/no
提示。dart pub publish --force