GitHub Dependabot を使ってパッケージを自動更新する - Azure Static Web Apps 編

GitHub の Dependabot は、リポジトリに含まれている脆弱性を発見して自動的にセキュリティアップデートを実施してくれる機能としてよく知られていますが、もともとの位置付けはアプリケーションのパッケージ依存関係を自動的に更新してくれる機能です。

今回は、Azure のフロントエンドホスティングサービスである Azure Static Web Apps で動かすアプリのリポジトリに Dependabot によるパッケージの自動更新を設定してみました。

Dependabot によるパッケージ自動更新の有効化

Dependabot によるパッケージ更新の仕組みやセキュリティアップデートについては、以下の公式ドキュメントに詳細が書かれています。最近の GitHub は日本語のドキュメントもとても充実していて助かりますね。

セキュリティアップデートについては、通常のリポジトリではデフォルトで有効化されているので、特に設定することはありませんが、パッケージ自動更新については、.github ディレクトリに dependabot.yml という設定ファイルを置いて有効にします。

version: 2
updates:
- package-ecosystem: "npm" # See documentation for possible values
directory: "/" # Location of package manifests
schedule:
interval: "daily"

この例では、npm パッケージの更新有無を毎週チェックして、自動的にプルリクエストをしてくれるように設定しています。オプションの詳細は 「バージョンアップデートの有効化と無効化 - GitHub Docs」 をチェックしてください。

GitHub Actions ワークフローのエラー修正

Static Web Apps が生成するデフォルトの GitHub Actions ワークフローを使っていると、Dependabot が生成されるプルリクエストがエラーで終了してしまいます。

GitHub Actions エラーログ

この理由は、2021 年 3 月から適用された以下の方針によるものです。

要するに Dependabot トリガーによるプルリクエストでは、Secret が読めなくなったということで、Azure Static Web Apps にデプロイするためのクレデンシャルにアクセスができなくなったためにワークフローがエラーで落ちるようになっていました。

Azure Static Web Apps のリポジトリでも Issue が上がっており回避策も提示されていました。

しかし、この方法だとワークフロー全体が実行されなくなってしまいます。せっかくパッケージ自動更新をしてくれているので、ビルドくらいは実行させておきたいところです。

GitHub Actions ワークフローでビルド処理のみを切り出す

そこで、Static Web Apps で GA 直前くらいに導入された ビルドのスキップ機能 を有効にして、Dependabot トリガーのプルリクエストではビルドのみが実行されるようにカスタマイズしたいと思います。

まず、ビルドのみを実行するジョブを作成します。アプリケーションの種類毎に設定方法が多少変わりますが、Vue.js の場合は以下のような構成になると思います。

build:
if: github.event_name == 'push' || (github.event_name == 'pull_request' && github.event.action != 'closed')
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Use Node.js ${{ env.NODE_VERSION }}
uses: actions/setup-node@v1
with:
node-version: ${{ env.NODE_VERSION }}
- run: npm ci
- run: npm run build
- name: move swa config
run: mv staticwebapp.config.json ./dist
- uses: actions/upload-artifact@v2
with:
name: vuedist
path: dist/

ポイントは、次のデプロイジョブに渡すためのアーティファクトとなる dist ディレクトリに Static Web Apps の設定ファイルを移動している箇所です。この設定ファイルがないと、ルーティングや認証を設定している場合は正しく動かなくなるので必ず含めるようにします。

Static Web Apps 用デプロイジョブのカスタマイズ

次に Static Web Apps が準備しているデプロイ用のアクションに skip_app_build: true を追加してデプロイのみが実行されるようにします。このオプションを有効にすると、発行される静的なコンテンツは output_location ではなく app_location を参照するようになります。

合わせて、このジョブが実行される条件に github.actor != 'dependabot[bot]' を追加して、Dependabot トリガーの場合はデプロイが走らないようにします。

deploy_job:
if: github.event_name == 'push' || (github.event_name == 'pull_request' && github.event.action != 'closed' && github.actor != 'dependabot[bot]')
runs-on: ubuntu-latest
needs: build
name: Build and Deploy Job
steps:
- name: Download publish files
uses: actions/download-artifact@v2
with:
name: vuedist
- name: Build And Deploy
id: deploy
uses: Azure/static-web-apps-deploy@v1
with:
azure_static_web_apps_api_token: ${{ secrets.AZURE_STATIC_WEB_APPS_API_TOKEN_ASHY_PEBBLE_0B78DD600 }}
repo_token: ${{ secrets.GITHUB_TOKEN }}
action: "upload"
app_location: ""
skip_app_build: true

この例では、ルートディレクトリに Vue がもともと dist に生成した静的コンテンツと Static Web Apps の設定ファイルが含まれており、このジョブでは静的コンテンツのアップロードのみが行われるようになります。

これで、Dependabot トリガーのプルリクエストで、ビルドのみが実行されるようになりワークフローが正常終了するようになりました。

GitHub Actions 実行結果

このようにビルドとデプロイのジョブを分割しておけば、E2E テストを組み込んだりすることもできるようになりますね。個人的には Static Web Apps 登場直後からビルドを切り出せるようにして欲しかったので、このアップデートにはとても満足しています。

今回の例を含むサンプルリポジトリを GitHub に置いておきました。ちなみにアプリは Vue3 + Vite + TypeScript で作っています。