Chrome拡張機能をリリース時に自動でChrome Web Storeに公開する

自動化

はじめに

Chrome拡張機能を開発していると、リリースのたびに手動でChrome Web Storeにアップロードするのが面倒になってきます。

今回は release-pleaseGitHub Actions を組み合わせて、GitHubでリリースが作成されたら自動的にChrome Web Storeに公開される仕組みを構築しました。

全体の流れ

  1. fix:feat: プレフィックス付きでコミット
  2. release-pleaseがRelease PRを自動作成
  3. Release PRをマージするとリリースが作成される
  4. リリース作成をトリガーにChrome Web Storeへ自動アップロード

事前準備

Google Cloud ConsoleでOAuth認証情報を取得

Chrome Web Store APIを使うには、OAuth 2.0の認証情報が必要です。

  1. Google Cloud Consoleにアクセス
  2. プロジェクトを作成(または既存のものを選択)
  3. 「APIとサービス」→「ライブラリ」から Chrome Web Store API を有効化
  4. 「APIとサービス」→「認証情報」→「認証情報を作成」→「OAuthクライアントID」
  5. アプリケーションの種類は「デスクトップアプリ」を選択
  6. 作成後、クライアントIDクライアントシークレット をメモ

リフレッシュトークンの取得

リフレッシュトークンは手動で取得する必要があります。

# 変数を設定
CLIENT_ID="your-client-id"
CLIENT_SECRET="your-client-secret"

# 認証URLを開く
open "https://accounts.google.com/o/oauth2/auth?response_type=code&scope=https://www.googleapis.com/auth/chromewebstore&client_id=${CLIENT_ID}&redirect_uri=urn:ietf:wg:oauth:2.0:oob"

ブラウザで認証後、表示される認証コードを使ってリフレッシュトークンを取得:

AUTH_CODE="ブラウザに表示された認証コード"

curl -s -X POST https://oauth2.googleapis.com/token 
  -d "client_id=${CLIENT_ID}" 
  -d "client_secret=${CLIENT_SECRET}" 
  -d "code=${AUTH_CODE}" 
  -d "grant_type=authorization_code" 
  -d "redirect_uri=urn:ietf:wg:oauth:2.0:oob"

レスポンスの refresh_token を保存します。

GitHub Secretsの設定

リポジトリの Settings → Secrets and variables → Actions で以下を設定:

Secret名
CHROME_EXTENSION_ID 拡張機能のID(Chrome Web StoreのURLから取得)
CHROME_CLIENT_ID OAuthクライアントID
CHROME_CLIENT_SECRET OAuthクライアントシークレット
CHROME_REFRESH_TOKEN 取得したリフレッシュトークン

注意: CHROME_CLIENT_IDCHROME_CLIENT_SECRETCHROME_REFRESH_TOKEN は複数のリポジトリで共通で使えます。CHROME_EXTENSION_ID だけが拡張機能ごとに異なります。

リポジトリの権限設定

Settings → Actions → General で:

  • Workflow permissions: 「Read and write permissions」を選択
  • 「Allow GitHub Actions to create and approve pull requests」にチェック

ワークフローの設定

release-please-config.json

manifest.json のバージョンを自動更新するために extra-files を設定:

{
  "packages": {
    ".": {
      "release-type": "node",
      "bump-minor-pre-major": true,
      "bump-patch-for-minor-pre-major": true,
      "extra-files": [
        {
          "type": "json",
          "path": "manifest.json",
          "jsonpath": "$.version"
        }
      ]
    }
  },
  "$schema": "https://raw.githubusercontent.com/googleapis/release-please/main/schemas/config.json"
}

これがないと package.jsonmanifest.json のバージョンがずれて、Chrome Web Storeへのアップロードが失敗します。

.github/workflows/release-please.yml

name: Release Please

on:
  push:
    branches: [main]

permissions:
  contents: write
  pull-requests: write

jobs:
  release-please:
    runs-on: ubuntu-latest
    outputs:
      release_created: ${{ steps.release.outputs.release_created }}
      tag_name: ${{ steps.release.outputs.tag_name }}
    steps:
      - uses: googleapis/release-please-action@v4
        id: release
        with:
          release-type: node

  publish-to-chrome-web-store:
    needs: release-please
    if: ${{ needs.release-please.outputs.release_created }}
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Create zip file
        run: |
          zip -r extension.zip . 
            -x "*.git*" 
            -x "node_modules/*" 
            -x "*.md" 
            -x "package*.json" 
            -x ".github/*" 
            -x "tests/*"

      - name: Upload to Chrome Web Store
        uses: mnao305/chrome-extension-upload@v5.0.0
        with:
          file-path: extension.zip
          extension-id: ${{ secrets.CHROME_EXTENSION_ID }}
          client-id: ${{ secrets.CHROME_CLIENT_ID }}
          client-secret: ${{ secrets.CHROME_CLIENT_SECRET }}
          refresh-token: ${{ secrets.CHROME_REFRESH_TOKEN }}
          publish: true

ポイント:

  • release-please ジョブの outputs でリリース作成を検知
  • publish-to-chrome-web-store ジョブは release_created が true の時のみ実行
  • zipファイル作成時に不要なファイルを除外

手動公開用ワークフロー(オプション)

緊急時の手動公開用に workflow_dispatch も用意しておくと便利です:

# .github/workflows/publish-chrome.yml
name: Publish to Chrome Web Store

on:
  workflow_dispatch:

jobs:
  publish:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Create zip file
        run: |
          zip -r extension.zip . 
            -x "*.git*" 
            -x "node_modules/*" 
            -x "*.md" 
            -x "package*.json" 
            -x ".github/*"

      - name: Upload to Chrome Web Store
        uses: mnao305/chrome-extension-upload@v5.0.0
        with:
          file-path: extension.zip
          extension-id: ${{ secrets.CHROME_EXTENSION_ID }}
          client-id: ${{ secrets.CHROME_CLIENT_ID }}
          client-secret: ${{ secrets.CHROME_CLIENT_SECRET }}
          refresh-token: ${{ secrets.CHROME_REFRESH_TOKEN }}
          publish: true

よくあるエラーと対処法

Invalid version number in manifest

package.jsonmanifest.json のバージョンが一致していない場合に発生します。

対処法: release-please-config.jsonextra-files を追加して manifest.json も自動更新されるようにする。

GitHub Actions is not permitted to create or approve pull requests

リポジトリの権限設定が不足しています。

対処法: Settings → Actions → General で「Allow GitHub Actions to create and approve pull requests」を有効にする。

審査中に新バージョンをアップロードした場合

Chrome Web Storeで審査中のバージョンがある状態で新しいバージョンをアップロードすると、審査中のバージョンは自動的にキャンセルされ、新しいバージョンが審査キューに入ります。

頻繁にリリースすると審査が永遠に終わらない状態になる可能性があるので、ある程度変更をまとめてからリリースするのがおすすめです。

おわりに

この仕組みを導入してから、Chrome拡張機能のリリース作業が格段に楽になりました。Conventional Commitsでコミットして、Release PRをマージするだけで公開まで完了します。

複数のChrome拡張機能を管理している場合は、OAuth認証情報を共通で使えるので、最初の設定さえ済めば2つ目以降は CHROME_EXTENSION_ID を設定するだけです。

関連リンク

タイトルとURLをコピーしました