目錄

自動發佈套件至 pub.dev

您可以從以下位置自動發佈:

以下章節說明如何設定自動發佈,以及如何根據您的偏好自訂發佈流程。

設定自動發佈時,您不需要建立複製到自動部署環境中的長期密碼。相反地,驗證依賴於由 GitHub Actions(請參閱GitHub Actions 的 OIDC)或 Google Cloud IAM 簽署的臨時 OpenID Connect 權杖。

您可以使用匯出的服務帳戶金鑰,用於不存在身分服務的部署環境。此類匯出的服務帳戶金鑰是長期密碼,在某些環境中可能更容易使用,但也可能在意外洩漏時帶來更大的風險。

使用 GitHub Actions 發佈套件

#

您可以使用 GitHub Actions 設定自動發佈。這涉及

  • 在 pub.dev 上啟用自動發佈,指定

    • GitHub 儲存庫,以及
    • 必須符合才能允許發佈的標籤模式
  • 建立用於發佈至 pub.dev 的 GitHub Actions 工作流程

  • 為要發佈的版本推送 git 標籤

以下章節概述如何完成這些步驟。

設定從 GitHub Actions 自動發佈至 pub.dev

#

若要啟用從 GitHub Actions 自動發佈至 pub.dev,您必須是

  • 套件的上傳者,或
  • 發佈者的管理員(如果套件是由發佈者擁有)。

如果您擁有足夠的權限,可以藉由以下方式啟用自動發佈:

  1. 導覽至 Admin 標籤(pub.dev/packages/<package>/admin)。

  2. 尋找 Automated publishing 區段。

  3. 按一下 Enable publishing from 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.yaml 中的 version 金鑰也必須符合此版本號碼。

如果您的儲存庫包含多個套件,請為每個套件指定不同的標籤模式。請考慮為名為 my_package_name 的套件使用像 my_package_name-v{{version}} 這樣的標籤模式

設定 GitHub Action 工作流程以發佈至 pub.dev

#

在 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 來建立標籤,您可以在 GitHub 上從 https://github.com/<organization>/<repository>/releases/new 建立版本。若要瞭解更多資訊,請查看 GitHub 的在儲存庫中管理版本

使用 GitHub 上的標籤保護規則強化安全性

#

設定從 GitHub Actions 自動發佈,可讓任何能將標籤推送到您的儲存庫的人,觸發發佈到 pub.dev。您可以使用 GitHub 上的標籤保護規則,限制誰可以將標籤推送到您的儲存庫。

藉由限制誰可以建立符合您的標籤模式的標籤,您可以限制誰可以發佈套件。

目前,標籤保護規則缺乏彈性。您可能希望使用 GitHub 部署環境來限制誰可以觸發發佈,如下一節所述。

使用 GitHub 部署環境強化安全性

#

在 pub.dev 上設定從 GitHub Actions 自動發佈時,您可以要求使用GitHub Actions 環境。若要要求使用 GitHub Actions 環境進行發佈,您必須

  1. 導覽至 管理員 索引標籤 (pub.dev/packages/<package>/admin)。
  2. 尋找 Automated publishing 區段。
  3. 點擊 要求 GitHub Actions 環境
  4. 指定 環境 名稱,(pub.dev 通常是不錯的名稱)

Configure pub.dev to require a GitHub deployment environment

當 pub.dev 上需要環境時,除非它們有 environment: pub.dev,否則 GitHub Actions 將無法發佈。因此,您必須

  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:$PROJECT_NUMBER@cloudbuild.gserviceaccount.com \
      --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 小時內過期。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 觸發器類型設定為「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

使用 Workload Identity Federation 發佈

#

在支援 OIDC 或 SAML 的雲端服務上執行時,您可以使用Workload Identity Federation 模擬 GCP 服務帳戶。這可讓您利用雲端供應商的身分服務。

例如,如果部署在 EC2 上,您可以設定與 AWS 的 workload identity federation,允許來自 EC2 中繼資料服務的臨時 AWS 權杖模擬服務帳戶。若要了解如何設定這些流程,請查看workload identity federation

使用匯出的服務帳戶金鑰發佈

#

在沒有身分服務的自訂系統上執行時,您可以匯出服務帳戶金鑰。匯出的服務帳戶金鑰可讓您以所述的服務帳戶進行驗證。若要了解更多資訊,請查看如何建立和管理服務帳戶金鑰

匯出服務帳戶金鑰

#
  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