GitHub Actions自動化実践:Azure SWA×Bicep CI/CDパイプライン構築

【基礎から学ぶ Azure Static Web Apps × Bicep 入門 #3】GitHub Actions で自動化!Bicep で実践CI/CDパイプライン構築

ご挨拶

ども!最近はClaudeのトークン数の消費が多くてちょいちょい制限にかかって、GitHub CopilotとGeminiも巡回ルートに入った龍ちゃんです。AIサービスにぶん投げている時間で、別の作業ができるってのが最高ですよね。チャットの代わりに音声入力したいですが、ずっと起動してるとPCパワーが足りなくなるのが難点です。

基礎から学ぶ Azure Static Web Apps × Bicep 入門

今回は「Azure Static Web Apps を Bicep(Infrastructure as Code)で管理し、GitHub Actions を使った自動デプロイパイプラインを構築する」というテーマで3部構成の「GitHub Action連携編」となります。各回のコンテンツの内容としては以下になります。

シリーズのまとめ記事はこちらになります。

  • Azure Static Web Apps + Bicep環境構築編
  • ローカル開発でのBicep + SWA CLIデプロイ実践編
  • Bicep+GitHub Actions連携デプロイ編 ← 今回はここ

この回での目標は以下となります。

  • GitHub Actions デプロイを前提としたBicepテンプレートの作成
  • GitHub Environment とSecrets の設定: BicepでStatic Web Appsを作成した後に取得できるデプロイトークンやアプリ設定情報をGitHubに登録
  • GitHub CLIを使った自動化: ローカルからGitHub CLIでSecrets登録を行うbashスクリプトの作成
  • GitHub Actions ワークフローの作成: GitHubリポジトリへのプッシュをトリガーとした自動デプロイパイプライン

それでは、ローカルからのBicepとGitHub CLIでの環境設定とGitHub Actionsを用いたデプロイを始めましょう。

前回の振り返り

前回は「基礎から学ぶ Azure Static Web Apps × Bicep 入門 #2」として、Bicepテンプレートを使ったローカル開発環境の構築とSWA CLIデプロイの実践を行いました。

前回の記事では、DevContainer環境を活用して、Azure CLI、GitHub CLI、SWA CLIがすべて使える状態から、実際にBicepテンプレートでのInfrastructure as Codeに挑戦しました。特にAzure CLIの認証情報がマウントされていたおかげで、コンテナ内での作業がとてもスムーズに進められましたね。

Bicepテンプレートの作成では、パラメータファイル(parameters.local.json)を使った設定値の分離を学びました。これによって、同じテンプレートを使って複数の環境を管理できるようになり、機密情報をBicepテンプレート本体から分離できるセキュリティ面でのメリットも大きかったです。

手動でのazコマンド実行から、最終的には一連の作業を自動化するbashスクリプト(deploy.local.sh)まで作成して、開発効率の向上を実感していただけたかと思います。

今回の記事は前回作成したBicepテンプレートとローカル開発環境をもとに進めていきます。もし環境が手元にない方は下の記事を先に読んでください。

環境構築については第一回の記事をご参照ください。

ローカル実行をターゲットとしたBicepに関しては第二回の記事をご参照ください。

ローカルからBicepとGitHub Actionsを使ったデプロイ

Bicep × GitHub Actionsで環境を作成するシナリオ

まずは、シナリオの整理から始めようと思います。Bicepではターゲットスコープを指定することができ、実行時に影響を及ぼす範囲を限定することができます。

  • resourceGroup: 既存のリソースグループに対するアクション
  • subscription: サブスクリプション全体での管理
  • managementGroup: 複数サブスクリプションをまとめて管理
  • tenant: テナント全体への最上位レベル操作

resourceGroup → subscription → managementGroup → tenantという具合に上位の権限が必要になります。一般的な開発者権限の場合は、resouceGroupスコープしか扱うことができないかと思います。

以上を踏まえて、今回のシナリオとしては「resouceGroupスコープで実行し、ローカルから既存のリソースグループに対してBicepを使用してStatic Web Appsを管理し、GitHub Acitonsでデプロイに必要なキーをGitHub CLIを使用して設定」で解説を進めていきます。

ディレクトリ構成

今回、検証に使用するプロジェクトのディレクトリ構成になります。

.
├── .devcontainer/
│   └── devcontainer.json          
├── .github/
│   └── workflows/
│       └── deploy.yml              # GitHub Actions workflow ⭐
├── infra/                          
│   ├── bicep/                     
│   │   ├── main.bicep              # GitHub Actions用Bicep ⭐
│   │   ├── main-local.bicep        
│   │   ├── parameters.json         # GitHub Actions用パラメータ ⭐
│   │   └── parameters-local.json   
│   └── scripts/                   
│       ├── deploy.sh               # 本番環境デプロイスクリプト ⭐
│       └── deploy-local.sh         
├── out/
│   └── index.html                 
├── .env.local                      
├── .env.deploy                     # スクリプト用環境変数
├── .gitignore                      # 機密情報を守る砦
├── swa-cli.config.json             
└── README.md                       # コマンドをメモするのに使ってね!                   

今回作成するファイルとしては、以下の3つになります。

  • deploy.yml:GitHub Actions用ワークフローファイル
  • parameters.json:ローカル開発用パラメータファイル
  • main.bicep:ローカル開発用Bicepテンプレート

パラメータファイルで値を管理する infra > bicep > parameters.json

こちらは、Bicepテンプレートへ値を渡すパラメーターファイルとなります。

{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "projectName": {
      "value": "bicep-swa-prod"
    },
    "environment": {
      "value": "production"
    },
    "location": {
      "value": "East Asia"
    },
    "repositoryUrl": {
      "value": "https://github.com/USER_MAME/REPOSITORY_NAME"
    },
    "branch": {
      "value": "main"
    },
    "appLocation": {
      "value": "/out"
    },
    "apiLocation": {
      "value": ""
    },
    "outputLocation": {
      "value": ""
    },
    "deploymentProvider": {
      "value": "GitHub"
    }
  }
}

設定項目を切り出しておくことで、パラメーターファイルを作成するだけで別の環境を作成することができます。また、リソース管理の観点からも変更差分が追跡しやすくなるため、使用する値はパラメーターファイルとして管理することが必須となります。特に機密情報(パスワードやAPI キーなど)をBicepテンプレート本体から分離できるセキュリティ面でのメリットも大きく、GitHubなどへの誤った機密情報のコミットを防止できます。

GitHub Actions用の設定項目として、リポジトリの情報とSWAへのデプロイ情報が追加されています。こちらは、Bicepテンプレートファイルで使用するため追加しています。

Bicepテンプレート infra > Bicep > main.bicep

Bicepのテンプレートは、以下の3つのパーツで構成されています。

  • パラメータ受け取り部分
  • Static Web Apps定義部分
  • 出力用設定
@description('プロジェクト名(リソース名のプレフィックスとして使用)')
param projectName string

@description('デプロイ環境 (dev, staging, prod)')
param environment string = 'dev'

@description('デプロイ先のリージョン')
param location string = resourceGroup().location

@description('GitHubリポジトリのURL')
param repositoryUrl string

@description('GitHubリポジトリのブランチ名')
param branch string = 'main'

@description('アプリファイルの場所')
param appLocation string = '/out'

@description('APIファイルの場所(使用しない場合は空文字)')
param apiLocation string = ''

@description('出力ファイルの場所')
param outputLocation string = ''

@description('デプロイプロバイダー (GitHub, DevOps)')
@allowed(['GitHub', 'DevOps'])
param deploymentProvider string = 'GitHub'

// GitHub Actions連携用Static Web Apps
resource staticWebApp 'Microsoft.Web/staticSites@2024-11-01' = {
  name: '${projectName}-swa-${environment}'
  location: location
  sku: {
    name: 'Free'
    tier: 'Free'
  }
  properties: {
    provider: deploymentProvider
    repositoryUrl: repositoryUrl
    branch: branch
    buildProperties: {
      appLocation: appLocation
      apiLocation: apiLocation
      outputLocation: outputLocation
      skipGithubActionWorkflowGeneration: true  // 手動管理
    }
  }
  tags: {
    Environment: environment
    Purpose: 'Production'
    CreatedBy: 'GitHub-Actions'
    Repository: repositoryUrl
    Branch: branch
  }
}

// 出力値
output staticWebAppName string = staticWebApp.name
output staticWebAppUrl string = 'https://${staticWebApp.properties.defaultHostname}'
output staticWebAppId string = staticWebApp.id
output resourceGroupName string = resourceGroup().name
output subscriptionId string = subscription().subscriptionId
output repositoryUrl string = repositoryUrl

パラメーター受け取り部分は、先ほど設定したパラメータの受け取りと初期値の設定を行います。

Static Web Apps定義部分は、SWAの構築に必要な情報が記載されています。必須のパラメータとしては、以下になります。

  • name:SWAの名前(Azure内でユニークな名前の必要あり)
  • location:デプロイリージョン(SWAの場合East US 2, West Europe, Central US, East Asia, West US 2
  • sku:価格プラン name-tierは一致させる

tags はAzure Protalやazコマンドでの検索を容易にしてくれます。設定しなくてもよいですが、検証中は助かる設定項目になります。将来的に複数のSWAを運用する際に、設定することで管理が容易になります。tags にpreviewやtestなどをつけておけば、必要なくなったら一気に削除なんてスクリプトを実行することも可能です。

今回のブログで重要になるのはproperties 設定となります。こちらの設定項目が、GitHubリポジトリとStatic Web Appsを接続しています。

プロパティ名説明
providerstringデプロイメントプロバイダー
repositoryUrlstringGitHubリポジトリのURL
branchstringデプロイ対象ブランチ

providerはGitHubと連携するのでGitHub固定でもよいですし、Azure DevOpsと連携するならばDevOpsを設定します。repositoryUrlbranchはGitHub Actionsでデプロイ運用と合わせた形で設定してください。

次にbuildProperties の中の設定を見ていきます。

プロパティ名説明
appLocationstring静的ファイルの格納ディレクトリ
apiLocationstringAzure Functions(API)のソース場所
outputLocationstringビルド後の成果物出力先
skipGithubActionWorkflowGenerationbooleanGitHub Actionsワークフロー自動生成の無効化

appLocationoutputLocationは使用するフレームワークによって変動する値になります。特にappLocationは必須で設定が必要になる値です。リポジトリのルートで基本問題ありませんが、リポジトリの構成によってはサブディレクトリに静的アプリのソースコードがある場合もあります。その場合は、リポジトリの構成に沿って適切に設定をしてください。apiLocationは同一リソースでAzure Functionsを作成していなければ設定しなくてよくなります。

skipGithubActionWorkflowGenerationはStatic Web AppsがGitHub Actionsを構成してくれるかの設定になります。Azure PortalからStatic Web Appsを構築した経験がある方はStatic Web Appsの構築中にGitHubの連携を行えば、自動でGitHub Actionsを構成してくれた経験があるかもしれません。便利な機能ですが、今回は自前でワークフローファイルを構成するためtrueに設定します。

GitHub Actionsの設定 .github > workflows > deploy.yml

次にワークフローファイルの構築を行いましょう。

name: Deploy to Azure Static Web Apps

on:
  workflow_dispatch:  # 手動実行を可能にする
  push:
    branches: [main]
    paths:
      - 'out/**'  # outディレクトリ内のファイルが変更された場合のみ実行

permissions:
  contents: read
  pull-requests: write

jobs:
  build_and_deploy:        
    environment: production
    env:
        APP_LOCATION: ${{ vars.APP_LOCATION || '.' }}
        OUTPUT_LOCATION: ${{ vars.OUTPUT_LOCATION || 'out' }}
        API_LOCATION: ${{ vars.API_LOCATION || '' }}
    runs-on: ubuntu-latest
    name: Build and Deploy
    steps:
      - uses: actions/checkout@v4
        with:
          submodules: true
      
      - name: Build And Deploy
        uses: Azure/static-web-apps-deploy@v1
        with:
          azure_static_web_apps_api_token: ${{ secrets.AZURE_STATIC_WEB_APPS_API_TOKEN }}
          repo_token: ${{ secrets.GITHUB_TOKEN }}
          action: "upload"
          app_location: ${{ env.APP_LOCATION }}
          api_location: ${{ env.API_LOCATION }}
          output_location: ${{ env.OUTPUT_LOCATION }}
          skip_app_build: true

ワークフローの実行タイミングとしては以下の二つを設定してます。

  • workflow_dispatch:GitHub Actionsタブで手動実行
  • push > branches:mainにpushされ、かつ変更がoutディレクトリに加えられた際に実行

これは検証目的で設定した内容です。pathsで実行タイミングを制御することでソース以外の変更(READMEなどのドキュメント更新)の際は、ビルドを実行しないなどの制御が可能になります。これは、本場環境でのワークフローファイルでも使用する可能性があります。

注目すべき点としては、environmentとしてproductionを設定して設定済みのSecretVariableにアクセスしている点です。次のセクションでBicepで作成したリソースと登録情報から、GitHub CLIを使用して設定する項目になります。Variableに関しては、未設定の可能性も考慮して未設定の場合は空文字もしくは定数を指定しています。

Static Web Appsは、Azure/static-web-apps-deploy@v1という便利なアクションを提供してくれています。こちらのアクションは、アクション使用時にディレクトリ構成を判断してビルドから配信までを行ってくれます。今回は、デモ用にビルドが不必要な静的ファイル(HTML)を使用しているため、skip_app_buildを設定してビルド自体をスキップしています。そのほかにも使用しているフレームワークに合わせて設定することで効率的な静的ファイルの配信を行うことができます。設定項目の公式ドキュメントはこちらになります。

!先ほどのBicepのparameterファイルと違うじゃないか!と思った方素晴らしいです。 結論としてこれでも動きます。skip_app_buildを設定してビルドが発生しない環境において、app_location : .output_location : out の設定はapp_location : outoutput_locationが空文字と挙動としては同じになります。設定の方法の豊富なのも考え物ですが、本来であればBicepで設定した値と同等にしておくほうが良いです。今回は、こちらの解説をしたかったのであえて異なる値に設定しています。

コマンドを使ってリソース作成~デプロイ

それでは、実際にBicepテンプレートを使用してリソースの作成、GitHub CLIを使用してenvironmentの設定、最終的にGitHub Acitonsを起動してデプロイを行っていきます。

再度シナリオの確認です。今回のシナリオは「resouceGroupスコープで実行し、ローカルから既存のリソースグループに対してBicepを使用してStatic Web Appsを管理し、GitHub Acitonsでデプロイに必要なキーをGitHub CLIを使用して設定」です。作成するリソースやGitHub CLIで設定する値としては以下の情報を設定します。

設定項目
リソースグループbicep-test-group
SWA名bicep-actions-deploy-swa
ロケーションeastasia
environment名production
ターゲットブランチ名main
APP_LOCATION.
OUTPUT_LOCATIOMout

あとは、ここに記載することができませんが以下の値が必要になります。

  • GitHub OWNER:ユーザー名もしくはOrganization名
  • GitHub REPO:リポジトリ名

こちらの値はそれぞれ自分の環境に合わせて設定してください。

Bashで表現すると以下のような変数になります。汎用性を高めるために、Bashの変数名でコマンドの解説を進めていきます。SWA名に関してはパラメーターファイルで設定済みですが、削除にも使用することも考えて、定義しておきます。

$RESOURCE_GROUP_NAME="bicep-test-group"

$LOACTION="eastasia"

$SWA_NAME="bicep-actions-deploy-swa"

$GITHUB_ENVIRONMENT="production"

$BRANCH="main"

$APP_LOCATION="/out"

$GITHUB_OWNER="xxxxxxx"

$GITHUB_REPO="xxxxx"

GitHubのリポジトリはすでに構築済みであると仮定します。GitHub CLIでenvironmentを設定するためには事前にenvironmentを作成しておく必要があります。productionという名前でenvironmentを作成してください。設定は公式のドキュメントを参考に設定してください。

それではコマンドに入っていきます。

リソースグループの作成

$RESOURCE_GROUP_NAME="bicep-test-group"
$LOACTION="eastasia"

# リソースグループの確認
az group show --name $RESOURCE_GROUP_NAME

# リソースの作成
az group create --name $RESOURCE_GROUP_NAME --location $LOCATION

az group createコマンドでは、--nameオプションで名前を--locationオプションでリージョンを指定する必要があります。

Bicepテンプレートの検証とデプロイ

Bicepテンプレートをデプロイする前に、構文エラーや設定ミスがないかを検証することが重要です。az deployment group validateコマンドを使用することで、実際にリソースを作成する前にテンプレートの妥当性をチェックできます。

# 検証
az deployment group validate \
	  --resource-group $RESOURCE_GROUP_NAME \
	  --template-file infra/bicep/main.local.bicep \
	  --parameters @infra/bicep/parameters.local.json
  
# デプロイ
az deployment group create \
	  --resource-group "$RESOURCE_GROUP" \
	  --name "$DEPLOYMENT_NAME" \
	  --template-file "$BICEP_TEMPLATE" \
	  --parameters "@$BICEP_PARAMS" 

検証が完了したら、az deployment group createコマンドで実際にBicepテンプレートをデプロイします。--nameオプションでデプロイ名を指定でき、後からAzure Portalでデプロイ履歴を確認する際に便利です。

Azure CLIでは、パラメーターファイルを指定する際に@ファイルパスという記法を使用します。この記法により、ファイルの内容がパラメータとして読み込まれます。

# ✅ 正しい - ファイルの内容を読み込む
--parameters "@parameters.local.json"

# ❌ 間違い - ファイル名がそのまま渡される
--parameters "parameters.local.json"

デプロイトークンの取得

SWA CLIでデプロイするためには、Static Web Appsのデプロイトークンが必要です。このトークンは、作成されたStatic Web Appsリソースからaz staticwebapp secrets listコマンドで取得できます。

az staticwebapp secrets list --name $SWA_NAME --resource-group $RESOURCE_GROUP_NAME --query "properties.apiKey" -o tsv

このコマンドでは、--query "properties.apiKey"オプションでJSON出力からAPIキー(デプロイトークン)のみを抽出し、-o tsvオプションでタブ区切り形式として出力することで、余計な引用符を除去しています。取得したトークンは環境変数に保存して、次のGitHub CLIを介した設定で使用します。

GitHub CLIを使ってenvironmentを設定する

GitHub CLIを使用してSecretとVariableを設定する、公式ドキュメントはこちらにまとまっています。

gh auth login

# コマンド紹介
# gh secret set <ここに登録名> --env <環境名> --repo $GITHUB_OWNER/$GITHUB_REPO --body <設定したい値>
# gh variable set <ここに登録名> --env <環境名> --repo $GITHUB_OWNER/$GITHUB_REPO --body <設定したい値>

gh variable set APP_LOCATION --env production --repo $GITHUB_OWNER/$GITHUB_REPO --body $APP_LOCATION
 
gh variable set OUTPUT_LOCATION --env production --repo $GITHUB_OWNER/$GITHUB_REPO --body $OUTPUT_LOCATION

gh secret set AZURE_STATIC_WEB_APPS_API_TOKEN --env production --repo $GITHUB_OWNER/$GITHUB_REPO --body $DEPLOY_TOKEN

ここで注意したいのは、SecretもVariableも空文字での登録を行うことはできません。

GitHub Actions実行

ここまで来たら必要な設定はすべて完了していると思います。手動でも検証のためにout > index.html に変更を加えてmainにpushすれば、GitHub Actionsがトリガーされてデプロイされるかと思います。

以下の画面が表示されれば成功です。

コラム:開発効率改善~処理をbashに集約~

さてさて!コマンドの検証は完了しました。ですが、今回のコマンドはさすがに一個ずつ入力するのはさすがに大変です。というわけで、第二回で作成したbashファイルを拡張してスクリプトとしてまとめておきたいと思います。

ベース作成も改修もAIにやってもらったので、本当にbashファイルを書くのはAIが強いですね。要望伝えて.envファイルを作ったらポンと作ってくれました。

作成するファイル

作成するファイルとしては、.envdeploy.shになります。

環境変数:.env

こちらのファイルでは、azコマンドでは埋め込んでいた値を変数として切り出しています。これによって.envを変更するだけで、異なるリソースを作成することができます。

# Azure Static Web Apps デプロイ設定ファイル

# Azure設定
RESOURCE_GROUP_NAME="************"
LOCATION="eastasia"

# GitHub設定
GITHUB_OWNER="************"        # GitHubユーザー名またはOrganization名
GITHUB_REPO="************"        # リポジトリ名
GITHUB_ENVIRONMENT="************"     # GitHub Environment名

# プロジェクト設定(parameters.jsonと合わせる)
PROJECT_NAME="************"
ENVIRONMENT="************"
REPOSITORY_URL="************"
BRANCH="main"

# デプロイ設定
APP_LOCATION="/out"
API_LOCATION=""
OUTPUT_LOCATION=""

parameter.jsonと値を合わせる運用にすることで、設定項目が異なることも防ぐことができます。二重管理になってしまいますが、parameter.jsonはBicep用、.envはbashファイル用なので責務としては分散されていると思っています。

自動化スクリプト:infra > scripts > deploy.sh

いきなりbashファイルを読むのは大変なので、抽象化してシーケンス図に起こします。bashファイルのベースとしては、先ほどのセクションで解説したコマンドになります。

#!/bin/bash

# Azure Static Web Apps GitHub Actions用デプロイスクリプト(設定ファイル対応版)
set -e

# スクリプトのディレクトリを取得
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"

# 設定ファイルの読み込み
CONFIG_FILE="$(git rev-parse --show-toplevel)/.env.deploy"

if [ -f "$CONFIG_FILE" ]; then
    echo "📁 設定ファイル読み込み: $CONFIG_FILE"
    source "$CONFIG_FILE"
else
    echo "⚠️  設定ファイルが見つかりません: $CONFIG_FILE"
    echo "   .env.deploy.example をコピーして設定してください"
    exit 1
fi

# 必須設定の確認
if [ -z "$GITHUB_OWNER" ] || [ -z "$GITHUB_REPO" ]; then
    echo "❌ GITHUB_OWNER と GITHUB_REPO を設定してください"
    exit 1
fi

# デプロイ名生成
DEPLOYMENT_NAME="swa-deployment-$(date +%Y%m%d-%H%M%S)"

echo "🚀 Azure Static Web Apps 本番環境デプロイ(GitHub Secret自動登録付き)"
echo "=================================================================="

# 設定値表示
echo "📋 設定確認:"
echo "  Azure Resource Group: $RESOURCE_GROUP_NAME"
echo "  Location: $LOCATION"
echo "  GitHub Owner: $GITHUB_OWNER"
echo "  GitHub Repo: $GITHUB_REPO"
echo "  GitHub Environment: $GITHUB_ENVIRONMENT"
echo ""

# 0. 前提条件確認
echo "📋 前提条件確認..."

# jq インストール確認
if ! command -v jq &> /dev/null; then
    echo "❌ jq がインストールされていません"
    echo "   Ubuntu/Debian: sudo apt-get install jq"
    echo "   macOS: brew install jq"
    exit 1
fi

# GitHub CLI インストール確認
if ! command -v gh &> /dev/null; then
    echo "❌ GitHub CLI (gh) がインストールされていません"
    echo "   インストール方法: https://cli.github.com/"
    exit 1
fi

# GitHub CLI 認証確認
echo "🔐 GitHub CLI認証状態確認..."
if ! gh auth status &> /dev/null; then
    echo "❌ GitHub CLIにログインしてください"
    echo "   実行コマンド: gh auth login"
    exit 1
else
    echo "✅ GitHub CLI認証済み"
    CURRENT_USER=$(gh api user --jq '.login')
    echo "   認証ユーザー: $CURRENT_USER"
fi

# リポジトリアクセス確認
echo "🔍 GitHubリポジトリアクセス確認..."
if ! gh repo view $GITHUB_OWNER/$GITHUB_REPO &> /dev/null; then
    echo "❌ リポジトリにアクセスできません: $GITHUB_OWNER/$GITHUB_REPO"
    echo "   リポジトリ名とアクセス権限を確認してください"
    exit 1
else
    echo "✅ リポジトリアクセス確認済み"
fi

# 1. Azure CLI ログイン確認
echo ""
echo "📋 Azure CLI認証状態確認..."
if ! az account show &> /dev/null; then
    echo "❌ Azure CLIにログインしてください"
    az login
else
    echo "✅ Azure CLI認証済み"
    az account show --query "{Name:name, SubscriptionId:id}" -o table
fi

# 2. リソースグループ作成(存在しない場合)
echo ""
echo "📦 本番用リソースグループ確認・作成..."
if ! az group show --name $RESOURCE_GROUP_NAME &> /dev/null; then
    echo "🔧 リソースグループ作成中: $RESOURCE_GROUP_NAME"
    az group create --name $RESOURCE_GROUP_NAME --location $LOCATION
    echo "✅ リソースグループ作成完了"
else
    echo "✅ リソースグループ既存: $RESOURCE_GROUP_NAME"
fi

# 3. Bicepファイル存在確認
BICEP_MAIN="infra/bicep/main.bicep"
BICEP_PARAMS="infra/bicep/parameters.json"

if [ ! -f "$BICEP_MAIN" ]; then
    echo "❌ Bicepテンプレートが見つかりません: $BICEP_MAIN"
    exit 1
fi

if [ ! -f "$BICEP_PARAMS" ]; then
    echo "❌ Bicepパラメータファイルが見つかりません: $BICEP_PARAMS"
    exit 1
fi

# 4. Bicepテンプレートの検証
echo ""
echo "🔍 GitHub Actions用Bicepテンプレート検証..."
az deployment group validate \
    --resource-group $RESOURCE_GROUP_NAME \
    --template-file $BICEP_MAIN \
    --parameters @$BICEP_PARAMS

echo "✅ Bicepテンプレート検証成功"

# 5. Bicepデプロイ実行
echo ""
echo "🚀 GitHub Actions連携用Static Web Appsデプロイ開始..."
echo "   デプロイ名: $DEPLOYMENT_NAME"

DEPLOYMENT_OUTPUT=$(az deployment group create \
    --resource-group $RESOURCE_GROUP_NAME \
    --name $DEPLOYMENT_NAME \
    --template-file $BICEP_MAIN \
    --parameters @$BICEP_PARAMS \
    --query "properties.outputs" -o json)

echo "✅ Bicepデプロイ完了"

# 6. デプロイ結果の取得
echo ""
echo "📊 デプロイ結果取得中..."
SWA_NAME=$(echo $DEPLOYMENT_OUTPUT | jq -r '.staticWebAppName.value')
SWA_URL=$(echo $DEPLOYMENT_OUTPUT | jq -r '.staticWebAppUrl.value')
RESOURCE_GROUP=$(echo $DEPLOYMENT_OUTPUT | jq -r '.resourceGroupName.value')
SUBSCRIPTION_ID=$(echo $DEPLOYMENT_OUTPUT | jq -r '.subscriptionId.value')

# デプロイトークン取得(リトライ機能付き)
echo "🔑 デプロイトークン取得中..."
RETRY_COUNT=0
MAX_RETRIES=5
while [ $RETRY_COUNT -lt $MAX_RETRIES ]; do
    DEPLOYMENT_TOKEN=$(az staticwebapp secrets list --name $SWA_NAME --resource-group $RESOURCE_GROUP_NAME --query "properties.apiKey" -o tsv 2>/dev/null)
    if [ -n "$DEPLOYMENT_TOKEN" ] && [ "$DEPLOYMENT_TOKEN" != "null" ]; then
        echo "✅ デプロイトークン取得成功"
        break
    fi
    RETRY_COUNT=$((RETRY_COUNT + 1))
    echo "   リトライ中... ($RETRY_COUNT/$MAX_RETRIES)"
    sleep 10
done

if [ -z "$DEPLOYMENT_TOKEN" ] || [ "$DEPLOYMENT_TOKEN" = "null" ]; then
    echo "❌ デプロイトークンの取得に失敗しました"
    exit 1
fi


# 7. GitHub Secretsの登録
echo ""
echo "🔐 GitHub Secrets & Variables 登録中... "

# 条件分岐で空文字をスキップ
if [ -n "$APP_LOCATION" ]; then
  echo $APP_LOCATION | gh variable set APP_LOCATION --env production --repo $GITHUB_OWNER/$GITHUB_REPO
  echo "✅ APP_LOCATION set to: $APP_LOCATION"
else
  echo "⏭️  APP_LOCATION is empty, skipping..."
fi

if [ -n "$OUTPUT_LOCATION" ]; then
  echo $OUTPUT_LOCATION | gh variable set OUTPUT_LOCATION --env production --repo $GITHUB_OWNER/$GITHUB_REPO
  echo "✅ OUTPUT_LOCATION set to: $OUTPUT_LOCATION"
else
  echo "⏭️  OUTPUT_LOCATION is empty, skipping..."
fi

if [ -n "$API_LOCATION" ]; then
  echo $API_LOCATION | gh variable set API_LOCATION --env production --repo $GITHUB_OWNER/$GITHUB_REPO
  echo "✅ API_LOCATION set to: $API_LOCATION"
else
  echo "⏭️  API_LOCATION is empty, skipping..."
fi


echo $DEPLOYMENT_TOKEN | gh secret set AZURE_STATIC_WEB_APPS_API_TOKEN --env production --repo $GITHUB_OWNER/$GITHUB_REPO


# 10. 登録されたSecretsの確認
echo ""
echo "🔍 登録されたSecretsの確認..."
echo "Environment Secrets ($GITHUB_ENVIRONMENT):"
gh secret list --env $GITHUB_ENVIRONMENT --repo $GITHUB_OWNER/$GITHUB_REPO 2>/dev/null | grep -E "(AZURE_STATIC_WEB_APPS_API_TOKEN)" || echo "  ※ Secret一覧の表示には管理者権限が必要です"
gh variable list --env $GITHUB_ENVIRONMENT --repo $GITHUB_OWNER/$GITHUB_REPO 2>/dev/null | grep -E "(APP_LOCATION|OUTPUT_LOCATION|API_LOCATION)" || echo "  ※ Variable一覧の表示には管理者権限が必要です"


# 11. デプロイ結果の表示
echo ""
echo "📊 本番環境デプロイ結果:"
echo "======================"
echo "🌐 Static Web App名: $SWA_NAME"
echo "🔗 URL: $SWA_URL"
echo "📁 リソースグループ: $RESOURCE_GROUP"
echo "🆔 サブスクリプション: $SUBSCRIPTION_ID"
echo "🔐 GitHub Environment: $GITHUB_ENVIRONMENT"
echo "🏷️  デプロイ名: $DEPLOYMENT_NAME"

# 12. 次のステップ案内
echo ""
echo "🎉 本番環境デプロイ完了!"
echo ""
echo "📝 次のステップ:"
echo "   1. ブラウザで $SWA_URL にアクセス"
echo "   2. GitHub Actions ワークフローファイルを作成"
echo "   3. 自動デプロイをテスト"
echo "   4. Environment保護ルールを設定(推奨)"
echo ""
echo "🔧 便利なリンク:"
echo "   - Static Web App: https://portal.azure.com/#resource/subscriptions/$SUBSCRIPTION_ID/resourceGroups/$RESOURCE_GROUP/providers/Microsoft.Web/staticSites/$SWA_NAME"
echo "   - GitHub Environment設定: https://github.com/$GITHUB_OWNER/$GITHUB_REPO/settings/environments"
echo "   - GitHub Actions: https://github.com/$GITHUB_OWNER/$GITHUB_REPO/actions"
echo ""
echo "💻 手動デプロイ用コマンド(トラブルシューティング時):"
echo "   cd out && npx @azure/static-web-apps-cli deploy --deployment-token [TOKEN]"

こちらを実行することで、リソースグループの作成からenvironmentの設定まで自動的に行うことができます。

機密情報を守る砦:.gitignore

.envファイルは流出しても影響は少ないかもですが、GitHubに上げることも考慮して機密情報をPushしないように.gitignoreの設定を追加します。


deploy.info.*.json

.env
.env.*

!.env.*.sample

まとめ

今回の三部作の最終回では、BicepとGitHub Actionsを組み合わせた実践的なCI/CDパイプラインの構築について詳しく解説してきました。

今回実現できたこと:

  • GitHub Actions用のBicepテンプレートとパラメータファイルの作成
  • GitHub CLIを使った自動化スクリプトによるSecretsとVariablesの設定
  • リソース作成からデプロイまでの完全自動化
  • 本番環境を想定したワークフローファイルの構築

特に印象的だったのは、GitHub CLIを活用した環境設定の自動化ですね。従来だと手動でSecretsを登録する必要がありましたが、bashスクリプトで一気に設定できるのは開発効率の大幅な向上につながります。

技術的なポイント:

  • skipGithubActionWorkflowGeneration: trueによる手動ワークフロー管理
  • environmentを使った本番環境用のSecrets/Variables管理
  • デプロイトークンの自動取得とリトライ機能
  • パラメータファイルによる設定の分離とセキュリティ向上

bashスクリプトの実装では、エラーハンドリングから前提条件の確認、結果の可視化まで、本番運用を意識した丁寧な作り込みが印象的でした。特にシーケンス図で処理フローを可視化していたのは、複雑な自動化処理を理解しやすくする工夫として素晴らしいですね。

三部作を通じて学べたこと:

  1. DevContainer環境での効率的な開発環境構築
  2. BicepによるInfrastructure as Codeの実践
  3. GitHub Actionsとの連携による完全自動化

この知識を活かして、皆さんもBicep + GitHub ActionsでのStatic Web Apps運用にチャレンジしてみてください!Infrastructure as CodeとCI/CDの組み合わせで、より安全で効率的な開発ライフサイクルを実現できるはずです。

ご覧いただきありがとうございます! この投稿はお役に立ちましたか?

役に立った 役に立たなかった

0人がこの投稿は役に立ったと言っています。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です