ほりひログ

所属組織の製品 (Azure とか) に関連する内容が多めだけど、個人の見解であって、所属組織を代表する公式情報ではないです。

Deploy to Azure ボタンで Bicep ファイルからデプロイする (っぽく見せる powered by GitHub Actions )。

Deploy to Azure ボタン

GitHub リポジトリーの README.md などで見かけるこのボタン。

https://aka.ms/deploytoazurebutton

これ自体は単なる画像でクリックしても何も起きないが、Markdown 中に以下の書式を書いておくと、クリック一つで Azure ポータルでデプロイ画面が開くボタンになる。

[![Deploy to Azure](https://aka.ms/deploytoazurebutton)](https://portal.azure.com/#create/Microsoft.Template/uri/<URLEncoded ARM Template URL>)

肝は <URLEncoded ARM template URL> で、Azure プラットフォームがこの <URLEncoded ARM template URL> で指定された URL エンコード済み URL から ARM テンプレート (カスタム デプロイ テンプレート) を取ってきて、それを基にデプロイ画面を作るらしい。

docs.microsoft.com

Deploy to Azure ボタンの弱点

弱点はこの ARM テンプレートが JSON 形式のみ対応なこと。Bicep 形式の ARM テンプレートは、別途 JSON 形式にビルドしておいて、その URL を使う必要がある。
ドキュメントにもハッキリと。

多分、Azure プラットフォーム側に Bicep をビルドする仕組みがないのでは*1

なので、このボタンがあるリポジトリーには、Bicep ファイルがあったとしても、大抵 JSON もある。
編集は Bicep でして、ローカルでこのデプロイ ボタンのために JSON にビルドして、Bicep と JSON をセットでリポジトリーにあげているんだろう。

同じ内容なのに形式が違うものを一緒に管理する、というのは個人的に気持ち悪いものを感じる。

GitHub Actions で克服してみる

この気持ち悪さを解消する。

といっても、Bicep のビルド自体は GitHub Actions の中で bicep build (az bicep build) してしまえばいいので難しくない。

悩み

ただ問題は出来上がった JSON ファイルをどこに置くか。

GitHub Actions から Artifacts として保存してしまうと、zip ファイル形式なるし、ワークフローごとに Artifacts の URL も変わってしまう。
特に URL が変わってしまうと Deploy to Azure ボタンに指定する URL も変えないといけないので、README.md を都度編集するのか、となる。
そんなことしたくない。有効期限もある。

なので、

  1. JSON 形式のまま保存できる場所
  2. 繰り返し実行しても URL が変わらないプロセス (上書きしてくれる)

を満足する必要がある。

解決

ヒントは GitHub Pages の仕組みに。

GitHub Pages は開発用ブランチにある Markdown 等のコンテンツを、 HTML 等の Web ブラウザーで表示可能な形式に変換して別ブランチに配置し、それに *.github.io な URL を割り当てている。
コンテンツを更新しても URL は基本変わらない。

この仕組みをマルっとパクって、開発用ブランチでの管理は Bicep で行い、GitHub Actions で JSON にビルドした後、その JSON を別ブランチに置く。
Markdown 内の Deploy to Azure ボタンからは、別ブランチ上の JSON ファイルの URL を参照する。

おまけに、保存先のブランチ名と保存対象のディレクトリを指定するだけで、ブランチに保存してくれる便利な GitHub Pages 用の GitHub Actions がある。
先人に感謝。

github.com

ワークフロー完成

ということで、出来上がったワークフローがこちら。

on:
  push:
    branches:
      - main  # Set a branch name to trigger deployment
    paths:
      - '**.bicep'
  workflow_dispatch:

env:
  out_dir: public
  main_bicep_file: bicep/main_parent.bicep
  publish_branch: json_template

jobs:
  deploy:
    runs-on: ubuntu-20.04
    steps:
      - uses: actions/checkout@v2

      - name: Build bicep
        run: |
          mkdir ./${{ env.out_dir }}
          az bicep build --file ${{ env.main_bicep_file }} --outdir ${{ env.out_dir }}
      - name: Publish to other branch
        uses: peaceiris/actions-gh-pages@v3
        if: ${{ github.ref == 'refs/heads/main' }}
        with:
          personal_token: ${{ secrets.PERSONAL_TOKEN }}
          publish_dir: ./${{ env.out_dir }}
          publish_branch: ${{ env.publish_branch }}

注意点として peaceiris/actions-gh-pages アクションで別ブランチにアクセスするには、 public_repo のスコープを持った Personal Access Token が必要。理由はわかってない。

あとは Markdown 内の Deploy to Azure ボタンに渡す URL を、JSON を保存したブランチ名とパスに合わせて指定するだけ。

https://portal.azure.com/#create/Microsoft.Template/uri/https%3A%2F%2Fraw.githubusercontent.com%2F<org>%2F<repo>%2F<branch>%2Fpath%2Fto%2Ftemplate.json

これでリポジトリーで管理する ARM テンプレートは、一見 Bicep ファイルだけになって、Bicep からデプロイしているように見える、かもしれない。

めでたしめでたし。

*1:あくまでも想像。ホントのところは知りません。