皆さん、こんにちは! 最先端のDevOpsとCI/CDの世界へようこそ。
今日は、皆さんの開発フローを劇的に進化させる、GitHub ActionsとGitHub Packagesの強力な連携について、その奥深くまで掘り下げていきましょう。
「プライベートな依存関係の管理、どうしてますか?」
この問いに「うーん、まだ手探りかな…」と感じる方は、今日の記事を読み終える頃には、きっと自信を持って「GitHub ActionsとGitHub Packagesにお任せ!」と答えられるようになっているはずです。
オープンソースの世界では、npmやMaven Centralにある公開パッケージを使うのが一般的ですよね。でも、社内でのみ使う独自のライブラリやフレームワーク、あるいは企業秘密に関わるようなコンポーネントを開発する時、それらを公開レジストリに置くわけにはいきません。かといって、各プロジェクトにコピー&ペーストで配布するのは、もはや悪夢です。バージョン管理はカオスになり、セキュリティリスクも増大します。
そこで登場するのが、GitHub PackagesとGitHub Actionsの黄金コンビです。
GitHub Packagesは、皆さんのプライベートなパッケージをセキュアにホスティングし、GitHub Actionsは、CI/CDパイプラインの中から、そのプライベートパッケージをスムーズに、そして安全に利用するための鍵となります。
これをマスターすれば、毎日の作業が劇的に楽になりますよ。さあ、一緒にこの強力なツールセットを使いこなしていきましょう!
—
1. GitHub Packagesとは? – あなたのプライベートなレジストリ
まずは、GitHub Packagesが何者なのか、その役割を理解するところから始めましょう。
GitHub Packagesは、GitHubが提供するパッケージホスティングサービスです。これを使うと、npm、Maven、Gradle、NuGet、Dockerイメージなど、様々な種類のパッケージをGitHubのリポジトリと連携させて保存・管理できます。
なぜGitHub Packagesなのか?
- GitHubエコシステムとの完全な統合: コード、CI/CD、パッケージがすべてGitHub上に集約されます。別々のサービスを行き来する必要がなくなり、開発体験が格段に向上します。
- プライベートパッケージの容易な管理: 公開したくない社内ライブラリや共通コンポーネントを、安全かつ簡単にホスティングできます。アクセス制御はGitHubのリポジトリの権限設定に紐づくため、管理がシンプルです。
- 無料枠からスタート: 個人開発や小規模チームであれば、無料枠でも十分利用可能です。
今回のテーマでは、特にnpmとMavenを例に、その利用方法とGitHub Actionsからの連携方法を深掘りしていきます。
—
2. プライベートnpmパッケージの作成とGitHub Packagesへの公開
まずは、GitHub Packagesに公開するプライベートなnpmパッケージを作成してみましょう。
ここでは「`@your-org/my-private-package`」というスコープ付きパッケージを例に進めます。
ステップ1: パッケージの初期化と作成
適当なディレクトリで新しいnpmパッケージを作成します。
mkdir my-private-package
cd my-private-package
npm init -y # とりあえずデフォルトで初期化
次に、簡単なロジックを持つファイルを作成しましょう。
`index.js`:
// index.js
/
- @param {string} name – 挨拶する相手の名前
- @returns {string} 挨拶メッセージ
/
function sayHello(name) {
return `Hello, ${name}! Welcome to your private package world!`;
}
module.exports = sayHello; // 関数をエクスポート
ステップ2: `package.json`の設定 – GitHub Packagesへの道
GitHub Packagesに公開するためには、`package.json`に特別な設定が必要です。特に重要なのが`publishConfig`です。
`package.json`:
{
“name”: “@your-org/my-private-package”, // ★重要: スコープ付きパッケージ名にする(@ユーザー名/リポジトリ名 または @組織名/リポジトリ名)
“version”: “1.0.0”,
“description”: “A simple private package for demonstration.”,
“main”: “index.js”,
“scripts”: {
“test”: “echo \”Error: no test specified\” && exit 1″
},
“keywords”: [],
“author”: “Your Name”,
“license”: “ISC”,
“publishConfig”: {
“registry”: “https://npm.pkg.github.com/” // ★GitHub PackagesのnpmレジストリURLを指定
}
}
- `name`: スコープ付きパッケージ名 (`@your-org/my-private-package`) は非常に重要です。`@your-org`の部分は、皆さんのGitHubユーザー名または組織名に置き換えてください。これで、このパッケージがどのGitHubアカウント(または組織)に紐づくかが決まります。
- `publishConfig.registry`: ここにGitHub PackagesのnpmレジストリのURL `https://npm.pkg.github.com/` を指定することで、`npm publish`コマンドがGitHub Packagesに向けて実行されるようになります。
ステップ3: GitHubリポジトリの作成とプッシュ
このパッケージをホスティングするGitHubリポジトリを作成しましょう。リポジトリ名はこのパッケージ名と一致させるのが一般的ですが、必須ではありません。今回は `my-private-package` という名前にします。
リポジトリを作成したら、ローカルのコードをプッシュします。
git init
git add .
git commit -m “Initial commit of private package”
git branch -M main
git remote add origin https://github.com/your-org/my-private-package.git # ★your-orgとリポジトリ名を置き換える
git push -u origin main
ステップ4: パッケージの公開(`npm publish`)
いよいよパッケージをGitHub Packagesに公開します。
初回公開時のみ、認証が必要です。 通常、`npm login`コマンドを使用しますが、GitHub Packagesの場合は、`Personal Access Token (PAT)`を使います。
1. PATの生成:
- GitHubの「Settings」→「Developer settings」→「Personal access tokens」→「Tokens (classic)」へ移動。
- 「Generate new token (classic)」をクリック。
- Scope: `write:packages` (パッケージ公開のため) と `repo` (リポジトリへのアクセス) を選択します。
- 有効期限を設定し、トークンを生成します。生成されたトークンは一度しか表示されないので、必ずメモしておいてください!
2. `npm login`での認証:
ターミナルで以下のコマンドを実行します。
npm login –registry=https://npm.pkg.github.com/
ユーザー名、パスワード、メールアドレスを求められます。
- Username: GitHubのユーザー名を入力。
- Password: 生成したPATを貼り付けます! (GitHubのパスワードではありません)
- Email: GitHubに登録しているメールアドレスを入力。
これで認証が完了し、`~/.npmrc`ファイルにGitHub Packagesへの認証情報が書き込まれます。
3. パッケージの公開:
npm publish
成功すれば、「`+ @your-org/my-private-package@1.0.0`」のようなメッセージが表示されます。
GitHubリポジトリの「Packages」タブを確認すると、公開されたパッケージが見えるはずです。
これで、プライベートパッケージの公開は完了です! 次は、これをGitHub Actionsから利用する方法を見ていきましょう。
—
3. GitHub Actionsからのプライベートパッケージ利用 – 認証の壁を突破せよ!
公開したプライベートパッケージを、CI/CDパイプラインであるGitHub Actionsの中から利用するには、認証の壁を突破する必要があります。ここが今回の記事の核心です。
課題: 認証情報の扱い
GitHub Actionsの実行環境はクリーンな状態から始まります。つまり、先ほどローカルで設定した`~/.npmrc`のような認証情報は存在しません。CI/CDの度に手動で認証するわけにもいかないので、自動で認証情報を渡す仕組みが必要です。
解決策: `GITHUB_TOKEN`の活用と最小権限の原則
ここで登場するのが、GitHub Actionsのワークフロー実行時に自動的に払い出される特別なトークン、`GITHUB_TOKEN`です。これは、そのワークフローが属するリポジトリの様々な操作を許可するためのScoped Token(スコープ付きトークン)です。
しかし、`GITHUB_TOKEN`はデフォルトでは、GitHub Packagesからの読み取り権限(`packages:read`)を持っていません。そのため、明示的に権限を設定してあげる必要があります。
3.1. プライベートパッケージを利用するプロジェクトの準備
新しいプロジェクトを作成し、先ほど公開したプライベートパッケージを依存関係として追加してみましょう。
mkdir my-app
cd my-app
npm init -y
`package.json`にプライベートパッケージを追加します。
`package.json` (my-app):
{
“name”: “my-app”,
“version”: “1.0.0”,
“description”: “An application using a private package.”,
“main”: “index.js”,
“scripts”: {
“start”: “node index.js”
},
“keywords”: [],
“author”: “Your Name”,
“license”: “ISC”,
“dependencies”: {
“@your-org/my-private-package”: “1.0.0” // ★プライベートパッケージを依存関係に追加
}
}
`index.js`でプライベートパッケージを利用するコードを書きます。
`index.js` (my-app):
// index.js (my-app)
const sayHello = require(‘@your-org/my-private-package’);
const userName = “GitHub Actions User”;
console.log(sayHello(userName)); // プライベートパッケージの関数を呼び出す
この`my-app`もGitHubリポジトリにプッシュしておきましょう。
git init
git add .
git commit -m “Initial commit of app using private package”
git branch -M main
git remote add origin https://github.com/your-org/my-app.git # ★your-orgとリポジトリ名を置き換える
git push -u origin main
3.2. GitHub Actionsワークフローの設定
`my-app`リポジトリに、GitHub Actionsのワークフローファイルを作成します。
`.github/workflows/ci.yml`:
name: CI for My App
on:
push:
branches:
- main
pull_request:
branches:
- main
jobs:
build:
runs-on: ubuntu-latest
permissions: # ★重要: ここでGITHUB_TOKENの権限を設定します
contents: read # リポジトリのコードを読み取る権限
packages: read # GitHub Packagesからパッケージを読み取る権限
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: ’18’
# ★GitHub Packagesに認証するためのトークンを渡します
# この設定により、~/.npmrc に自動的に認証情報が書き込まれます
token: ${{ secrets.GITHUB_TOKEN }}
- name: Install dependencies
run: npm install
- name: Run application (example)
run: npm start
ここが極限の知見! `permissions`ブロックと`GITHUB_TOKEN`
このワークフローのキモは、`permissions`ブロックと`actions/setup-node`アクションの`token`オプションです。
1. `permissions`ブロック:
- `contents: read`: リポジトリのコードをチェックアウトするために必要です。
- `packages: read`: ここがポイントです! `GITHUB_TOKEN`にGitHub Packagesからパッケージを読み取る権限を明示的に与えています。デフォルトではこの権限がないため、必ず設定してください。
- 「最小権限の原則」: 必要な権限だけを記述することで、万が一トークンが漏洩しても被害を最小限に抑えられます。`GITHUB_TOKEN`のデフォルト権限は比較的広範なので、このように`permissions`ブロックで明示的に必要な権限だけを指定する習慣をつけましょう。
2. `actions/setup-node@v4`アクションの`token`オプション:
- `token: ${{ secrets.GITHUB_TOKEN }}` と指定することで、`setup-node`アクションが自動的に`~/.npmrc`ファイルにGitHub Packagesへの認証情報を設定してくれます。具体的には、`.npmrc`に以下のような設定が追加されます。
//npm.pkg.github.com/:_authToken=${{ secrets.GITHUB_TOKEN }}
@your-org:registry=https://npm.pkg.github.com/
- これにより、その後の`npm install`コマンドが、GitHub Packagesにホスティングされているプライベートパッケージを問題なくダウンロードできるようになります。
このワークフローをコミットしてGitHubにプッシュすると、GitHub Actionsが自動的に実行され、プライベートパッケージが正常にインストールされ、アプリケーションが実行されるのを確認できるはずです!
—
4. Mavenでのプライベートパッケージ利用(応用編)
npmだけでなく、Javaの世界で広く使われているMavenでも、GitHub PackagesとGitHub Actionsの連携は非常に強力です。考え方はnpmとほぼ同じですが、設定ファイルが異なります。
4.1. プライベートMavenパッケージの作成とGitHub Packagesへの公開
プライベートなMavenプロジェクトを作成し、`pom.xml`にGitHub Packagesへの公開設定を追加します。
`pom.xml` (my-private-java-lib):
- `distributionManagement`: ここでGitHub PackagesのリポジトリURLを指定します。`id`は任意の文字列ですが、後に`settings.xml`でこのIDと認証情報を紐づけます。
- PATの生成: npmと同様に、`write:packages`と`repo`スコープを持つPATが必要です。
パッケージの公開は、`mvn deploy`コマンドで行います。この際、認証情報(PAT)を`~/.m2/settings.xml`に設定しておく必要があります。
`~/.m2/settings.xml` (ローカルでの公開用):
その後、`mvn deploy`を実行してパッケージを公開します。
4.2. GitHub ActionsからのMavenプライベートパッケージ利用
Mavenの場合も、基本的にはnpmと同様に`GITHUB_TOKEN`を使って認証を行います。
利用側の`pom.xml`には、GitHub Packagesのリポジトリを追加します。
`pom.xml` (my-java-app):
そして、GitHub Actionsワークフローです。`actions/setup-java`アクションがMavenの`settings.xml`を生成し、`GITHUB_TOKEN`を認証情報として注入してくれます。
`.github/workflows/maven-ci.yml`:
name: Maven CI for My Java App
on:
push:
branches:
- main
pull_request:
branches:
- main
jobs:
build:
runs-on: ubuntu-latest
permissions: # ★重要: ここでGITHUB_TOKENの権限を設定します
contents: read
packages: read # GitHub Packagesからパッケージを読み取る権限
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Java and Maven
uses: actions/setup-java@v4
with:
java-version: ’11’
distribution: ‘temurin’
# ★GitHub Packagesに認証するためのトークンを渡します
# これにより、~/.m2/settings.xml に認証情報が自動的に設定されます
server-id: github # pom.xmlのrepository.idと一致させる
settings-xml-path: ${{ github.workspace }} # settings.xmlをどこに生成するか
token: ${{ secrets.GITHUB_TOKEN }}
- name: Build with Maven
run: mvn clean install -B
- name: Run application (example)
run: mvn exec:java -Dexec.mainClass=”com.your_org.MyApp” # アプリケーションの実行例
- `actions/setup-java@v4`アクション:
- `server-id`: `pom.xml`の`
`で指定したIDと一致させます。github - `token`: ここに`GITHUB_TOKEN`を渡すことで、`setup-java`アクションが自動的に`settings.xml`を生成し、指定した`server-id`に対して`GITHUB_TOKEN`をパスワードとして設定してくれます。
これで、MavenプロジェクトでもGitHub ActionsからプライベートなGitHub Packagesの依存関係をセキュアに解決できるようになります。
—
5. ベストプラクティスと「極限の知見」
GitHub ActionsとGitHub Packagesの連携をマスターしたら、さらに一歩進んだ「極限の知見」とベストプラクティスを身につけましょう。
5.1. `GITHUB_TOKEN`の権限は常に最小限に
これは何度でも強調したいポイントです。
GitHub Actionsのワークフローで、`permissions`ブロックを省略すると、`GITHUB_TOKEN`はリポジトリに対してデフォルトの広範な権限を持つことがあります(特にオーナー権限に近いアカウントで設定されている場合)。これはセキュリティ上、非常に危険です。
- `permissions`ブロックを明示的に記述する: 読み取り専用のCI/CDであれば`contents: read`と`packages: read`のみ、デプロイを含む場合は`deployments: write`など、必要最小限の権限を設定しましょう。
- `id-token: write`: OIDC (OpenID Connect) を利用してAWSやGCPなどのクラウドプロバイダーに認証する場合は、`id-token: write`権限も必要になります。これも必要な場合にのみ設定します。
5.2. シークレットの安全な管理
GitHub Packagesへの公開(`npm publish`や`mvn deploy`)をGitHub Actionsから行う場合、`write:packages`権限を持つPATが必要になります。このPATは`secrets`としてGitHubリポジトリに安全に保存し、ワークフローから`secrets.MY_GITHUB_TOKEN_FOR_PUBLISH`のように参照しましょう。
例: パッケージ公開用のワークフローの一部
- name: Publish package to GitHub Packages
run: npm publish
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_PUBLISH_TOKEN }} # write:packages権限を持つPAT
この際、`NPM_PUBLISH_TOKEN`は、`secrets.GITHUB_TOKEN`とは別物として用意し、より制限されたPATを使用することが望ましいです。`GITHUB_TOKEN`は常にワークフロー実行時に自動的に払い出される一時的なトークンですが、パッケージ公開用のPATは長期的なものになるため、特に厳重な管理が必要です。
5.3. バージョン管理とセマンティックバージョニング
プライベートパッケージも、公開パッケージと同様にセマンティックバージョニング(`MAJOR.MINOR.PATCH`)を厳密に守りましょう。
- `PATCH`: 後方互換性のあるバグ修正。
- `MINOR`: 後方互換性のある新機能追加。
- `MAJOR`: 後方互換性のない変更(破壊的変更)。
これにより、依存するプロジェクト側が安心してパッケージをアップデートできるようになります。
5.4. Dependabotの活用
GitHubには、依存関係の脆弱性や新しいバージョンを自動で検知し、Pull Requestを上げてくれるDependabotという素晴らしい機能があります。GitHub Packagesにホスティングされたプライベートパッケージも、適切に設定すればDependabotの監視対象にできます。
リポジトリのルートに`.github/dependabot.yml`を作成します。
.github/dependabot.yml
version: 2
registries: # GitHub Packagesの認証情報を設定
github-npm:
type: npm-registry
url: https://npm.pkg.github.com
token: ${{secrets.DEPENDABOT_NPM_TOKEN}} # read:packagesを持つPATをsecretsに登録
github-maven:
type: maven-repository
url: https://maven.pkg.github.com/your-org # 組織名またはユーザー名
token: ${{secrets.DEPENDABOT_MAVEN_TOKEN}} # read:packagesを持つPATをsecretsに登録
updates:
- package-ecosystem: “npm”
directory: “/”
schedule:
interval: “daily”
registries:
- github-npm
- package-ecosystem: “maven”
directory: “/”
schedule:
interval: “daily”
registries:
- github-maven
ここで使用するトークンも、`read:packages`権限のみを持つPATをGitHub Secretsとして登録し、Dependabotに渡します。
—
6. まとめ – あなたのCI/CDはもう一段階上のレベルへ
GitHub ActionsとGitHub Packagesの連携は、プライベートな依存関係をセキュアに、そして効率的に管理するための現代的なソリューションです。
- GitHub Packages: あなたのプライベートなパッケージをGitHub上で一元管理する強力なレジストリ。
- GitHub Actions: CI/CDパイプラインから、そのプライベートパッケージへのアクセスを自動化し、認証の壁をスマートに突破する鍵。
特に重要なのは、`GITHUB_TOKEN`の`permissions`ブロックによる最小権限の原則と、`actions/setup-node`や`actions/setup-java`のような公式アクションが提供する認証の自動化です。これらを適切に設定することで、セキュリティを担保しつつ、開発フローの生産性を飛躍的に向上させることができます。
この記事をきっかけに、皆さんの開発がよりスムーズに、よりセキュアになることを心から願っています。
これで、あなたのCI/CDはもう一段階上のレベルへと引き上げられました。さあ、GitHubの強力なエコシステムを最大限に活用し、素晴らしいプロダクトを開発していきましょう!