跳到主要內容

自動將套件發佈到 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.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: 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 部署環境強化安全性

#

在 pub.dev 上設定來自 GitHub Actions 的自動發佈時,您可以要求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 Project(或使用現有專案),
  • 建立用於發佈到 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 Service account 發佈。 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 Service Account Credentials 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 Configuration」,該類型位於儲存庫中的 /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 Approver 角色的使用者才能給予批准。在給予批准時,批准者可以指定 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