From 17d65a2350a8e06e09c4bd894620771ff47d9adc Mon Sep 17 00:00:00 2001 From: Prajwal D C Date: Wed, 25 Jun 2025 20:45:52 +0530 Subject: [PATCH 1/3] feat: Removed local build from preprovision and added as part of post deployment --- azure.yaml | 7 - docs/CustomizingAzdParameters.md | 1 - docs/DeploymentGuide.md | 24 +- .../container_app/deploy_container_app.bicep | 8 +- .../deploy_container_app_api_web.bicep | 4 - infra/deploy_container_registry.bicep | 16 ++ infra/deploy_role_assignments.bicep | 14 -- infra/main.bicep | 44 ++-- infra/main.bicepparam | 12 - infra/main.json | 229 ++++-------------- infra/main.parameters.json | 33 +++ infra/scripts/docker-build.ps1 | 162 ++++++++----- infra/scripts/docker-build.sh | 177 ++++++++------ 13 files changed, 332 insertions(+), 399 deletions(-) delete mode 100644 infra/main.bicepparam create mode 100644 infra/main.parameters.json diff --git a/azure.yaml b/azure.yaml index b5b9121e..d695029d 100644 --- a/azure.yaml +++ b/azure.yaml @@ -8,13 +8,6 @@ metadata: name: content-processinge@1.0 hooks: - preprovision: - posix: - shell: sh - run: timestamp=$(date +"%Y%m%d-%H%M%S"); logFile="azd_preprovision_$timestamp.log"; sed -i 's/\r$//' ./infra/scripts/docker-build.sh; ./infra/scripts/docker-build.sh "$AZURE_SUBSCRIPTION_ID" "$AZURE_ENV_NAME" "$AZURE_LOCATION" "$AZURE_RESOURCE_GROUP" "$USE_LOCAL_BUILD" "$AZURE_ENV_IMAGETAG" 2>&1 | tee "$logFile" - windows: - shell: pwsh - run: $timestamp = Get-Date -Format "yyyyMMdd-HHmmss"; $logFile = "azd_preprovision_$timestamp.log"; ./infra/scripts/docker-build.ps1 $env:AZURE_SUBSCRIPTION_ID $env:AZURE_ENV_NAME $env:AZURE_LOCATION $env:AZURE_RESOURCE_GROUP $env:USE_LOCAL_BUILD $env:AZURE_ENV_IMAGETAG *>&1 | Tee-Object -FilePath $logFile postprovision: posix: shell: sh diff --git a/docs/CustomizingAzdParameters.md b/docs/CustomizingAzdParameters.md index d16f28ab..2ed4c383 100644 --- a/docs/CustomizingAzdParameters.md +++ b/docs/CustomizingAzdParameters.md @@ -16,7 +16,6 @@ By default this template will use the environment name as the prefix to prevent | `AZURE_ENV_MODEL_NAME` | string | `gpt-4o` | Specifies the GPT model name (allowed values: `gpt-4o`). | `AZURE_ENV_MODEL_VERSION` | string | `2024-08-06` | Specifies the GPT model version (allowed values: `2024-08-06`). | | `AZURE_ENV_MODEL_CAPACITY` | integer | `30` | Sets the model capacity (choose based on your subscription's available GPT capacity). | -| `USE_LOCAL_BUILD` | boolean | `false` | Indicates whether to use a local container build for deployment. | | `AZURE_ENV_IMAGETAG` | boolean | `latest` | Set the Image tag Like (allowed values: latest, dev, hotfix) | | `AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID` | string | `` | Reuses an existing Log Analytics Workspace instead of provisioning a new one. | diff --git a/docs/DeploymentGuide.md b/docs/DeploymentGuide.md index 0735575f..f09fb732 100644 --- a/docs/DeploymentGuide.md +++ b/docs/DeploymentGuide.md @@ -177,34 +177,24 @@ Once you've opened the project in [Codespaces](#github-codespaces), [Dev Contain 6. If you are done trying out the application, you can delete the resources by running `azd down`. -### Publishing Local Build Container to Azure Container Registry +## Post Deployment Steps +1. Optional: Publishing Local Build Container to Azure Container Registry If you need to rebuild the source code and push the updated container to the deployed Azure Container Registry, follow these steps: -1. Set the environment variable `USE_LOCAL_BUILD` to `True`: - - **Linux/macOS**: ```bash - export USE_LOCAL_BUILD=True + cd ./infra/scripts/ + ./docker-build.sh ``` - **Windows (PowerShell)**: ```powershell - $env:USE_LOCAL_BUILD = $true + cd .\infra\scripts\ + .\docker-build.ps1 ``` -2. Run the `az login` command - ```bash - az login - ``` - -3. Run the `azd up` command again to rebuild and push the updated container: - ```bash - azd up - ``` -This will rebuild the source code, package it into a container, and push it to the Azure Container Registry associated with your deployment. - -## Post Deployment Steps +This will create a new Azure Container Registry, rebuild the source code, package it into a container, and push it to the Container Registry created. 1. **Register Schema Files** diff --git a/infra/container_app/deploy_container_app.bicep b/infra/container_app/deploy_container_app.bicep index a20a6b0c..5275a843 100644 --- a/infra/container_app/deploy_container_app.bicep +++ b/infra/container_app/deploy_container_app.bicep @@ -16,7 +16,6 @@ param probes array = [] param allowedOrigins array = [] param minReplicas int = 1 param maxReplicas int = 1 -param useLocalBuild string = 'false' //Todo: Add Appconfig endpoint as Env variable @@ -34,12 +33,7 @@ resource processorContainerApp 'Microsoft.App/containerApps@2024-03-01' = { environmentId: containerEnvId workloadProfileName: 'Consumption' configuration:{ - registries: useLocalBuild == 'true' ? [ - { - server: azureContainerRegistry - identity: managedIdentityId - } - ] : null + registries: null ingress: enableIngress ? { external: true transport: 'auto' diff --git a/infra/container_app/deploy_container_app_api_web.bicep b/infra/container_app/deploy_container_app_api_web.bicep index 41272dd2..9245898f 100644 --- a/infra/container_app/deploy_container_app_api_web.bicep +++ b/infra/container_app/deploy_container_app_api_web.bicep @@ -25,7 +25,6 @@ param maxReplicaContainerWeb int = 1 // Container related params param azureContainerRegistry string param containerRegistryReaderId string -param useLocalBuild string = 'false' param imageTag string var abbrs = loadJsonContent('../abbreviations.json') @@ -88,7 +87,6 @@ module containerApp 'deploy_container_app.bicep' = { enableIngress: false minReplicas: minReplicaContainerApp maxReplicas: maxReplicaContainerApp - useLocalBuild: useLocalBuild } } @@ -112,7 +110,6 @@ module containerAppApi 'deploy_container_app.bicep' = { probes: probes minReplicas: minReplicaContainerApi maxReplicas: maxReplicaContainerApi - useLocalBuild: useLocalBuild } } @@ -154,7 +151,6 @@ module containerAppWeb 'deploy_container_app.bicep' = { ] minReplicas: minReplicaContainerWeb maxReplicas: maxReplicaContainerWeb - useLocalBuild: useLocalBuild } } diff --git a/infra/deploy_container_registry.bicep b/infra/deploy_container_registry.bicep index 021fb7b4..571e10af 100644 --- a/infra/deploy_container_registry.bicep +++ b/infra/deploy_container_registry.bicep @@ -14,6 +14,9 @@ param location string = resourceGroup().location @description('Provide a tier of your Azure Container Registry.') param acrSku string = 'Basic' + +@description('List of Principal Ids to which ACR pull role assignment is required') +param acrPullPrincipalIds array = [] resource containerRegistry 'Microsoft.ContainerRegistry/registries@2021-09-01' = { name: containerNameCleaned @@ -26,6 +29,19 @@ resource containerRegistry 'Microsoft.ContainerRegistry/registries@2021-09-01' = zoneRedundancy: 'Disabled' } } + +// Add Role assignments for required principal id's +resource acrPullRoleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for principalId in acrPullPrincipalIds: { + name: guid(principalId, 'acrpull') + scope: containerRegistry + properties: { + roleDefinitionId: subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '7f951dda-4ed3-4680-a7ca-43fe172d538d' + ) + principalId: principalId + } +}] output createdAcrName string = containerNameCleaned output createdAcrId string = containerRegistry.id diff --git a/infra/deploy_role_assignments.bicep b/infra/deploy_role_assignments.bicep index a8c8e8f7..4c915418 100644 --- a/infra/deploy_role_assignments.bicep +++ b/infra/deploy_role_assignments.bicep @@ -9,8 +9,6 @@ param storagePrincipalId string // Resource ID of the Storage account param aiServiceCUId string // Resource ID of the Azure AI Content Understanding Service param aiServiceId string // Resource ID of the Azure Open AI service -param containerRegistryReaderPrincipalId string - resource appConfigDataReader 'Microsoft.Authorization/roleDefinitions@2018-01-01-preview' existing = { scope: resourceGroup() name: '516239f1-63e1-4d78-a4de-a74fb236a071' @@ -130,15 +128,3 @@ resource cognitiveServicesUserRoleAssignment 'Microsoft.Authorization/roleAssign principalType: 'ServicePrincipal' } } - -resource acrPullRoleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = { - name: guid(containerRegistryReaderPrincipalId, 'acrpull') - scope: resourceGroup() - properties: { - roleDefinitionId: subscriptionResourceId( - 'Microsoft.Authorization/roleDefinitions', - '7f951dda-4ed3-4680-a7ca-43fe172d538d' - ) // AcrPull role - principalId: containerRegistryReaderPrincipalId - } -} diff --git a/infra/main.bicep b/infra/main.bicep index b2cb538b..83501cf8 100644 --- a/infra/main.bicep +++ b/infra/main.bicep @@ -20,7 +20,16 @@ param secondaryLocation string = 'EastUs2' type: 'location' } }) -param contentUnderstandingLocation string +param contentUnderstandingLocation string = 'WestUS' + +@metadata({azd: { + type: 'location' + usageName: [ + 'OpenAI.GlobalStandard.gpt-4o,100' + ] + } +}) +param aiDeploymentsLocation string @minLength(1) @description('GPT model deployment type:') @@ -36,8 +45,6 @@ param gptModelName string = 'gpt-4o' @description('Version of the GPT model to deploy:') param gptModelVersion string = '2024-08-06' -//var gptModelVersion = '2024-02-15-preview' - @minValue(10) @description('Capacity of the GPT deployment:') // You can increase this, but capacity is limited per model/region, so you will get errors if you go over @@ -62,9 +69,6 @@ param minReplicaContainerWeb int = 1 @description('Maximum number of replicas to be added for Container Web App') param maxReplicaContainerWeb int = 1 -@description('Set this flag to true only if you are deplpoying from Local') -param useLocalBuild string = 'false' - @description('Optional: Existing Log Analytics Workspace Resource ID') param existingLogAnalyticsWorkspaceId string = '' @@ -76,9 +80,6 @@ var resourceGroupLocation = resourceGroup().location // Load the abbrevations file required to name the azure resources. var abbrs = loadJsonContent('./abbreviations.json') -// Convert input to lowercase -var useLocalBuildLower = toLower(useLocalBuild) - // ========== Managed Identity ========== // module managedIdentityModule 'deploy_managed_identity.bicep' = { name: 'deploy_managed_identity' @@ -111,13 +112,13 @@ module applicationInsights 'deploy_app_insights.bicep' = { } } -// ========== Container Registry ========== // -module containerRegistry 'deploy_container_registry.bicep' = { - name: 'deploy_container_registry' - params: { - environmentName: environmentName - } -} +// // ========== Container Registry ========== // +// module containerRegistry 'deploy_container_registry.bicep' = { +// name: 'deploy_container_registry' +// params: { +// environmentName: environmentName +// } +// } // ========== Storage Account ========== // module storage 'deploy_storage_account.bicep' = { @@ -134,7 +135,7 @@ module aifoundry 'deploy_ai_foundry.bicep' = { name: 'deploy_ai_foundry' params: { solutionName: solutionPrefix - solutionLocation: resourceGroupLocation + solutionLocation: aiDeploymentsLocation cuLocation: contentUnderstandingLocation deploymentType: deploymentType gptModelName: gptModelName @@ -173,7 +174,6 @@ module containerApps './container_app/deploy_container_app_api_web.bicep' = { maxReplicaContainerApi: maxReplicaContainerApi minReplicaContainerWeb: minReplicaContainerWeb maxReplicaContainerWeb: maxReplicaContainerWeb - useLocalBuild: 'false' imageTag: 'latest' } } @@ -221,7 +221,6 @@ module roleAssignments 'deploy_role_assignments.bicep' = { containerAppPrincipalId: containerApps.outputs.containerAppPrincipalId aiServiceCUId: aifoundry.outputs.aiServicesCuId aiServiceId: aifoundry.outputs.aiServicesId - containerRegistryReaderPrincipalId: containerAppEnv.outputs.containerRegistryReaderPrincipalId } } @@ -230,7 +229,7 @@ module updateContainerApp './container_app/deploy_container_app_api_web.bicep' = params: { solutionName: solutionPrefix location: secondaryLocation - azureContainerRegistry: useLocalBuildLower == 'true' ? containerRegistry.outputs.acrEndpoint : containerImageEndPoint + azureContainerRegistry: containerImageEndPoint appConfigEndPoint: appconfig.outputs.appConfigEndpoint containerAppEnvId: containerAppEnv.outputs.containerEnvId containerRegistryReaderId: containerAppEnv.outputs.containerRegistryReaderId @@ -242,7 +241,6 @@ module updateContainerApp './container_app/deploy_container_app_api_web.bicep' = maxReplicaContainerApi: maxReplicaContainerApi minReplicaContainerWeb: minReplicaContainerWeb maxReplicaContainerWeb: maxReplicaContainerWeb - useLocalBuild: useLocalBuildLower imageTag: imageTag } dependsOn: [roleAssignments] @@ -251,4 +249,8 @@ module updateContainerApp './container_app/deploy_container_app_api_web.bicep' = output CONTAINER_WEB_APP_NAME string = containerApps.outputs.containerAppWebName output CONTAINER_API_APP_NAME string = containerApps.outputs.containerAppApiName output CONTAINER_WEB_APP_FQDN string = containerApps.outputs.containweAppWebEndPoint +output CONTAINER_APP_NAME string = containerApps.outputs.containerAppName output CONTAINER_API_APP_FQDN string = containerApps.outputs.containweAppApiEndPoint +output CONTAINER_APP_USER_IDENTITY_ID string = containerAppEnv.outputs.containerRegistryReaderId +output CONTAINER_APP_USER_PRINCIPAL_ID string = containerAppEnv.outputs.containerRegistryReaderPrincipalId +output AZURE_ENV_IMAGETAG string = imageTag diff --git a/infra/main.bicepparam b/infra/main.bicepparam deleted file mode 100644 index b6a15d71..00000000 --- a/infra/main.bicepparam +++ /dev/null @@ -1,12 +0,0 @@ -using './main.bicep' - -param environmentName = readEnvironmentVariable('AZURE_ENV_NAME', 'cps') -param secondaryLocation = readEnvironmentVariable('AZURE_ENV_SECONDARY_LOCATION', 'EastUs2') -param contentUnderstandingLocation = readEnvironmentVariable('AZURE_ENV_CU_LOCATION', 'WestUS') -param deploymentType = readEnvironmentVariable('AZURE_ENV_MODEL_DEPLOYMENT_TYPE', 'GlobalStandard') -param gptModelName = readEnvironmentVariable('AZURE_ENV_MODEL_NAME', 'gpt-4o') -param gptModelVersion = readEnvironmentVariable('AZURE_ENV_MODEL_VERSION', '2024-08-06') -param gptDeploymentCapacity = int(readEnvironmentVariable('AZURE_ENV_MODEL_CAPACITY', '30')) -param useLocalBuild = readEnvironmentVariable('USE_LOCAL_BUILD', 'false') -param imageTag = readEnvironmentVariable('AZURE_ENV_IMAGETAG', 'latest') -param existingLogAnalyticsWorkspaceId = readEnvironmentVariable('AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID', '') diff --git a/infra/main.json b/infra/main.json index 4221a0bb..cda89093 100644 --- a/infra/main.json +++ b/infra/main.json @@ -5,7 +5,7 @@ "_generator": { "name": "bicep", "version": "0.36.1.42791", - "templateHash": "7133413659987113184" + "templateHash": "4455095207947106270" } }, "parameters": { @@ -26,6 +26,7 @@ }, "contentUnderstandingLocation": { "type": "string", + "defaultValue": "WestUS", "allowedValues": [ "WestUS", "SwedenCentral", @@ -39,6 +40,17 @@ }, "minLength": 1 }, + "aiDeploymentsLocation": { + "type": "string", + "metadata": { + "azd": { + "type": "location", + "usageName": [ + "OpenAI.GlobalStandard.gpt-4o,100" + ] + } + } + }, "deploymentType": { "type": "string", "defaultValue": "GlobalStandard", @@ -115,13 +127,6 @@ "description": "Maximum number of replicas to be added for Container Web App" } }, - "useLocalBuild": { - "type": "string", - "defaultValue": "false", - "metadata": { - "description": "Set this flag to true only if you are deplpoying from Local" - } - }, "existingLogAnalyticsWorkspaceId": { "type": "string", "defaultValue": "", @@ -368,8 +373,7 @@ "solutionPrefix": "[format('cps-{0}', padLeft(take(variables('uniqueId'), 12), 12, '0'))]", "containerImageEndPoint": "cpscontainerreg.azurecr.io", "resourceGroupLocation": "[resourceGroup().location]", - "abbrs": "[variables('$fxv#0')]", - "useLocalBuildLower": "[toLower(parameters('useLocalBuild'))]" + "abbrs": "[variables('$fxv#0')]" }, "resources": [ { @@ -678,86 +682,6 @@ } } }, - { - "type": "Microsoft.Resources/deployments", - "apiVersion": "2022-09-01", - "name": "deploy_container_registry", - "properties": { - "expressionEvaluationOptions": { - "scope": "inner" - }, - "mode": "Incremental", - "parameters": { - "environmentName": { - "value": "[parameters('environmentName')]" - } - }, - "template": { - "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "contentVersion": "1.0.0.0", - "metadata": { - "_generator": { - "name": "bicep", - "version": "0.36.1.42791", - "templateHash": "6955709595359352278" - } - }, - "parameters": { - "environmentName": { - "type": "string" - }, - "location": { - "type": "string", - "defaultValue": "[resourceGroup().location]", - "metadata": { - "description": "Provide a location for the registry." - } - }, - "acrSku": { - "type": "string", - "defaultValue": "Basic", - "metadata": { - "description": "Provide a tier of your Azure Container Registry." - } - } - }, - "variables": { - "uniqueId": "[toLower(uniqueString(subscription().id, parameters('environmentName'), resourceGroup().location))]", - "solutionName": "[format('cps-{0}', padLeft(take(variables('uniqueId'), 12), 12, '0'))]", - "containerNameCleaned": "[replace(format('cr{0}', variables('solutionName')), '-', '')]" - }, - "resources": [ - { - "type": "Microsoft.ContainerRegistry/registries", - "apiVersion": "2021-09-01", - "name": "[variables('containerNameCleaned')]", - "location": "[parameters('location')]", - "sku": { - "name": "[parameters('acrSku')]" - }, - "properties": { - "publicNetworkAccess": "Enabled", - "zoneRedundancy": "Disabled" - } - } - ], - "outputs": { - "createdAcrName": { - "type": "string", - "value": "[variables('containerNameCleaned')]" - }, - "createdAcrId": { - "type": "string", - "value": "[resourceId('Microsoft.ContainerRegistry/registries', variables('containerNameCleaned'))]" - }, - "acrEndpoint": { - "type": "string", - "value": "[reference(resourceId('Microsoft.ContainerRegistry/registries', variables('containerNameCleaned')), '2021-09-01').loginServer]" - } - } - } - } - }, { "type": "Microsoft.Resources/deployments", "apiVersion": "2022-09-01", @@ -906,7 +830,7 @@ "value": "[variables('solutionPrefix')]" }, "solutionLocation": { - "value": "[variables('resourceGroupLocation')]" + "value": "[parameters('aiDeploymentsLocation')]" }, "cuLocation": { "value": "[parameters('contentUnderstandingLocation')]" @@ -1503,9 +1427,6 @@ "maxReplicaContainerWeb": { "value": "[parameters('maxReplicaContainerWeb')]" }, - "useLocalBuild": { - "value": "false" - }, "imageTag": { "value": "latest" } @@ -1517,7 +1438,7 @@ "_generator": { "name": "bicep", "version": "0.36.1.42791", - "templateHash": "9208787367229886695" + "templateHash": "10338800926086953929" } }, "parameters": { @@ -1590,10 +1511,6 @@ "containerRegistryReaderId": { "type": "string" }, - "useLocalBuild": { - "type": "string", - "defaultValue": "false" - }, "imageTag": { "type": "string" } @@ -1913,9 +1830,6 @@ }, "maxReplicas": { "value": "[parameters('maxReplicaContainerApp')]" - }, - "useLocalBuild": { - "value": "[parameters('useLocalBuild')]" } }, "template": { @@ -1925,7 +1839,7 @@ "_generator": { "name": "bicep", "version": "0.36.1.42791", - "templateHash": "13562163699289922411" + "templateHash": "8984863566776850276" } }, "parameters": { @@ -1973,10 +1887,6 @@ "maxReplicas": { "type": "int", "defaultValue": 1 - }, - "useLocalBuild": { - "type": "string", - "defaultValue": "false" } }, "resources": [ @@ -1996,7 +1906,7 @@ "environmentId": "[parameters('containerEnvId')]", "workloadProfileName": "Consumption", "configuration": { - "registries": "[if(equals(parameters('useLocalBuild'), 'true'), createArray(createObject('server', parameters('azureContainerRegistry'), 'identity', parameters('managedIdentityId'))), null())]", + "registries": null, "ingress": "[if(parameters('enableIngress'), createObject('external', true(), 'transport', 'auto', 'allowInsecure', true(), 'corsPolicy', if(greater(length(parameters('allowedOrigins')), 0), createObject('allowedOrigins', parameters('allowedOrigins'), 'allowedMethods', createArray('GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'), 'allowedHeaders', createArray('Authorization', 'Content-Type', '*')), null())), null())]" }, "template": { @@ -2093,9 +2003,6 @@ }, "maxReplicas": { "value": "[parameters('maxReplicaContainerApi')]" - }, - "useLocalBuild": { - "value": "[parameters('useLocalBuild')]" } }, "template": { @@ -2105,7 +2012,7 @@ "_generator": { "name": "bicep", "version": "0.36.1.42791", - "templateHash": "13562163699289922411" + "templateHash": "8984863566776850276" } }, "parameters": { @@ -2153,10 +2060,6 @@ "maxReplicas": { "type": "int", "defaultValue": 1 - }, - "useLocalBuild": { - "type": "string", - "defaultValue": "false" } }, "resources": [ @@ -2176,7 +2079,7 @@ "environmentId": "[parameters('containerEnvId')]", "workloadProfileName": "Consumption", "configuration": { - "registries": "[if(equals(parameters('useLocalBuild'), 'true'), createArray(createObject('server', parameters('azureContainerRegistry'), 'identity', parameters('managedIdentityId'))), null())]", + "registries": null, "ingress": "[if(parameters('enableIngress'), createObject('external', true(), 'transport', 'auto', 'allowInsecure', true(), 'corsPolicy', if(greater(length(parameters('allowedOrigins')), 0), createObject('allowedOrigins', parameters('allowedOrigins'), 'allowedMethods', createArray('GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'), 'allowedHeaders', createArray('Authorization', 'Content-Type', '*')), null())), null())]" }, "template": { @@ -2285,9 +2188,6 @@ }, "maxReplicas": { "value": "[parameters('maxReplicaContainerWeb')]" - }, - "useLocalBuild": { - "value": "[parameters('useLocalBuild')]" } }, "template": { @@ -2297,7 +2197,7 @@ "_generator": { "name": "bicep", "version": "0.36.1.42791", - "templateHash": "13562163699289922411" + "templateHash": "8984863566776850276" } }, "parameters": { @@ -2345,10 +2245,6 @@ "maxReplicas": { "type": "int", "defaultValue": 1 - }, - "useLocalBuild": { - "type": "string", - "defaultValue": "false" } }, "resources": [ @@ -2368,7 +2264,7 @@ "environmentId": "[parameters('containerEnvId')]", "workloadProfileName": "Consumption", "configuration": { - "registries": "[if(equals(parameters('useLocalBuild'), 'true'), createArray(createObject('server', parameters('azureContainerRegistry'), 'identity', parameters('managedIdentityId'))), null())]", + "registries": null, "ingress": "[if(parameters('enableIngress'), createObject('external', true(), 'transport', 'auto', 'allowInsecure', true(), 'corsPolicy', if(greater(length(parameters('allowedOrigins')), 0), createObject('allowedOrigins', parameters('allowedOrigins'), 'allowedMethods', createArray('GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'), 'allowedHeaders', createArray('Authorization', 'Content-Type', '*')), null())), null())]" }, "template": { @@ -2822,9 +2718,6 @@ }, "aiServiceId": { "value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, resourceGroup().name), 'Microsoft.Resources/deployments', 'deploy_ai_foundry'), '2022-09-01').outputs.aiServicesId.value]" - }, - "containerRegistryReaderPrincipalId": { - "value": "[reference(resourceId('Microsoft.Resources/deployments', 'deploy_container_app_env'), '2022-09-01').outputs.containerRegistryReaderPrincipalId.value]" } }, "template": { @@ -2834,7 +2727,7 @@ "_generator": { "name": "bicep", "version": "0.36.1.42791", - "templateHash": "4418232655579357592" + "templateHash": "1992580664978730799" } }, "parameters": { @@ -2861,9 +2754,6 @@ }, "aiServiceId": { "type": "string" - }, - "containerRegistryReaderPrincipalId": { - "type": "string" } }, "resources": [ @@ -2963,15 +2853,6 @@ "roleDefinitionId": "[resourceId('Microsoft.Authorization/roleDefinitions', 'a97b65f3-24c7-4388-baec-2e87135dc908')]", "principalType": "ServicePrincipal" } - }, - { - "type": "Microsoft.Authorization/roleAssignments", - "apiVersion": "2022-04-01", - "name": "[guid(parameters('containerRegistryReaderPrincipalId'), 'acrpull')]", - "properties": { - "roleDefinitionId": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d')]", - "principalId": "[parameters('containerRegistryReaderPrincipalId')]" - } } ] } @@ -2979,7 +2860,6 @@ "dependsOn": [ "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, resourceGroup().name), 'Microsoft.Resources/deployments', 'deploy_ai_foundry')]", "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, resourceGroup().name), 'Microsoft.Resources/deployments', 'deploy_app_config_service')]", - "[resourceId('Microsoft.Resources/deployments', 'deploy_container_app_env')]", "[resourceId('Microsoft.Resources/deployments', 'deploy_container_app_api_web')]", "[resourceId('Microsoft.Resources/deployments', 'deploy_storage_account')]" ] @@ -3000,7 +2880,9 @@ "location": { "value": "[parameters('secondaryLocation')]" }, - "azureContainerRegistry": "[if(equals(variables('useLocalBuildLower'), 'true'), createObject('value', reference(resourceId('Microsoft.Resources/deployments', 'deploy_container_registry'), '2022-09-01').outputs.acrEndpoint.value), createObject('value', variables('containerImageEndPoint')))]", + "azureContainerRegistry": { + "value": "[variables('containerImageEndPoint')]" + }, "appConfigEndPoint": { "value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, resourceGroup().name), 'Microsoft.Resources/deployments', 'deploy_app_config_service'), '2022-09-01').outputs.appConfigEndpoint.value]" }, @@ -3034,9 +2916,6 @@ "maxReplicaContainerWeb": { "value": "[parameters('maxReplicaContainerWeb')]" }, - "useLocalBuild": { - "value": "[variables('useLocalBuildLower')]" - }, "imageTag": { "value": "[parameters('imageTag')]" } @@ -3048,7 +2927,7 @@ "_generator": { "name": "bicep", "version": "0.36.1.42791", - "templateHash": "9208787367229886695" + "templateHash": "10338800926086953929" } }, "parameters": { @@ -3121,10 +3000,6 @@ "containerRegistryReaderId": { "type": "string" }, - "useLocalBuild": { - "type": "string", - "defaultValue": "false" - }, "imageTag": { "type": "string" } @@ -3444,9 +3319,6 @@ }, "maxReplicas": { "value": "[parameters('maxReplicaContainerApp')]" - }, - "useLocalBuild": { - "value": "[parameters('useLocalBuild')]" } }, "template": { @@ -3456,7 +3328,7 @@ "_generator": { "name": "bicep", "version": "0.36.1.42791", - "templateHash": "13562163699289922411" + "templateHash": "8984863566776850276" } }, "parameters": { @@ -3504,10 +3376,6 @@ "maxReplicas": { "type": "int", "defaultValue": 1 - }, - "useLocalBuild": { - "type": "string", - "defaultValue": "false" } }, "resources": [ @@ -3527,7 +3395,7 @@ "environmentId": "[parameters('containerEnvId')]", "workloadProfileName": "Consumption", "configuration": { - "registries": "[if(equals(parameters('useLocalBuild'), 'true'), createArray(createObject('server', parameters('azureContainerRegistry'), 'identity', parameters('managedIdentityId'))), null())]", + "registries": null, "ingress": "[if(parameters('enableIngress'), createObject('external', true(), 'transport', 'auto', 'allowInsecure', true(), 'corsPolicy', if(greater(length(parameters('allowedOrigins')), 0), createObject('allowedOrigins', parameters('allowedOrigins'), 'allowedMethods', createArray('GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'), 'allowedHeaders', createArray('Authorization', 'Content-Type', '*')), null())), null())]" }, "template": { @@ -3624,9 +3492,6 @@ }, "maxReplicas": { "value": "[parameters('maxReplicaContainerApi')]" - }, - "useLocalBuild": { - "value": "[parameters('useLocalBuild')]" } }, "template": { @@ -3636,7 +3501,7 @@ "_generator": { "name": "bicep", "version": "0.36.1.42791", - "templateHash": "13562163699289922411" + "templateHash": "8984863566776850276" } }, "parameters": { @@ -3684,10 +3549,6 @@ "maxReplicas": { "type": "int", "defaultValue": 1 - }, - "useLocalBuild": { - "type": "string", - "defaultValue": "false" } }, "resources": [ @@ -3707,7 +3568,7 @@ "environmentId": "[parameters('containerEnvId')]", "workloadProfileName": "Consumption", "configuration": { - "registries": "[if(equals(parameters('useLocalBuild'), 'true'), createArray(createObject('server', parameters('azureContainerRegistry'), 'identity', parameters('managedIdentityId'))), null())]", + "registries": null, "ingress": "[if(parameters('enableIngress'), createObject('external', true(), 'transport', 'auto', 'allowInsecure', true(), 'corsPolicy', if(greater(length(parameters('allowedOrigins')), 0), createObject('allowedOrigins', parameters('allowedOrigins'), 'allowedMethods', createArray('GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'), 'allowedHeaders', createArray('Authorization', 'Content-Type', '*')), null())), null())]" }, "template": { @@ -3816,9 +3677,6 @@ }, "maxReplicas": { "value": "[parameters('maxReplicaContainerWeb')]" - }, - "useLocalBuild": { - "value": "[parameters('useLocalBuild')]" } }, "template": { @@ -3828,7 +3686,7 @@ "_generator": { "name": "bicep", "version": "0.36.1.42791", - "templateHash": "13562163699289922411" + "templateHash": "8984863566776850276" } }, "parameters": { @@ -3876,10 +3734,6 @@ "maxReplicas": { "type": "int", "defaultValue": 1 - }, - "useLocalBuild": { - "type": "string", - "defaultValue": "false" } }, "resources": [ @@ -3899,7 +3753,7 @@ "environmentId": "[parameters('containerEnvId')]", "workloadProfileName": "Consumption", "configuration": { - "registries": "[if(equals(parameters('useLocalBuild'), 'true'), createArray(createObject('server', parameters('azureContainerRegistry'), 'identity', parameters('managedIdentityId'))), null())]", + "registries": null, "ingress": "[if(parameters('enableIngress'), createObject('external', true(), 'transport', 'auto', 'allowInsecure', true(), 'corsPolicy', if(greater(length(parameters('allowedOrigins')), 0), createObject('allowedOrigins', parameters('allowedOrigins'), 'allowedMethods', createArray('GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'), 'allowedHeaders', createArray('Authorization', 'Content-Type', '*')), null())), null())]" }, "template": { @@ -3985,7 +3839,6 @@ "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, resourceGroup().name), 'Microsoft.Resources/deployments', 'deploy_app_config_service')]", "[resourceId('Microsoft.Resources/deployments', 'deploy_container_app_env')]", "[resourceId('Microsoft.Resources/deployments', 'deploy_container_app_api_web')]", - "[resourceId('Microsoft.Resources/deployments', 'deploy_container_registry')]", "[resourceId('Microsoft.Resources/deployments', 'deploy_role_assignments')]" ] } @@ -4003,9 +3856,25 @@ "type": "string", "value": "[reference(resourceId('Microsoft.Resources/deployments', 'deploy_container_app_api_web'), '2022-09-01').outputs.containweAppWebEndPoint.value]" }, + "CONTAINER_APP_NAME": { + "type": "string", + "value": "[reference(resourceId('Microsoft.Resources/deployments', 'deploy_container_app_api_web'), '2022-09-01').outputs.containerAppName.value]" + }, "CONTAINER_API_APP_FQDN": { "type": "string", "value": "[reference(resourceId('Microsoft.Resources/deployments', 'deploy_container_app_api_web'), '2022-09-01').outputs.containweAppApiEndPoint.value]" + }, + "CONTAINER_APP_USER_IDENTITY_ID": { + "type": "string", + "value": "[reference(resourceId('Microsoft.Resources/deployments', 'deploy_container_app_env'), '2022-09-01').outputs.containerRegistryReaderId.value]" + }, + "CONTAINER_APP_USER_PRINCIPAL_ID": { + "type": "string", + "value": "[reference(resourceId('Microsoft.Resources/deployments', 'deploy_container_app_env'), '2022-09-01').outputs.containerRegistryReaderPrincipalId.value]" + }, + "AZURE_ENV_IMAGETAG": { + "type": "string", + "value": "[parameters('imageTag')]" } } } \ No newline at end of file diff --git a/infra/main.parameters.json b/infra/main.parameters.json new file mode 100644 index 00000000..c38f5aa2 --- /dev/null +++ b/infra/main.parameters.json @@ -0,0 +1,33 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "environmentName": { + "value": "${AZURE_ENV_NAME}" + }, + "secondaryLocation": { + "value": "${AZURE_ENV_SECONDARY_LOCATION}" + }, + "contentUnderstandingLocation": { + "value": "${AZURE_ENV_CU_LOCATION}" + }, + "deploymentType": { + "value": "${AZURE_ENV_MODEL_DEPLOYMENT_TYPE}" + }, + "gptModelName": { + "value": "${AZURE_ENV_MODEL_NAME}" + }, + "gptModelVersion": { + "value": "${AZURE_ENV_MODEL_VERSION}" + }, + "gptDeploymentCapacity": { + "value": "${AZURE_ENV_MODEL_CAPACITY}" + }, + "imageTag": { + "value": "latest" + }, + "existingLogAnalyticsWorkspaceId": { + "value": "${AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID}" + } + } +} diff --git a/infra/scripts/docker-build.ps1 b/infra/scripts/docker-build.ps1 index 8a0816d3..00920edc 100644 --- a/infra/scripts/docker-build.ps1 +++ b/infra/scripts/docker-build.ps1 @@ -1,65 +1,13 @@ -# Define script parameters -param ( - [string]$AZURE_SUBSCRIPTION_ID, - [string]$ENV_NAME, - [string]$AZURE_LOCATION, - [string]$AZURE_RESOURCE_GROUP, - [string]$USE_LOCAL_BUILD, - [string]$AZURE_ENV_IMAGETAG -) - -# Convert USE_LOCAL_BUILD to Boolean -$USE_LOCAL_BUILD = if ($USE_LOCAL_BUILD -match "^(?i:true)$") { $true } else { $false } - -if ([string]::IsNullOrEmpty($AZURE_ENV_IMAGETAG)) { - $AZURE_ENV_IMAGETAG = "latest" -} - -# Validate required parameters -if (-not $AZURE_SUBSCRIPTION_ID -or -not $ENV_NAME -or -not $AZURE_LOCATION -or -not $AZURE_RESOURCE_GROUP) { - Write-Error "Missing required arguments. Usage: docker-build.ps1 " - exit 1 -} - -if ($USE_LOCAL_BUILD -eq $false) { - Write-Output "Local Build not enabled. Using prebuilt image." - exit 0 -} - -Write-Output "Local Build enabled. Starting build process." - -# Set Azure subscription -az account set --subscription "$AZURE_SUBSCRIPTION_ID" -if ($LASTEXITCODE -ne 0) { - Write-Error "Failed to set Azure subscription." - exit 1 -} - -# Deploy container registry -Write-Host "Deploying container registry in location: $AZURE_LOCATION" -$OUTPUTS = az deployment group create --resource-group $AZURE_RESOURCE_GROUP --template-file "./infra/deploy_container_registry.bicep" --parameters environmentName=$ENV_NAME --query "properties.outputs" --output json | ConvertFrom-Json -# Extract ACR name and endpoint -$ACR_NAME = $OUTPUTS.createdAcrName.value -$ACR_ENDPOINT = $OUTPUTS.acrEndpoint.value - -Write-Host "Extracted ACR Name: $ACR_NAME" -Write-Host "Extracted ACR Endpoint: $ACR_ENDPOINT" - -# Store outputs in a .env file -Set-Content -Path .env -Value "ACR_NAME=$ACR_NAME`nACR_ENDPOINT=$ACR_ENDPOINT" - -# Set ACR details as environment variables in AZD -azd env set ACR_NAME $ACR_NAME -azd env set ACR_ENDPOINT $ACR_ENDPOINT - -Write-Host "Saved ACR details to AZD environment variables." +# Get all environment values +$envValues = azd env get-values --output json | ConvertFrom-Json # Define function to build and push Docker images function Build-And-Push-Image { param ( [string]$IMAGE_NAME, - [string]$BUILD_PATH + [string]$BUILD_PATH, + [string]$CONTAINER_APP_NAME ) $IMAGE_URI = "$ACR_NAME.azurecr.io/$($IMAGE_NAME):$AZURE_ENV_IMAGETAG" @@ -79,8 +27,104 @@ function Build-And-Push-Image { } Write-Host "Docker image pushed successfully: $IMAGE_URI" + + if($CONTAINER_APP_NAME) + { + Write-Host "Updating the Container app registry server & image" + az containerapp registry set --name $CONTAINER_APP_NAME --resource-group $AZURE_RESOURCE_GROUP --server "$ACR_NAME.azurecr.io" --identity $CONTAINER_APP_USER_IDENTITY_ID --only-show-errors + az containerapp update --name $CONTAINER_APP_NAME --resource-group $AZURE_RESOURCE_GROUP --image $IMAGE_URI --only-show-errors + Write-Host "Updated the registry for Container: $CONTAINER_APP_NAME" + } +} + +function Ensure-AzLogin { + try { + $accountInfo = az account show --only-show-errors | ConvertFrom-Json + Write-Host "Already logged in as: $($accountInfo.user.name)" + } catch { + Write-Host "No active Azure session found. Logging in..." + az login --only-show-errors | Out-Null + + if ($LASTEXITCODE -ne 0) { + Write-Error "Azure login failed." + exit 1 + } + + # Set Azure subscription + az account set --subscription "$AZURE_SUBSCRIPTION_ID" + if ($LASTEXITCODE -ne 0) { + Write-Error "Failed to set Azure subscription." + exit 1 + } + } } +# Validate and fetch required parameters from azd env if missing +function Get-AzdEnvValueOrDefault { + param ( + [Parameter(Mandatory = $true)] + [string]$KeyName, + + [Parameter(Mandatory = $false)] + [string]$DefaultValue = "", + + [Parameter(Mandatory = $false)] + [bool]$Required = $false + ) + + # Check if key exists + if ($envValues.PSObject.Properties.Name -contains $KeyName) { + return $envValues.$KeyName + } + + # Key doesn't exist + if ($Required) { + Write-Error "Required environment key '$KeyName' not found in azd environment." + exit 1 + } else { + return $DefaultValue + } +} + +# Read the required details from Bicep deployment output +$AZURE_SUBSCRIPTION_ID = Get-AzdEnvValueOrDefault -KeyName "AZURE_SUBSCRIPTION_ID" -Required $true +$ENV_NAME = Get-AzdEnvValueOrDefault -KeyName "AZURE_ENV_NAME" -Required $true +$CONTAINER_APP_USER_IDENTITY_ID = Get-AzdEnvValueOrDefault -KeyName "CONTAINER_APP_USER_IDENTITY_ID" -Required $true +$AZURE_RESOURCE_GROUP = Get-AzdEnvValueOrDefault -KeyName "AZURE_RESOURCE_GROUP" -Required $true +$CONTAINER_APP_USER_PRINCIPAL_ID = Get-AzdEnvValueOrDefault -KeyName "CONTAINER_APP_USER_PRINCIPAL_ID" -Required $true +$AZURE_ENV_IMAGETAG = Get-AzdEnvValueOrDefault -KeyName "AZURE_ENV_IMAGETAG" -DefaultValue "latest" +$CONTAINER_WEB_APP_NAME=Get-AzdEnvValueOrDefault -KeyName "CONTAINER_WEB_APP_NAME" -Required $true +$CONTAINER_API_APP_NAME=Get-AzdEnvValueOrDefault -KeyName "CONTAINER_API_APP_NAME" -Required $true +$CONTAINER_APP_NAME=Get-AzdEnvValueOrDefault -KeyName "CONTAINER_APP_NAME" -Required $true + +# Export the variables for later use +Write-Host "Using the following parameters:" +Write-Host "AZURE_SUBSCRIPTION_ID = $AZURE_SUBSCRIPTION_ID" +Write-Host "ENV_NAME = $ENV_NAME" +Write-Host "AZURE_RESOURCE_GROUP = $AZURE_RESOURCE_GROUP" +Write-Host "AZURE_ENV_IMAGETAG = $AZURE_ENV_IMAGETAG" + +Ensure-AzLogin + +Write-Output "Starting build process." + +# Deploy container registry +Write-Host "Deploying container registry" +$OUTPUTS = az deployment group create --resource-group $AZURE_RESOURCE_GROUP --template-file "./infra/deploy_container_registry.bicep" --parameters environmentName=$ENV_NAME acrPullPrincipalIds="['$($CONTAINER_APP_USER_PRINCIPAL_ID)']" --query "properties.outputs" --output json | ConvertFrom-Json + +# Extract ACR name and endpoint +$ACR_NAME = $OUTPUTS.createdAcrName.value +$ACR_ENDPOINT = $OUTPUTS.acrEndpoint.value + +Write-Host "Extracted ACR Name: $ACR_NAME" +Write-Host "Extracted ACR Endpoint: $ACR_ENDPOINT" + +# Set ACR details as environment variables in AZD +azd env set ACR_NAME $ACR_NAME +azd env set ACR_ENDPOINT $ACR_ENDPOINT + +Write-Host "Saved ACR details to AZD environment variables." + # Log in to Azure Container Registry Write-Host "Logging into Azure Container Registry: $ACR_NAME" az acr login -n $ACR_NAME @@ -90,8 +134,8 @@ if ($LASTEXITCODE -ne 0) { } # Build and push images -Build-And-Push-Image "contentprocessor" ".\src\ContentProcessor\" -Build-And-Push-Image "contentprocessorapi" ".\src\ContentProcessorAPI\" -Build-And-Push-Image "contentprocessorweb" ".\src\ContentProcessorWeb\" +Build-And-Push-Image "contentprocessor" ".\src\ContentProcessor\" $CONTAINER_APP_NAME +Build-And-Push-Image "contentprocessorapi" ".\src\ContentProcessorAPI\" $CONTAINER_API_APP_NAME +Build-And-Push-Image "contentprocessorweb" ".\src\ContentProcessorWeb\" $CONTAINER_WEB_APP_NAME Write-Host "All Docker images built and pushed successfully." diff --git a/infra/scripts/docker-build.sh b/infra/scripts/docker-build.sh index 3c080a9d..7302772a 100644 --- a/infra/scripts/docker-build.sh +++ b/infra/scripts/docker-build.sh @@ -1,88 +1,111 @@ #!/bin/bash -echo "In shell script" - -echo $1 -echo $2 -echo $3 -echo $4 -echo $5 -echo $6 - -# Check if the required arguments are provided -if [ "$#" -ne 6 ]; then - echo "Usage: docker-build.sh " - exit 1 -fi - -AZURE_SUBSCRIPTION_ID=$1 -ENV_NAME=$2 -AZURE_LOCATION=$3 -AZURE_RESOURCE_GROUP=$4 -USE_LOCAL_BUILD=$5 -AZURE_ENV_IMAGETAG=$6 - -USE_LOCAL_BUILD=$(echo "$USE_LOCAL_BUILD" | grep -iq "^true$" && echo "true" || echo "false") - -AZURE_ENV_IMAGETAG=${AZURE_ENV_IMAGETAG:-latest} - -if [ "$USE_LOCAL_BUILD" = "true" ]; then - echo "Local Build enabled. Starting build process." - az account set --subscription "$AZURE_SUBSCRIPTION_ID" - - # Deploy container registry - echo "Deploying container registry in location: $AZURE_LOCATION" - OUTPUTS=$(az deployment group create --resource-group "$AZURE_RESOURCE_GROUP" \ - --template-file "./infra/deploy_container_registry.bicep" \ - --parameters environmentName="$ENV_NAME" --query "properties.outputs" --output json) - - ACR_NAME=$(echo "$OUTPUTS" | jq -r '.createdAcrName.value') - ACR_ENDPOINT=$(echo "$OUTPUTS" | jq -r '.acrEndpoint.value') - - echo "Extracted ACR Name: $ACR_NAME" - echo "Extracted ACR Endpoint: $ACR_ENDPOINT" - - # Store outputs in a .env file - echo -e "ACR_NAME=$ACR_NAME\nACR_ENDPOINT=$ACR_ENDPOINT" > .env +set -e - # Set AZD environment variables - azd env set ACR_NAME "$ACR_NAME" - azd env set ACR_ENDPOINT "$ACR_ENDPOINT" +# Get all environment values +echo "Fetching environment values from azd..." +ENV_VALUES_JSON=$(azd env get-values --output json) - echo "Saved ACR details to AZD environment variables." - echo "Deployed container registry in location." +get_azd_env_value_or_default() { + local key="$1" + local default="$2" + local required="${3:-false}" - # Construct full image names - CONTENTPROCESSOR_IMAGE_URI="$ACR_NAME.azurecr.io/contentprocessor:$AZURE_ENV_IMAGETAG" - CONTENTPROCESSORAPI_IMAGE_URI="$ACR_NAME.azurecr.io/contentprocessorapi:$AZURE_ENV_IMAGETAG" - CONTENTPROCESSORWEB_IMAGE_URI="$ACR_NAME.azurecr.io/contentprocessorweb:$AZURE_ENV_IMAGETAG" + value=$(azd env get-value "$key" 2>/dev/null || echo "") - # Azure login - echo "Logging into Azure Container Registry: $ACR_NAME" - if ! az acr login -n "$ACR_NAME"; then - echo "Failed to log in to ACR" - exit 1 + if [ -z "$value" ]; then + if [ "$required" = true ]; then + echo "❌ Required environment key '$key' not found." >&2 + exit 1 + else + value="$default" + fi fi - # Build and push Docker images - for service in "ContentProcessor" "ContentProcessorAPI" "ContentProcessorWeb"; do - IMAGE_VAR_NAME="${service^^}_IMAGE_URI" - IMAGE_URI=${!IMAGE_VAR_NAME} + echo "$value" +} +# Required env variables +AZURE_SUBSCRIPTION_ID=$(get_azd_env_value_or_default "AZURE_SUBSCRIPTION_ID" "" true) +ENV_NAME=$(get_azd_env_value_or_default "AZURE_ENV_NAME" "" true) +CONTAINER_APP_USER_IDENTITY_ID=$(get_azd_env_value_or_default "CONTAINER_APP_USER_IDENTITY_ID" "" true) +AZURE_RESOURCE_GROUP=$(get_azd_env_value_or_default "AZURE_RESOURCE_GROUP" "" true) +CONTAINER_APP_USER_PRINCIPAL_ID=$(get_azd_env_value_or_default "CONTAINER_APP_USER_PRINCIPAL_ID" "" true) +AZURE_ENV_IMAGETAG=$(get_azd_env_value_or_default "AZURE_ENV_IMAGETAG" "latest" false) +CONTAINER_WEB_APP_NAME=$(get_azd_env_value_or_default "CONTAINER_WEB_APP_NAME" "" true) +CONTAINER_API_APP_NAME=$(get_azd_env_value_or_default "CONTAINER_API_APP_NAME" "" true) +CONTAINER_APP_NAME=$(get_azd_env_value_or_default "CONTAINER_APP_NAME" "" true) + + +echo "Using the following parameters:" +echo "AZURE_SUBSCRIPTION_ID = $AZURE_SUBSCRIPTION_ID" +echo "ENV_NAME = $ENV_NAME" +echo "AZURE_RESOURCE_GROUP = $AZURE_RESOURCE_GROUP" +echo "AZURE_ENV_IMAGETAG = $AZURE_ENV_IMAGETAG" + +# Ensure Azure login +echo "Checking Azure login status..." +if ! az account show --only-show-errors &>/dev/null; then + echo "No active Azure session found. Logging in..." + az login --only-show-errors + az account set --subscription "$AZURE_SUBSCRIPTION_ID" +fi - echo "Building Docker image: $IMAGE_URI" - if ! docker build "./src/$service/." --no-cache -t "$IMAGE_URI"; then - echo "Failed to build Docker image" - exit 1 - fi +# Deploy container registry +echo "Deploying container registry..." +DEPLOY_OUTPUT=$(az deployment group create \ + --resource-group "$AZURE_RESOURCE_GROUP" \ + --template-file "./infra/deploy_container_registry.bicep" \ + --parameters environmentName="$ENV_NAME" acrPullPrincipalIds="['$CONTAINER_APP_USER_PRINCIPAL_ID']" \ + --query "properties.outputs" \ + --output json) + +ACR_NAME=$(echo "$DEPLOY_OUTPUT" | jq -r '.createdAcrName.value') +ACR_ENDPOINT=$(echo "$DEPLOY_OUTPUT" | jq -r '.acrEndpoint.value') + +echo "Extracted ACR Name: $ACR_NAME" +echo "Extracted ACR Endpoint: $ACR_ENDPOINT" + +azd env set ACR_NAME "$ACR_NAME" +azd env set ACR_ENDPOINT "$ACR_ENDPOINT" + +echo "Logging into ACR..." +az acr login -n "$ACR_NAME" + +# Build and push function +build_and_push_image() { + IMAGE_NAME="$1" + BUILD_PATH="$2" + CONTAINER_APP="$3" + + IMAGE_URI="$ACR_NAME.azurecr.io/$IMAGE_NAME:$AZURE_ENV_IMAGETAG" + echo "Building image: $IMAGE_URI" + docker build "$BUILD_PATH" --no-cache -t "$IMAGE_URI" + + echo "Pushing image: $IMAGE_URI" + docker push "$IMAGE_URI" + + if [ -n "$CONTAINER_APP" ]; then + echo "Updating container app: $CONTAINER_APP" + az containerapp registry set \ + --name "$CONTAINER_APP" \ + --resource-group "$AZURE_RESOURCE_GROUP" \ + --server "$ACR_NAME.azurecr.io" \ + --identity "$CONTAINER_APP_USER_IDENTITY_ID" \ + --only-show-errors + + az containerapp update \ + --name "$CONTAINER_APP" \ + --resource-group "$AZURE_RESOURCE_GROUP" \ + --image "$IMAGE_URI" \ + --only-show-errors + + echo "Updated registry for container app: $CONTAINER_APP" + fi +} - echo "Pushing Docker image to ACR: $IMAGE_URI" - if ! docker push "$IMAGE_URI"; then - echo "Failed to push Docker image" - exit 1 - fi +# Build and push all images +build_and_push_image "contentprocessor" "./src/ContentProcessor/" "$CONTAINER_APP_NAME" +build_and_push_image "contentprocessorapi" "./src/ContentProcessorAPI/" "$CONTAINER_API_APP_NAME" +build_and_push_image "contentprocessorweb" "./src/ContentProcessorWeb/" "$CONTAINER_WEB_APP_NAME" - echo "Docker image pushed successfully: $IMAGE_URI" - done -else - echo "Local Build not enabled. Using prebuilt image." -fi +echo "All Docker images built and pushed successfully." From 46bfe0f907abff04d8f723c3016d9be09c8ff842 Mon Sep 17 00:00:00 2001 From: Prajwal D C Date: Wed, 25 Jun 2025 22:16:55 +0530 Subject: [PATCH 2/3] docs: Fomating deployment guide --- docs/DeploymentGuide.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/DeploymentGuide.md b/docs/DeploymentGuide.md index f09fb732..8848e80a 100644 --- a/docs/DeploymentGuide.md +++ b/docs/DeploymentGuide.md @@ -180,7 +180,7 @@ Once you've opened the project in [Codespaces](#github-codespaces), [Dev Contain ## Post Deployment Steps 1. Optional: Publishing Local Build Container to Azure Container Registry -If you need to rebuild the source code and push the updated container to the deployed Azure Container Registry, follow these steps: + If you need to rebuild the source code and push the updated container to the deployed Azure Container Registry, follow these steps: - **Linux/macOS**: ```bash @@ -194,9 +194,9 @@ If you need to rebuild the source code and push the updated container to the dep .\docker-build.ps1 ``` -This will create a new Azure Container Registry, rebuild the source code, package it into a container, and push it to the Container Registry created. + This will create a new Azure Container Registry, rebuild the source code, package it into a container, and push it to the Container Registry created. -1. **Register Schema Files** +2. **Register Schema Files** > Want to customize the schemas for your own documents? [Learn more about adding your own schemas here.](./CustomizeSchemaData.md) @@ -226,7 +226,7 @@ This will create a new Azure Container Registry, rebuild the source code, packag - **Verify Results** ![schema file registration](./images/SchemaFileRegistration.png) -2. **Import Sample Data** +3. **Import Sample Data** - Grab the Schema IDs for Invoice and Property Damage Claim Form's Schema from first step - Move to the folder location to samples in ContentProcessorApi - [/src/ContentProcessorApi/samples/](/src/ContentProcessorApi/samples/) - Execute the script with Schema IDs From 80ffee3dede72a8ac4e1a5bd0cbfe28b997dae54 Mon Sep 17 00:00:00 2001 From: Prajwal-Microsoft Date: Wed, 25 Jun 2025 21:12:35 +0000 Subject: [PATCH 3/3] fix: Relativ path issues fixed --- infra/scripts/docker-build.ps1 | 17 +++++++++++++---- infra/scripts/docker-build.sh | 13 +++++++++---- 2 files changed, 22 insertions(+), 8 deletions(-) mode change 100644 => 100755 infra/scripts/docker-build.sh diff --git a/infra/scripts/docker-build.ps1 b/infra/scripts/docker-build.ps1 index 00920edc..4af1ab6c 100644 --- a/infra/scripts/docker-build.ps1 +++ b/infra/scripts/docker-build.ps1 @@ -2,6 +2,15 @@ # Get all environment values $envValues = azd env get-values --output json | ConvertFrom-Json +# Full path to this script's folder +$ScriptDir = $PSScriptRoot + +# Resolve relative paths based on the script location +$TemplateFile = Join-Path $ScriptDir "..\deploy_container_registry.bicep" +$ContentProcessorPath = Join-Path $ScriptDir "..\..\src\ContentProcessor" +$ContentApiPath = Join-Path $ScriptDir "..\..\src\ContentProcessorAPI" +$ContentWebPath = Join-Path $ScriptDir "..\..\src\ContentProcessorWeb" + # Define function to build and push Docker images function Build-And-Push-Image { param ( @@ -110,7 +119,7 @@ Write-Output "Starting build process." # Deploy container registry Write-Host "Deploying container registry" -$OUTPUTS = az deployment group create --resource-group $AZURE_RESOURCE_GROUP --template-file "./infra/deploy_container_registry.bicep" --parameters environmentName=$ENV_NAME acrPullPrincipalIds="['$($CONTAINER_APP_USER_PRINCIPAL_ID)']" --query "properties.outputs" --output json | ConvertFrom-Json +$OUTPUTS = az deployment group create --resource-group $AZURE_RESOURCE_GROUP --template-file "$TemplateFile" --parameters environmentName=$ENV_NAME acrPullPrincipalIds="['$($CONTAINER_APP_USER_PRINCIPAL_ID)']" --query "properties.outputs" --output json | ConvertFrom-Json # Extract ACR name and endpoint $ACR_NAME = $OUTPUTS.createdAcrName.value @@ -134,8 +143,8 @@ if ($LASTEXITCODE -ne 0) { } # Build and push images -Build-And-Push-Image "contentprocessor" ".\src\ContentProcessor\" $CONTAINER_APP_NAME -Build-And-Push-Image "contentprocessorapi" ".\src\ContentProcessorAPI\" $CONTAINER_API_APP_NAME -Build-And-Push-Image "contentprocessorweb" ".\src\ContentProcessorWeb\" $CONTAINER_WEB_APP_NAME +Build-And-Push-Image "contentprocessor" "$ContentProcessorPath" $CONTAINER_APP_NAME +Build-And-Push-Image "contentprocessorapi" "$ContentApiPath" $CONTAINER_API_APP_NAME +Build-And-Push-Image "contentprocessorweb" "$ContentWebPath" $CONTAINER_WEB_APP_NAME Write-Host "All Docker images built and pushed successfully." diff --git a/infra/scripts/docker-build.sh b/infra/scripts/docker-build.sh old mode 100644 new mode 100755 index 7302772a..9e9e8cbc --- a/infra/scripts/docker-build.sh +++ b/infra/scripts/docker-build.sh @@ -6,6 +6,9 @@ set -e echo "Fetching environment values from azd..." ENV_VALUES_JSON=$(azd env get-values --output json) +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +TEMPLATE_FILE="$SCRIPT_DIR/../deploy_container_registry.bicep" + get_azd_env_value_or_default() { local key="$1" local default="$2" @@ -54,7 +57,7 @@ fi echo "Deploying container registry..." DEPLOY_OUTPUT=$(az deployment group create \ --resource-group "$AZURE_RESOURCE_GROUP" \ - --template-file "./infra/deploy_container_registry.bicep" \ + --template-file "$TEMPLATE_FILE" \ --parameters environmentName="$ENV_NAME" acrPullPrincipalIds="['$CONTAINER_APP_USER_PRINCIPAL_ID']" \ --query "properties.outputs" \ --output json) @@ -104,8 +107,10 @@ build_and_push_image() { } # Build and push all images -build_and_push_image "contentprocessor" "./src/ContentProcessor/" "$CONTAINER_APP_NAME" -build_and_push_image "contentprocessorapi" "./src/ContentProcessorAPI/" "$CONTAINER_API_APP_NAME" -build_and_push_image "contentprocessorweb" "./src/ContentProcessorWeb/" "$CONTAINER_WEB_APP_NAME" +build_and_push_image "contentprocessor" "$SCRIPT_DIR/../../src/ContentProcessor/" "$CONTAINER_APP_NAME" + +build_and_push_image "contentprocessorapi" "$SCRIPT_DIR/../../src/ContentProcessorAPI/" "$CONTAINER_API_APP_NAME" + +build_and_push_image "contentprocessorweb" "$SCRIPT_DIR/../../src/ContentProcessorWeb/" "$CONTAINER_WEB_APP_NAME" echo "All Docker images built and pushed successfully."