メインコンテンツにスキップ

pub.dev へのパッケージの自動公開

自動公開を以下のソースから行えます。

以降のセクションでは、自動公開がどのように設定されるか、および好みに合わせて公開フローをカスタマイズする方法について説明します。

自動公開を設定する際、自動デプロイメント環境にコピーされる長期のシークレットを作成する必要はありません。代わりに、認証は GitHub Actions (「OIDC for GitHub Actions」を参照) または Google Cloud IAM によって署名された一時的な OpenID Connect トークンに依存します。

ID サービスが存在しないデプロイメント環境では、エクスポートされたサービスアカウントキーを使用できます。このようなエクスポートされたサービスアカウントキーは長期のシークレットであり、一部の環境では使用が容易かもしれませんが、誤って漏洩した場合のリスクも大きくなります。

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 Actions ワークフローの設定

#

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 でワークフローログを確認してください。

アクションがトリガーされなかった場合は、.github/workflows/publish.yml で設定されたパターンがプッシュされたgit タグと一致しているか確認してください。アクションが失敗した場合は、ログに失敗した理由の手がかりが含まれている可能性があります。

公開されると、pub.devaudit-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. 自動公開セクションを見つけます。
  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 サービスアカウントに、公開用に作成したサービスアカウントを代行する権限を付与する。
  • 一時的な OIDC id_token を取得し、pub.dev への公開に使用する cloudbuild.yaml ファイルを作成する。
  • Google Cloud Build 上のプロジェクトで cloudbuild.yaml の手順を実行するための Cloud Build トリガーを設定する。

以下のセクションでは、これらの手順を完了する方法を概説します。

公開用のサービスアカウントの作成

#

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 トリガーのタイプをリポジトリ内の /cloudbuild.yaml ファイルにある「Cloud Build Configuration」に設定します。トリガーされるビルドにサービスアカウントを指定しないでください。代わりに、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 サービスアカウントを代行できます。これにより、クラウドプロバイダーの ID サービスを活用できます。

たとえば、EC2 でデプロイする場合、AWS との Workload Identity Federation を設定することができ、EC2 メタデータサービスからの一時的な AWS トークンを使用してサービスアカウントを代行できます。これらのフローを設定する方法については、「Workload Identity Federation」を参照してください。

エクスポートされたサービスアカウントキーを使用した公開

#

ID サービスのないカスタムシステムで実行する場合、サービスアカウントキーをエクスポートできます。エクスポートされたサービスアカウントキーを使用すると、そのサービスアカウントとして認証できます。詳細については、「サービスアカウントキーの作成と管理」を参照してください。

サービスアカウントキーのエクスポート

#
  1. 既存のサービスアカウントのエクスポートされたサービスアカウントキーを作成します。

    gcloud iam service-accounts keys create key-file.json \
      --iam-account=pub-dev@$PROJECT_ID.iam.gserviceaccount.com
  2. key-file.json ファイルを後で使用するために保存します。

エクスポートされたサービスアカウントキーを使用したパッケージの公開

#

エクスポートされたサービスアカウントキーを使用してパッケージを公開するには、以下の手順を実行します。

  1. key-file.json (前の手順で作成) を使用して gcloud を認証するように設定します。

    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