こんにちは、サイオステクノロジーの佐藤 陽です。
今回はAzure Static Web Appsと外部のAPIを統合させて、
かつStatic Web App側も外部API側もCI/CDを構築して、いい感じにDevOps環境を構築しよう!という内容です。
こんな感じのCI/CD環境を構築していきます。
目次
はじめに
Azure Static Web AppsはSPA(Single Page Application)などのプロジェクトをデプロイし、簡単にCI/CDが構築できるAzureのリソースです。
以前こちらのブログでまとめたのでご覧ください!
外部APIとの統合
SPAは性質上、APIを多く呼び出すかと思います。
StaticWebApps内でAPI(Azure Functions)を持つことも可能ですが、もちろん外部で実装したAPIとも統合可能です。
実際のプロジェクトにおいては外部APIを利用することの方が多いかもしれないですね。
統合可能なリソースとしては以下4つです。
- API Management
- Azure Functions
- Container App
- Web App
今回はAzure Functionsを使ってAPI統合の方を試してみたいと思います。
Azure Functions
Azure Functionsのリソースを作成します。
今回の検証においてはConsumptionプランで問題ないです。
続いて作成したAzure Functionsにデプロイスロットを追加していきます。
アプリの運用をしていくのであればデプロイスロットの利用は必須ですね。
Consumptionプランを使っているので、スロットが1つ追加で作成できます。
今回、stagingという名前のスロットを作成しました。
production環境と、staging環境でそれぞれ初期画面が表示されることが確認できます。
- https://{function app name}.azurewebsites.net/
- https://{function app name}-staging.azurewebsites.net/
これでAzure Functionsのリソースの準備が整いました。
API実装における注意点
実際にAPIを実装するにあたりひとつ注意点があります。
例えば、以下のようなrootのAPIを実装するとします。
GET https://{function app name}.azurewebsites.net/articles
この時、Static Web Appsから呼び出すためには、以下のように/api/というパスを追加してrootを指定する必要があります。
GET https://{function app name}.azurewebsites.net/api/articles
こうすることにより、StaticWebAppsのSPAプロジェクトから呼び出す際にドメイン名を意識せず呼び出すことが可能となります。
const res = await fetch("/api/articles")
Azure Static Web Apps
Static Web Appsのリソース作成およびyamlファイルの設定に関しては省略します。
上で紹介したブログを参照してください。
注意点としては、外部APIと統合するためにはStandardプランを選択する必要があるので
ホスティングプランに関してはStandardを選択してください。
また今回は、Azure Pieplinesを利用してデプロイの方を行い、
環境としてはmainとdevelopの2つのブランチに基づく環境を用意したいと思います。
yamlとしては以下のような形のものを用意しました。
name: Azure Static Web Apps CI/CD pr: branches: include: - main trigger: branches: include: - main - develop jobs: - job: build_and_deploy_job displayName: Build and Deploy Job condition: or(eq(variables['Build.Reason'], 'Manual'),or(eq(variables['Build.Reason'], 'PullRequest'),eq(variables['Build.Reason'], 'IndividualCI'))) pool: vmImage: ubuntu-latest variables: - group: Azure-Static-Web-Apps-apple-plant-058c24120-variable-group steps: - checkout: self submodules: true - task: AzureStaticWebApp@0 inputs: azure_static_web_apps_api_token: $(AZURE_STATIC_WEB_APPS_API_TOKEN_ORANGE_PLANT_058C23700) production_branch : main ###### Repository/Build Configurations - These values can be configured to match your app requirements. ###### # For more information regarding Static Web App workflow configurations, please visit: https://aka.ms/swaworkflowconfig app_location: "/" # App source code path api_location: "" # Api source code path - optional output_location: "" # Built app content directory - optional ###### End of Repository/Build Configurations ######
次に、Static Web Appsの構成ブレードから、Staging環境を有効にします。
pull request を使用して新しいステージング環境を自動的に作成します。
とありますが、現状ここを有効にしないとブランチ環境も作成されませんでした…。
それぞれのブランチでPieplinesを走らせデプロイが完了すると、
Productionの環境とdevelopの環境が構築されているのが分かります。
これでAzure Static Web Appsの準備が整いました。
統合
それぞれ準備したStatic Web AppsとAzure Functionsを統合していきます。
といっても拍子抜けするほど簡単です。
Static Web Appsのリソースを選択し、APIのブレードを選択します。
すると先ほど構築された環境が2つ並んでおり、右端に「リンク」というボタンがあります。
これをクリックすると統合するAPIが選択可能となるので、先ほど作成したAPIを選択しましょう。
この時スロットの選択も可能となっており
Productionの環境においては「既定」(=本番環境)、developの環境においては「staging」を選択します。
こうすることで
- StaticWebAppsのProduction環境ではproductionのAzureFunctionsを呼び出す
- StaticWebAppsのDevelop環境ではstagingのAzureFunctionsを呼び出す
と、本番環境と開発環境をうまく分離することができました!
今回は、本番環境と開発環境の2本で試してみましたが、
StaticWebAppsの環境や、AzureFunctionsのデプロイスロットを増やすことでより柔軟な運用を行えそうです。
外部APIの認証
また、この時に注目したいのがAzure Functionsの認証設定です。
先ほど作成したAzure Functionsのリソースに直接アクセスしてみます。
すると、「Bad Request」とだけ表示されているかと思います。
Postmanなどで実行すると401エラーが返ってきていることが分かります。
そこで、Azure Functionsの「認証」ブレードを確認してみます。
するとIDプロバイダーとしてStatic Web Appsが追加されていることが確認できます。
Static Web Appsと連携することで、自動で認証の設定が行われ、Static Web Appsからの呼び出しに限定されるようです。
Azure FunctionsのCI/CD
これでStatic Web AppsのCI/CD設定と、外部APIとの統合が完了しました。
ここまでくれば後はAzureFunctionsの自動化だけですね。
実装の詳細に関しては省略しますが、それぞれのトリガーに対してslotNameを指定することで
上記のAPIにそれぞれDeployが可能となります。
trigger: - main - task: AzureFunctionApp@1 inputs: azureSubscription: <Azure service connection> appName: $(appName) package: $(System.ArtifactsDirectory)/**/*.zip
trigger: - develop - task: AzureFunctionApp@1 inputs: azureSubscription: <Azure service connection> appName: $(appName) package: $(System.ArtifactsDirectory)/**/*.zip slotName: 'staging'
まとめ
今回はAzure Static Web Appsの外部API統合の設定を試してみましたが、非常に簡単に外部のAPIと連携することができました!
また標準でCI/CD機能が搭載されているので、運用の構築がぐっと楽になりますね。
統合するAPIの方もCI/CDを構築してあげることで、さらに柔軟性も増します。
是非試してみてください。