PRをマージしたらAzureContainerRegistryにpushする
前回からの続きでCI/CDを整備していきます。
現在、手動でDockerをビルド→ACRにプッシュ→WebHookでAppServicesにデプロイしていました。今回は、githubのPRをマージ(Mainブランチを更新)したら、githubActionでビルド→ACRにプッシュ→AppServicesにデプロイするようにします。
今回やりたいこと
・秘密情報(APIのシークレットやクレデンシャル)をKeyVaultに移行
・ソースコードをgithubにpush
・PRをマージしたらACRにpush
KeyVaultに移行
まずは、秘密情報をKeyVaultに移します。プログラムや設定ファイルには書かず、DockerfileのENVに書いていたため、KeyVaultにコピペしました。あとはAppServicesの環境変数からKeyVaultを読むように変更すればOKです。
githubにpushする
CI/CDを整備するためにもgithubでソースを管理します。Orgにリポジトリを追加してpushしました。
マージしたらACRにpushする
この記事を見ながら、まずはACRにpushできるようにworkflowを整備していきます。準備されているYAMLファイルに自分の環境部分を追記していきます。
またPrismaでエラーになった
Error: @prisma/client did not initialize yet. Please run "prisma generate" and try to import it again.
Prismaはテーブル定義からORMのファイルを自動生成しています。ローカルでは手動でコマンド実行していたが、githubにpushする際に node_modules は除外していたので、ビルド時にこのコマンドが必要なことを気付かなかった。
・・・
FROM base AS builder
WORKDIR /app
COPY /app/node_modules ./node_modules
COPY . .
RUN npx prisma generate
・・・
取り急ぎ node_modules を作った後で npx することでエラー解消しました。
push後AppServicesのWebHookが効かない
手動ビルド時は気にせずタグ名を latest にしていたが GA にしてからはSHAに変えました。WebHookの設定では latest が更新されたらデプロイする、という設定にしていたので動かなくなっていました。
毎回タグ名が変わるのでWorkFlowにAppServicesをデプロイするまで組み込むことで最後まで動かせています。latestのWebHookは不要なので削除しました。
name: CI to Azure Container Registry
on:
push:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
name: Checkout source code
- name: Log in to Azure Container Registry
uses: docker/login-action@v2
with:
registry: <レジストリ名>.azurecr.io
username: ${{ secrets.REGISTRY_USERNAME }}
password: ${{ secrets.REGISTRY_PASSWORD }}
- name: Build and push Docker image
run: |
docker build . -t <レジストリ名>.azurecr.io/<アプリ名>:${{ github.sha }}
docker push <レジストリ名>.azurecr.io/<アプリ名>:${{ github.sha }}
- uses: azure/webapps-deploy@v2
with:
app-name: '<アプリ名>'
publish-profile: ${{ secrets.AZURE_WEBAPP_PUBLISH_PROFILE }}
images: '<レジストリ名>.azurecr.io/<アプリ名>:${{ github.sha }}'
これで無駄に数分取られる作業を自動化できました!
ついでに Auth.js のセッション情報を取得してみます。
参考にしたのはこの記事。
import { auth } from "@/auth";
import { NextResponse } from 'next/server';
export async function GET() {
const session = await auth()
if (!session?.user) return NextResponse.json({ message: "Not authenticated" }, { status: 401 })
return NextResponse.json(session);
}
レスポンス
{"user":{"id":"cm8gyeegk0001m5m016jv99r7","name":"kai kusakari","email":"kai.kusakari@gmail.com","emailVerified":null,"image":"https://lh3.googleusercontent.com/a/ACg8ocK0BGDNEzzXxP2Qce7rkfRXgy2c-GPjn9yiMQz76WV2uhEct-cT=s96-c","createdAt":"2025-03-20T06:11:46.484Z","updatedAt":"2025-03-20T06:11:46.484Z"},"sessionToken":"<session token>","userId":"cm8gyeegk0001m5m016jv99r7","expires":"2025-04-20T13:19:23.910Z","createdAt":"2025-03-21T13:19:23.912Z","updatedAt":"2025-03-21T13:19:23.912Z"}
サーバサイド側でもしっかりログインした人の情報がしっかり取得できているようなので、素晴らしいですね!
Discussion