GitHub Actionsでパッケージ管理を自動化
GitHub PackagesとGitHub Actionsを組み合わせることで、パッケージの公開とインストールを完全に自動化できます。この記事では、公式ドキュメントをもとに、実務で使える自動化の方法を解説します。
1. CI/CDパイプラインにおけるパッケージング
継続的インテグレーション(CI)や継続的デリバリー(CD)のワークフローにおいて、パッケージングは重要なステップです。コードのビルドとテストが完了した後、実行可能または展開可能なアーティファクトを生成することで、プルリクエストのレビューや動作確認が容易になります。
例えば、Javaプロジェクトではmvn packageを実行してJARファイルを生成し、Node.jsアプリケーションではDockerコンテナを作成します。これにより、レビュアーはワークフローの実行結果からアーティファクトをダウンロードして、ローカル環境で実際に動作確認できます。
2. 認証方式の選択:GITHUB_TOKENを使うべき理由
GitHub Packagesへの認証には、個人アクセストークン(PAT)ではなくGITHUB_TOKENの使用が推奨されています。これには明確な理由があります。
2.1 GITHUB_TOKENの利点
-
セキュリティの向上:長期間有効なPATと異なり、
GITHUB_TOKENはワークフロー実行時に自動生成され、実行終了後は無効化されます - 最小権限の原則:必要な権限のみを付与でき、リポジトリ全体への不要なアクセスを防げます
- 管理の簡素化:トークンのローテーションや管理が不要です
2.2 レジストリの種類による違い
GitHub Packagesのレジストリには、2種類の権限モデルがあります。
細かい権限設定が可能なレジストリ
- パッケージをユーザーまたは組織にスコープ設定可能
- リポジトリとは独立してアクセス制御を設定できる
-
GITHUB_TOKENを使用することで、ワークフローからパッケージの削除や復元も可能(REST API経由、現在パブリックプレビュー中)
リポジトリスコープの権限のみをサポートするレジストリ
- パッケージはリポジトリに紐付けられる
-
GITHUB_TOKENに対してcontentsスコープには読み取り権限、packagesスコープには書き込み権限を設定する必要があります - フォークの場合、
GITHUB_TOKENは親リポジトリへの読み取りアクセスが付与されます
3. ワークフローでのパッケージ公開の実装
実際のワークフロー例を見ていきましょう。以下は、Dockerイメージをビルドして自動公開する設定です。
注意: このワークフローで使用するアクションはGitHubによって認定されたものではありません。サードパーティによって提供されており、別個の利用規約、プライバシーポリシー、サポートドキュメントが適用されます。GitHubは、アクションをコミットSHAにピン留めすることを推奨しています。
name: Dockerイメージの作成と公開
on:
push:
branches: ['release']
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
jobs:
build-and-push-image:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
attestations: write
id-token: write
steps:
- name: リポジトリのチェックアウト
uses: actions/checkout@v5
- name: コンテナレジストリへのログイン
uses: docker/login-action@65b78e6e13532edd9afa3aa52ac7964289d1a9c1
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Dockerのメタデータ抽出
id: meta
uses: docker/metadata-action@9ec57ed1fcdbf14dcef7dfbe97b2010124a938b7
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
- name: Dockerイメージのビルドとプッシュ
id: push
uses: docker/build-push-action@f2a1d5e99d037542a71f64918e516c093c6f3fc4
with:
context: .
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
- name: アーティファクト証明の生成
uses: actions/attest-build-provenance@v3
with:
subject-name: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME}}
subject-digest: ${{ steps.push.outputs.digest }}
push-to-registry: true
3.1 ワークフローの動作フロー
3.2 各ステップの解説
トリガー設定
on:
push:
branches: ['release']
releaseブランチへの変更がプッシュされるたびに、ワークフローが自動実行されます。
環境変数の定義
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
コンテナレジストリのドメインとイメージ名を環境変数として定義します。これにより、複数箇所での参照が容易になります。
権限の設定
permissions:
contents: read
packages: write
attestations: write
id-token: write
GITHUB_TOKENに必要最小限の権限のみを付与します。これはセキュリティのベストプラクティスです。
認証処理
- name: コンテナレジストリへのログイン
uses: docker/login-action@65b78e6e13532edd9afa3aa52ac7964289d1a9c1
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
docker/login-actionを使用して、GITHUB_TOKENでコンテナレジストリに認証します。パッケージは、ここで指定したアカウントにスコープされます。
メタデータの抽出
- name: Dockerのメタデータ抽出
id: meta
uses: docker/metadata-action@9ec57ed1fcdbf14dcef7dfbe97b2010124a938b7
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
タグとラベルを自動生成します。このステップの出力は、後続のステップでsteps.meta.outputsとして参照できます。
ビルドとプッシュ
- name: Dockerイメージのビルドとプッシュ
id: push
uses: docker/build-push-action@f2a1d5e99d037542a71f64918e516c093c6f3fc4
with:
context: .
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
リポジトリのDockerfileをもとにイメージをビルドし、ビルドが成功すればGitHub Packagesにプッシュします。contextパラメータは、ビルドコンテキストとしてカレントディレクトリを指定しています。
アーティファクト証明
- name: アーティファクト証明の生成
uses: actions/attest-build-provenance@v3
with:
subject-name: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME}}
subject-digest: ${{ steps.push.outputs.digest }}
push-to-registry: true
イメージがどこでどのようにビルドされたかを示す、改ざん不可能な証明を生成します。これはサプライチェーンセキュリティの観点から重要です。
4. デフォルトの権限とアクセス設定
細かい権限設定が可能なレジストリでは、ワークフローを通じてパッケージを作成・変更する際に、以下のデフォルト設定が適用されます。
4.1 パッケージ作成時のデフォルト動作
ワークフローがGITHUB_TOKENを使用してパッケージを作成すると:
- パッケージはワークフローが実行されたリポジトリの可視性と権限モデルを継承します
- ワークフローが実行されたリポジトリの管理者が、パッケージ作成後にパッケージの管理者になります
4.2 ワークフロータスク別のデフォルト権限
| ワークフローのタスク | デフォルトの権限とアクセス |
|---|---|
| 既存パッケージのダウンロード | パブリック:すべてのリポジトリのワークフローがダウンロード可能 インターナル:エンタープライズアカウント所有のすべてのリポジトリがダウンロード可能 プライベート:読み取り権限を付与されたリポジトリのみダウンロード可能。公開リポジトリにプライベートパッケージへのアクセスを許可すると、そのフォークもプライベートパッケージにアクセスできる可能性があります |
| 既存パッケージへの新バージョンアップロード | 書き込み権限を付与されたリポジトリのみアップロード可能 |
| パッケージまたはバージョンの削除 | 管理者権限を付与されたリポジトリのみ削除可能 |
これらの設定は、後から細かく調整することも可能です。
5. ワークフローでのパッケージインストール
GitHub Packagesを通じてパッケージをインストールすることで、依存関係の解決とCIテストを効率的に実行できます。
5.1 パッケージインストールの利点
-
最小限の設定:
GITHUB_TOKENを使用するため、追加の認証設定が不要です - 無料のデータ転送:アクションがパッケージをインストールする際のデータ転送は無料です
- シームレスな統合:同じリポジトリ内でビルドとテストを完結できます
5.2 インストールワークフローの例
name: パッケージを使用したテスト
on: [pull_request]
jobs:
test:
runs-on: ubuntu-latest
permissions:
packages: read
contents: read
steps:
- name: リポジトリのチェックアウト
uses: actions/checkout@v5
- name: パッケージレジストリへの認証
run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u ${{ github.actor }} --password-stdin
- name: 依存パッケージのプル
run: docker pull ghcr.io/組織名/パッケージ名:latest
- name: テストの実行
run: docker run --rm ghcr.io/組織名/パッケージ名:latest npm test
6. PATからGITHUB_TOKENへの移行手順
既存のワークフローで個人アクセストークンを使用している場合、以下の手順でGITHUB_TOKENに移行できます。
6.1 移行ステップ
6.2 具体的な変更例
変更前(PATを使用):
- name: ログイン
run: echo "${{ secrets.PERSONAL_ACCESS_TOKEN }}" | docker login ghcr.io -u ユーザー名 --password-stdin
変更後(GITHUB_TOKENを使用):
- name: ログイン
run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u ${{ github.actor }} --password-stdin
6.3 移行時の注意点
- リポジトリの追加:パッケージ設定の「Manage Actions access」でリポジトリを追加する操作は、パッケージをリポジトリに接続する操作とは異なります
-
権限の確認:
GITHUB_TOKENに必要な権限(packages: writeなど)がワークフローファイルで明示的に設定されていることを確認してください - 動作テスト:移行後は必ずテストブランチで動作確認を行いましょう
-
セキュリティの向上:
GITHUB_TOKENの使用により、repoスコープを持つ長期間有効なPATを使用する必要がなくなり、リポジトリへの不要なアクセスを防げます
7. 実践的なワークフロー例
最後に、より実践的なワークフロー例を紹介します。これは複数のトリガーに対応し、タグの命名規則も考慮しています。
name: 本番デプロイ
on:
push:
branches:
- main
- develop
tags:
- v*
pull_request:
env:
IMAGE_NAME: プロダクト名
jobs:
push:
runs-on: ubuntu-latest
permissions:
packages: write
contents: read
steps:
- uses: actions/checkout@v5
- name: イメージのビルド
run: docker build . --file Dockerfile --tag $IMAGE_NAME --label "runnumber=${GITHUB_RUN_ID}"
- name: レジストリへのログイン
run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u ${{ github.actor }} --password-stdin
- name: イメージのプッシュ
run: |
IMAGE_ID=ghcr.io/${{ github.repository_owner }}/$IMAGE_NAME
IMAGE_ID=$(echo $IMAGE_ID | tr '[A-Z]' '[a-z]')
VERSION=$(echo "${{ github.ref }}" | sed -e 's,.*/\(.*\),\1,')
[[ "${{ github.ref }}" == "refs/tags/"* ]] && VERSION=$(echo $VERSION | sed -e 's/^v//')
[ "$VERSION" == "main" ] && VERSION=latest
echo IMAGE_ID=$IMAGE_ID
echo VERSION=$VERSION
docker tag $IMAGE_NAME $IMAGE_ID:$VERSION
docker push $IMAGE_ID:$VERSION
7.1 このワークフローの動作
トリガー条件:
-
mainまたはdevelopブランチへのpush -
vで始まるタグの作成 - プルリクエストの作成または更新
バージョン管理ロジック:
- Git refプレフィックスを除去(
refs/heads/main→main) - タグの場合、先頭の
vを削除(v1.0.0→1.0.0) -
mainブランチの場合、バージョンをlatestに設定 - すべての大文字を小文字に変換(Dockerの命名規則に準拠)
8. まとめ
GitHub ActionsとGitHub Packagesを組み合わせることで、以下が実現できます。
- 完全自動化:コードのpushからパッケージ公開まで、人手を介さず実行
-
セキュアな認証:
GITHUB_TOKENによる安全で管理しやすい認証 - 柔軟な権限管理:パッケージごとに細かくアクセス制御を設定可能
- トレーサビリティ:アーティファクト証明によるサプライチェーンセキュリティの向上
- コスト削減:GitHub Actions経由のデータ転送は無料
これらの機能を活用することで、開発チームはパッケージ管理の運用負荷を大幅に削減し、コードの品質向上に集中できます。まずは小規模なプロジェクトで試してみて、効果を実感してから本格的に導入することをお勧めします。