|
| 1 | +name: conversation-knowledge-mining-custom |
| 2 | + |
| 3 | +requiredVersions: |
| 4 | + azd: ">= 1.18.0" |
| 5 | + |
| 6 | +metadata: |
| 7 | + |
| 8 | + |
| 9 | +environment: |
| 10 | + name: conversation-knowledge-mining |
| 11 | + location: japaneast |
| 12 | + |
| 13 | +infra: |
| 14 | + provider: bicep |
| 15 | + path: infra |
| 16 | + module: main |
| 17 | + parameters: infra/main.parameters.json |
| 18 | + |
| 19 | +hooks: |
| 20 | + preprovision: |
| 21 | + windows: |
| 22 | + shell: pwsh |
| 23 | + interactive: true |
| 24 | + continueOnError: false |
| 25 | + run: | |
| 26 | + $ErrorActionPreference = 'Stop' |
| 27 | +
|
| 28 | + Write-Host "[preprovision] Preparing ACR and building local images..." -ForegroundColor Cyan |
| 29 | +
|
| 30 | + try { az account show | Out-Null } catch { Write-Error "Azure CLI not logged in. Run 'az login' first."; exit 1 } |
| 31 | +
|
| 32 | + $location = $env:AZURE_LOCATION |
| 33 | + if (-not $location) { $location = 'japaneast' } |
| 34 | + $envName = $env:AZURE_ENV_NAME |
| 35 | + if (-not $envName) { $envName = 'conversation-knowledge-mining' } |
| 36 | +
|
| 37 | + $env:AZURE_LOCATION = $location |
| 38 | + azd env set AZURE_LOCATION $location | Out-Null |
| 39 | + $env:AZURE_ENV_NAME = $envName |
| 40 | + azd env set AZURE_ENV_NAME $envName | Out-Null |
| 41 | +
|
| 42 | + $acrRg = "rg-$envName-acr" |
| 43 | + if ((az group exists -n $acrRg) -ne 'true') { |
| 44 | + Write-Host "Creating resource group $acrRg in $location" -ForegroundColor Yellow |
| 45 | + az group create -n $acrRg -l $location | Out-Null |
| 46 | + } |
| 47 | +
|
| 48 | + $acrNameBase = 'kmcontainerreg' |
| 49 | + $acrName = $acrNameBase |
| 50 | + if ((az acr check-name --name $acrNameBase --query nameAvailable -o tsv) -ne 'true') { |
| 51 | + $suffix = Get-Random -Maximum 99999 |
| 52 | + $acrName = "$acrNameBase$suffix" |
| 53 | + Write-Host "Base ACR name unavailable. Using $acrName" -ForegroundColor Yellow |
| 54 | + } |
| 55 | +
|
| 56 | + $acrShowName = az acr show -n $acrName -g $acrRg --only-show-errors --query name -o tsv 2>$null |
| 57 | + if ($acrShowName -ne $acrName) { |
| 58 | + Write-Host "Creating ACR $acrName" -ForegroundColor Yellow |
| 59 | + az acr create -n $acrName -g $acrRg -l $location --sku Basic --only-show-errors | Out-Null |
| 60 | + $acrServer = '' |
| 61 | + for ($i = 0; $i -lt 30; $i++) { |
| 62 | + $acrServer = az acr show -n $acrName --query loginServer -o tsv 2>$null |
| 63 | + if ($acrServer) { break } |
| 64 | + Start-Sleep -Seconds 5 |
| 65 | + } |
| 66 | + if (-not $acrServer) { Write-Error "ACR $acrName did not become ready (no loginServer)"; exit 1 } |
| 67 | + } |
| 68 | +
|
| 69 | + az acr update -n $acrName --admin-enabled true | Out-Null |
| 70 | + $acrServer = az acr show -n $acrName --query loginServer -o tsv |
| 71 | + $acrCreds = az acr credential show -n $acrName --only-show-errors | ConvertFrom-Json |
| 72 | + if (-not $acrCreds -or -not $acrCreds.passwords -or $acrCreds.passwords.Count -lt 1) { |
| 73 | + Write-Error "ACR credentials unavailable."; exit 1 |
| 74 | + } |
| 75 | + $acrUser = $acrCreds.username |
| 76 | + $acrPass = $acrCreds.passwords[0].value |
| 77 | +
|
| 78 | + $tag = "latest_waf_{0}" -f ((Get-Date).ToString("yyyy-MM-dd_HHmm")) |
| 79 | + $env:AZURE_ENV_IMAGETAG = $tag |
| 80 | + $env:AZURE_ENV_CONTAINER_REGISTRY_ENDPOINT = $acrServer |
| 81 | + $env:AZURE_ENV_ACR_USERNAME = $acrUser |
| 82 | + $env:AZURE_ENV_ACR_PASSWORD = $acrPass |
| 83 | +
|
| 84 | + azd env set AZURE_ENV_IMAGETAG $tag | Out-Null |
| 85 | + azd env set AZURE_ENV_CONTAINER_REGISTRY_ENDPOINT $acrServer | Out-Null |
| 86 | + azd env set AZURE_ENV_ACR_USERNAME $acrUser | Out-Null |
| 87 | + azd env set AZURE_ENV_ACR_PASSWORD $acrPass | Out-Null |
| 88 | +
|
| 89 | + Write-Host "Using registry: $acrServer" -ForegroundColor Cyan |
| 90 | + Write-Host "Image tag: $tag" -ForegroundColor Cyan |
| 91 | +
|
| 92 | + Write-Host "Building API image (km-api:$tag) via ACR Build" -ForegroundColor Yellow |
| 93 | + $repoRoot = (Get-Location).Path |
| 94 | + $apiCtx = Join-Path $repoRoot 'src\api' |
| 95 | + $apiDockerfile = Join-Path $apiCtx 'ApiApp.Dockerfile' |
| 96 | + if (-not (Test-Path $apiDockerfile)) { Write-Error "API Dockerfile not found at $apiDockerfile"; exit 1 } |
| 97 | + $apiBuildSucceeded = $true |
| 98 | + az acr build -r $acrName -t "km-api:$tag" -f $apiDockerfile $apiCtx |
| 99 | + if ($LASTEXITCODE -ne 0) { $apiBuildSucceeded = $false } |
| 100 | + if (-not $apiBuildSucceeded) { |
| 101 | + Write-Warning "ACR build failed for km-api. Falling back to local Docker build & push." |
| 102 | + if (-not (Get-Command docker -ErrorAction SilentlyContinue)) { Write-Error "Docker is not installed or not in PATH for local fallback."; exit 1 } |
| 103 | + az acr login -n $acrName | Out-Null |
| 104 | + docker build -f $apiDockerfile -t "$acrServer/km-api:$tag" $apiCtx |
| 105 | + docker push "$acrServer/km-api:$tag" |
| 106 | + } |
| 107 | +
|
| 108 | + Write-Host "Building Frontend image (km-app:$tag) via ACR Build" -ForegroundColor Yellow |
| 109 | + $feCtx = Join-Path $repoRoot 'src\App' |
| 110 | + $feDockerfile = Join-Path $feCtx 'WebApp.Dockerfile' |
| 111 | + if (-not (Test-Path $feDockerfile)) { Write-Error "Frontend Dockerfile not found at $feDockerfile"; exit 1 } |
| 112 | + $feBuildSucceeded = $true |
| 113 | + az acr build -r $acrName -t "km-app:$tag" -f $feDockerfile $feCtx |
| 114 | + if ($LASTEXITCODE -ne 0) { $feBuildSucceeded = $false } |
| 115 | + if (-not $feBuildSucceeded) { |
| 116 | + Write-Warning "ACR build failed for km-app. Falling back to local Docker build & push." |
| 117 | + if (-not (Get-Command docker -ErrorAction SilentlyContinue)) { Write-Error "Docker is not installed or not in PATH for local fallback."; exit 1 } |
| 118 | + az acr login -n $acrName | Out-Null |
| 119 | + docker build -f $feDockerfile -t "$acrServer/km-app:$tag" $feCtx |
| 120 | + docker push "$acrServer/km-app:$tag" |
| 121 | + } |
| 122 | +
|
| 123 | + Write-Host "[preprovision] Images built & pushed. Proceeding to provision..." -ForegroundColor Green |
| 124 | +
|
| 125 | + posix: |
| 126 | + shell: sh |
| 127 | + interactive: true |
| 128 | + continueOnError: false |
| 129 | + run: | |
| 130 | + set -euo pipefail |
| 131 | + echo "[preprovision] Preparing ACR and building local images..." |
| 132 | + az account show >/dev/null || { echo "Run 'az login' first"; exit 1; } |
| 133 | + : "${AZURE_LOCATION:=japaneast}" |
| 134 | + : "${AZURE_ENV_NAME:=conversation-knowledge-mining}" |
| 135 | + azd env set AZURE_LOCATION "$AZURE_LOCATION" >/dev/null |
| 136 | + azd env set AZURE_ENV_NAME "$AZURE_ENV_NAME" >/dev/null |
| 137 | + acr_rg="rg-${AZURE_ENV_NAME}-acr" |
| 138 | + az group create -n "$acr_rg" -l "$AZURE_LOCATION" >/dev/null 2>&1 || true |
| 139 | + acr_name_base="kmcontainerreg" |
| 140 | + name_ok=$(az acr check-name --name "$acr_name_base" --query nameAvailable -o tsv) |
| 141 | + if [ "$name_ok" != "true" ]; then |
| 142 | + suffix=$(printf "%05d" $(shuf -i 0-99999 -n 1)) |
| 143 | + acr_name="${acr_name_base}${suffix}" |
| 144 | + echo "Base ACR name unavailable. Using $acr_name" |
| 145 | + else |
| 146 | + acr_name="$acr_name_base" |
| 147 | + fi |
| 148 | + az acr show -n "$acr_name" -g "$acr_rg" >/dev/null 2>&1 || az acr create -n "$acr_name" -g "$acr_rg" -l "$AZURE_LOCATION" --sku Basic >/dev/null |
| 149 | + az acr update -n "$acr_name" --admin-enabled true >/dev/null |
| 150 | + acr_server=$(az acr show -n "$acr_name" --query loginServer -o tsv) |
| 151 | + acr_user=$(az acr credential show -n "$acr_name" --query username -o tsv) |
| 152 | + acr_pass=$(az acr credential show -n "$acr_name" --query passwords[0].value -o tsv) |
| 153 | + tag="latest_waf_$(date +%Y-%m-%d_%H%M)" |
| 154 | + export AZURE_ENV_IMAGETAG="$tag" |
| 155 | + export AZURE_ENV_CONTAINER_REGISTRY_ENDPOINT="$acr_server" |
| 156 | + export AZURE_ENV_ACR_USERNAME="$acr_user" |
| 157 | + export AZURE_ENV_ACR_PASSWORD="$acr_pass" |
| 158 | + azd env set AZURE_ENV_IMAGETAG "$tag" >/dev/null |
| 159 | + azd env set AZURE_ENV_CONTAINER_REGISTRY_ENDPOINT "$acr_server" >/dev/null |
| 160 | + azd env set AZURE_ENV_ACR_USERNAME "$acr_user" >/dev/null |
| 161 | + azd env set AZURE_ENV_ACR_PASSWORD "$acr_pass" >/dev/null |
| 162 | + echo "Using registry: $acr_server" |
| 163 | + echo "Image tag: $tag" |
| 164 | + echo "Building API image (km-api:$tag) via ACR Build" |
| 165 | + api_ctx="$(pwd)/src/api" |
| 166 | + api_df="$api_ctx/ApiApp.Dockerfile" |
| 167 | + [ -f "$api_df" ] || { echo "API Dockerfile not found at $api_df"; exit 1; } |
| 168 | + if ! az acr build -r "$acr_name" -t "km-api:$tag" -f "$api_df" "$api_ctx"; then |
| 169 | + echo "ACR build failed for km-api. Falling back to local Docker build & push." |
| 170 | + command -v docker >/dev/null 2>&1 || { echo "Docker not installed for local fallback."; exit 1; } |
| 171 | + az acr login -n "$acr_name" >/dev/null |
| 172 | + docker build -f "$api_df" -t "$acr_server/km-api:$tag" "$api_ctx" |
| 173 | + docker push "$acr_server/km-api:$tag" |
| 174 | + fi |
| 175 | +
|
| 176 | + echo "Building Frontend image (km-app:$tag) via ACR Build" |
| 177 | + fe_ctx="$(pwd)/src/App" |
| 178 | + fe_df="$fe_ctx/WebApp.Dockerfile" |
| 179 | + [ -f "$fe_df" ] || { echo "Frontend Dockerfile not found at $fe_df"; exit 1; } |
| 180 | + if ! az acr build -r "$acr_name" -t "km-app:$tag" -f "$fe_df" "$fe_ctx"; then |
| 181 | + echo "ACR build failed for km-app. Falling back to local Docker build & push." |
| 182 | + command -v docker >/dev/null 2>&1 || { echo "Docker not installed for local fallback."; exit 1; } |
| 183 | + az acr login -n "$acr_name" >/dev/null |
| 184 | + docker build -f "$fe_df" -t "$acr_server/km-app:$tag" "$fe_ctx" |
| 185 | + docker push "$acr_server/km-app:$tag" |
| 186 | + fi |
| 187 | + echo "[preprovision] Images built & pushed. Proceeding to provision..." |
| 188 | +
|
| 189 | + postprovision: |
| 190 | + windows: |
| 191 | + shell: pwsh |
| 192 | + interactive: true |
| 193 | + continueOnError: false |
| 194 | + run: | |
| 195 | + $ErrorActionPreference = 'Stop' |
| 196 | +
|
| 197 | + Write-Host "[postprovision] Configuring App Services to use ACR credentials..." -ForegroundColor Cyan |
| 198 | +
|
| 199 | + $rg = $env:RESOURCE_GROUP_NAME |
| 200 | + $acrServer = $env:AZURE_ENV_CONTAINER_REGISTRY_ENDPOINT |
| 201 | + $acrUser = $env:AZURE_ENV_ACR_USERNAME |
| 202 | + $acrPass = $env:AZURE_ENV_ACR_PASSWORD |
| 203 | +
|
| 204 | + if (-not $rg) { Write-Warning "RESOURCE_GROUP_NAME not set; skipping ACR appsettings."; exit 0 } |
| 205 | + if (-not $acrServer -or -not $acrUser -or -not $acrPass) { Write-Warning "ACR env vars missing; skipping appsettings."; exit 0 } |
| 206 | +
|
| 207 | + $webAppName = ([uri]$env:WEB_APP_URL).Host.Split('.')[0] |
| 208 | + $apiAppName = ([uri]$env:API_APP_URL).Host.Split('.')[0] |
| 209 | +
|
| 210 | + foreach ($appName in @($webAppName, $apiAppName)) { |
| 211 | + if (-not $appName) { continue } |
| 212 | + Write-Host "Updating appsettings for $appName" -ForegroundColor Yellow |
| 213 | + az webapp config appsettings set -g $rg -n $appName --settings "DOCKER_REGISTRY_SERVER_URL=https://$acrServer" "DOCKER_REGISTRY_SERVER_USERNAME=$acrUser" "DOCKER_REGISTRY_SERVER_PASSWORD=$acrPass" | Out-Null |
| 214 | + } |
| 215 | +
|
| 216 | + # Ensure container images are updated to the freshly built tag |
| 217 | + if ($acrServer -and $env:AZURE_ENV_IMAGETAG) { |
| 218 | + $tag = $env:AZURE_ENV_IMAGETAG |
| 219 | + if ($apiAppName) { |
| 220 | + Write-Host "Setting API container image to $acrServer/km-api:$tag" -ForegroundColor Yellow |
| 221 | + az webapp config container set -g $rg -n $apiAppName --docker-custom-image-name "$acrServer/km-api:$tag" | Out-Null |
| 222 | + az webapp restart -g $rg -n $apiAppName | Out-Null |
| 223 | + $apiFx = az webapp config container show -g $rg -n $apiAppName --query linuxFxVersion -o tsv |
| 224 | + Write-Host "API linuxFxVersion: $apiFx" -ForegroundColor Green |
| 225 | + } |
| 226 | + if ($webAppName) { |
| 227 | + Write-Host "Setting Web container image to $acrServer/km-app:$tag" -ForegroundColor Yellow |
| 228 | + az webapp config container set -g $rg -n $webAppName --docker-custom-image-name "$acrServer/km-app:$tag" | Out-Null |
| 229 | + az webapp restart -g $rg -n $webAppName | Out-Null |
| 230 | + $webFx = az webapp config container show -g $rg -n $webAppName --query linuxFxVersion -o tsv |
| 231 | + Write-Host "Web linuxFxVersion: $webFx" -ForegroundColor Green |
| 232 | + } |
| 233 | + } else { |
| 234 | + Write-Warning "AZURE_ENV_CONTAINER_REGISTRY_ENDPOINT or AZURE_ENV_IMAGETAG missing; skipping container image update." |
| 235 | + } |
| 236 | +
|
| 237 | + Write-Host "[postprovision] App Services configured for private ACR." -ForegroundColor Green |
| 238 | +
|
| 239 | + posix: |
| 240 | + shell: sh |
| 241 | + interactive: true |
| 242 | + continueOnError: false |
| 243 | + run: | |
| 244 | + set -euo pipefail |
| 245 | + echo "[postprovision] Configuring App Services to use ACR credentials..." |
| 246 | + rg="${RESOURCE_GROUP_NAME:-}" |
| 247 | + acr_server="${AZURE_ENV_CONTAINER_REGISTRY_ENDPOINT:-}" |
| 248 | + acr_user="${AZURE_ENV_ACR_USERNAME:-}" |
| 249 | + acr_pass="${AZURE_ENV_ACR_PASSWORD:-}" |
| 250 | + [ -z "$rg" ] && echo "RESOURCE_GROUP_NAME not set; skipping." && exit 0 |
| 251 | + [ -z "$acr_server" ] || [ -z "$acr_user" ] || [ -z "$acr_pass" ] && echo "ACR env vars missing; skipping." && exit 0 |
| 252 | + web_app_name=$(echo "$WEB_APP_URL" | sed -E 's#https?://([^/]+)/?.*#\1#' | cut -d'.' -f1) |
| 253 | + api_app_name=$(echo "$API_APP_URL" | sed -E 's#https?://([^/]+)/?.*#\1#' | cut -d'.' -f1) |
| 254 | + for app in "$web_app_name" "$api_app_name"; do |
| 255 | + [ -z "$app" ] && continue |
| 256 | + echo "Updating appsettings for $app" |
| 257 | + az webapp config appsettings set -g "$rg" -n "$app" --settings \ |
| 258 | + DOCKER_REGISTRY_SERVER_URL="https://$acr_server" \ |
| 259 | + DOCKER_REGISTRY_SERVER_USERNAME="$acr_user" \ |
| 260 | + DOCKER_REGISTRY_SERVER_PASSWORD="$acr_pass" >/dev/null |
| 261 | + done |
| 262 | + # Ensure container images are updated to the freshly built tag |
| 263 | + if [ -n "$acr_server" ] && [ -n "${AZURE_ENV_IMAGETAG:-}" ]; then |
| 264 | + tag="$AZURE_ENV_IMAGETAG" |
| 265 | + if [ -n "$api_app_name" ]; then |
| 266 | + echo "Setting API container image to $acr_server/km-api:$tag" |
| 267 | + az webapp config container set -g "$rg" -n "$api_app_name" --docker-custom-image-name "$acr_server/km-api:$tag" >/dev/null |
| 268 | + az webapp restart -g "$rg" -n "$api_app_name" >/dev/null |
| 269 | + fi |
| 270 | + if [ -n "$web_app_name" ]; then |
| 271 | + echo "Setting Web container image to $acr_server/km-app:$tag" |
| 272 | + az webapp config container set -g "$rg" -n "$web_app_name" --docker-custom-image-name "$acr_server/km-app:$tag" >/dev/null |
| 273 | + az webapp restart -g "$rg" -n "$web_app_name" >/dev/null |
| 274 | + fi |
| 275 | + else |
| 276 | + echo "AZURE_ENV_CONTAINER_REGISTRY_ENDPOINT or AZURE_ENV_IMAGETAG missing; skipping container image update." |
| 277 | + fi |
| 278 | + echo "[postprovision] App Services configured for private ACR." |
0 commit comments