Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
ce2ef1c
CustomTemplate
UtkarshMishra-Microsoft Oct 29, 2025
3a0e72b
frontend
UtkarshMishra-Microsoft Oct 29, 2025
7f5273d
newFiles
UtkarshMishra-Microsoft Oct 30, 2025
eaa6455
mainfiles
UtkarshMishra-Microsoft Oct 30, 2025
69f8c18
newchange
UtkarshMishra-Microsoft Oct 31, 2025
5621c30
newBicep
UtkarshMishra-Microsoft Oct 31, 2025
ba4c641
portUpdated
UtkarshMishra-Microsoft Nov 3, 2025
5d5efb3
Delete infra/main.json
UtkarshMishra-Microsoft Nov 7, 2025
128912d
readmeUpdated
UtkarshMishra-Microsoft Nov 10, 2025
36dd060
Merge branch 'dev' into customfile
UtkarshMishra-Microsoft Nov 11, 2025
00997f0
docfile
UtkarshMishra-Microsoft Nov 11, 2025
541b085
Merge pull request #40 from microsoft/customfile
Roopan-Microsoft Nov 11, 2025
bdf46fb
different extention file error bug fix
Nov 11, 2025
5d57f57
Network error
Nov 12, 2025
6f83f58
remove retry logic
Nov 13, 2025
be917e6
add createdBy param in ci.yml
Nov 17, 2025
2cace4b
add parameters as prefix
Nov 17, 2025
d9333f6
add created by
Nov 17, 2025
5da4063
Merge branch 'dev' into main-to-dev
Prajwal-Microsoft Nov 20, 2025
950d542
Merge pull request #54 from microsoft/main-to-dev
Prajwal-Microsoft Nov 20, 2025
5c213e2
Merge pull request #47 from microsoft/psl-upload-bug
Roopan-Microsoft Nov 21, 2025
ab9d9a5
fix success message bar
Nov 21, 2025
4201f62
Add guidance for disabling Log Analytics workspace replication before…
Abdul-Microsoft Nov 21, 2025
a9214c0
Merge pull request #55 from microsoft/psl-fix-bar
Roopan-Microsoft Nov 21, 2025
7dd6f76
Merge pull request #56 from microsoft/psl-loganalyticsdeletionguide
Roopan-Microsoft Nov 24, 2025
9fc4caa
Merge pull request #50 from microsoft/psl-fix-validate-template
Roopan-Microsoft Nov 24, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ on:
- main
- dev
- demo
pull_request:
branches:
- dev
schedule:
- cron: '0 9,21 * * *' # Runs at 9:00 AM and 9:00 PM GMT
workflow_dispatch: # Allow manual triggering
Expand Down Expand Up @@ -113,7 +116,8 @@ jobs:
--parameters solutionName=${{env.SOLUTION_PREFIX}} \
--parameters location=${{ env.AZURE_LOCATION }} \
--parameters aiDeploymentLocation=${{ env.AZURE_LOCATION }} \
--parameters azureAiServiceLocation=${{ env.AZURE_LOCATION }}
--parameters azureAiServiceLocation=${{ env.AZURE_LOCATION }} \
--parameters createdBy="pipeline" \


- name: Extract AI Services and Key Vault Names
Expand Down
108 changes: 108 additions & 0 deletions azure_custom.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
# yaml-language-server: $schema=https://raw.githubusercontent.com/Azure/azure-dev/main/schemas/v1.0/azure.yaml.json

# This file contains a developer‑focused Azure Developer CLI configuration. It
# extends the default template by defining three services (backend API,
# processor and frontend) and instructs azd to build container images from
# your local source code. All three services are packaged as container apps
# using the Dockerfiles located in their respective project directories.
# After deployment a post‑deploy hook prints the endpoints of the deployed
# container apps.

name: container-migration-solution-accelerator
metadata:
template: container-migration-solution-accelerator@1.0

requiredVersions:
# Require a recent version of azd that supports the packaging
# functionality used here. Versions less than 1.17.1 had a bug in
# remoteBuild.
azd: ">=1.18.2"

infra:
parameters:
backendImageName: ${SERVICE_BACKEND_IMAGE_NAME}
processorImageName: ${SERVICE_PROCESSOR_IMAGE_NAME}
frontendImageName: ${SERVICE_FRONTEND_IMAGE_NAME}

services:
# Backend API service. This is a Python FastAPI application defined in
# src/backend-api. The azd packaging stage builds a Docker image using
# the Dockerfile in that directory. The image name 'backend-api' is
# combined with the automatically created Azure Container Registry login
# server to form the final image reference.
backend:
project: ./src/backend-api
language: py
host: containerapp
docker:
image: backend-api
remoteBuild: true

# Processor service. This service reads messages from storage queues and
# orchestrates long‑running migrations. It is also packaged as a
# container and deployed to a container app environment. The Dockerfile
# in the src/processor directory defines how the image is built.
processor:
project: ./src/processor
language: py
host: containerapp
docker:
image: processor
remoteBuild: true

# Frontend service. The frontend consists of a React single‑page
# application and a lightweight Python server that serves the compiled
# assets. azd packages the frontend by building a Docker image using
# the Dockerfile in the src/frontend directory and deploys it to a
# container app.
frontend:
project: ./src/frontend
language: py
host: containerapp
docker:
image: frontend
remoteBuild: true

hooks:
# After deployment prints the names and endpoints of the deployed
# container apps. This reproduces the behaviour of the default
# configuration so that developers can easily discover their services.
postdeploy:
posix:
shell: sh
run: |
echo "-----"
echo "🧭 Frontend Container App Details:"
echo "✅ Name: $CONTAINER_FRONTEND_APP_NAME"
echo "🌐 Endpoint: https://$CONTAINER_FRONTEND_APP_FQDN"
echo "🔗 Portal URL: https://portal.azure.com/#resource/subscriptions/$AZURE_SUBSCRIPTION_ID/resourceGroups/$AZURE_RESOURCE_GROUP/providers/Microsoft.App/containerApps/$CONTAINER_FRONTEND_APP_NAME"
echo "-----"
echo "🧭 Backend API Container App Details:"
echo "✅ Name: $CONTAINER_API_APP_NAME"
echo "🌐 Endpoint: https://$CONTAINER_API_APP_FQDN"
echo "🔗 Portal URL: https://portal.azure.com/#resource/subscriptions/$AZURE_SUBSCRIPTION_ID/resourceGroups/$AZURE_RESOURCE_GROUP/providers/Microsoft.App/containerApps/$CONTAINER_API_APP_NAME"
echo "-----"
echo "🧭 Processor Container App Details:"
echo "✅ Name: $SERVICE_PROCESSOR_NAME"
echo "🔗 Portal URL: https://portal.azure.com/#resource/subscriptions/$AZURE_SUBSCRIPTION_ID/resourceGroups/$AZURE_RESOURCE_GROUP/providers/Microsoft.App/containerApps/$SERVICE_PROCESSOR_NAME"
echo "-----"
interactive: true
windows:
shell: pwsh
run: |
Write-Host "-----"
Write-Host "🧭 Frontend Container App Details:"
Write-Host "✅ Name: $env:CONTAINER_FRONTEND_APP_NAME"
Write-Host "🌐 Endpoint: https://$env:CONTAINER_FRONTEND_APP_FQDN"
Write-Host "🔗 Portal URL: https://portal.azure.com/#resource/subscriptions/$env:AZURE_SUBSCRIPTION_ID/resourceGroups/$env:AZURE_RESOURCE_GROUP/providers/Microsoft.App/containerApps/$env:CONTAINER_FRONTEND_APP_NAME" -ForegroundColor Cyan
Write-Host "-----"
Write-Host "🧭 Backend API Container App Details:"
Write-Host "✅ Name: $env:CONTAINER_API_APP_NAME"
Write-Host "🌐 Endpoint: https://$env:CONTAINER_API_APP_FQDN"
Write-Host "🔗 Portal URL: https://portal.azure.com/#resource/subscriptions/$env:AZURE_SUBSCRIPTION_ID/resourceGroups/$env:AZURE_RESOURCE_GROUP/providers/Microsoft.App/containerApps/$env:CONTAINER_API_APP_NAME" -ForegroundColor Cyan
Write-Host "-----"
Write-Host "🧭 Processor Container App Details:"
Write-Host "✅ Name: $env:SERVICE_PROCESSOR_NAME"
Write-Host "🔗 Portal URL: https://portal.azure.com/#resource/subscriptions/$env:AZURE_SUBSCRIPTION_ID/resourceGroups/$env:AZURE_RESOURCE_GROUP/providers/Microsoft.App/containerApps/$env:SERVICE_PROCESSOR_NAME" -ForegroundColor Cyan
Write-Host "-----"
interactive: true
8 changes: 8 additions & 0 deletions docs/DeploymentGuide.md
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,7 @@ After successful deployment:
```shell
azd down
```
> **Note:** If you deployed with `enableRedundancy=true` and Log Analytics workspace replication is enabled, you must first disable replication before running `azd down` else resource group delete will fail. Follow the steps in [Handling Log Analytics Workspace Deletion with Replication Enabled](./LogAnalyticsReplicationDisable.md), wait until replication returns `false`, then run `azd down`.

### Manual Cleanup (if needed)
If deployment fails or you need to clean up manually:
Expand Down Expand Up @@ -430,3 +431,10 @@ azd env get-values
- 🐛 **Issues:** Check [Troubleshooting Guide](./TroubleShootingSteps.md)
- 💬 **Support:** Review [Support Guidelines](../SUPPORT.md)
- 🔧 **Development:** See [Contributing Guide](../CONTRIBUTING.md)

### Deploy Your local changes
To Deploy your local changes rename the below files.

Rename `azure.yaml` to `azure_custom2.yaml` and `azure_custom.yaml` to `azure.yaml`.
Go to `infra` directory
Rename `main.bicep` to `main_custom2.bicep` and `main_custom.bicep` to `main.bicep`. Continue with the [deploying steps](#deploying-with-azd).
28 changes: 28 additions & 0 deletions docs/LogAnalyticsReplicationDisable.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# 🛠 Handling Log Analytics Workspace Deletion with Replication Enabled

If redundancy (replication) is enabled for your Log Analytics workspace, you must disable it before deleting the workspace or resource group. Otherwise, deletion will fail.

## ✅ Steps to Disable Replication Before Deletion
Run the following Azure CLI command. Note: This operation may take about 5 minutes to complete.

```bash
az resource update --ids "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.OperationalInsights/workspaces/{logAnalyticsName}" --set properties.replication.enabled=false
```

Replace:
- `{subscriptionId}` → Your Azure subscription ID
- `{resourceGroupName}` → The name of your resource group
- `{logAnalyticsName}` → The name of your Log Analytics workspace

Optional: Verify replication disabled (should output `false`):
```bash
az resource show --ids "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.OperationalInsights/workspaces/{logAnalyticsName}" --query properties.replication.enabled -o tsv
```

## ✅ After Disabling Replication
You can safely delete:
- The Log Analytics workspace (manual)
- The resource group (manual), or
- All provisioned resources via `azd down`

Return to: [Deployment Guide](./DeploymentGuide.md)
69 changes: 61 additions & 8 deletions infra/main.bicep
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ param azureAiServiceLocation string
'westus3'
])
@description('Required. Azure region for AI model deployment. Should match azureAiServiceLocation for optimal performance.')
#disable-next-line no-unused-params
param aiDeploymentLocation string = azureAiServiceLocation

@description('Optional. The host (excluding https://) of an existing container registry. This is the `loginServer` when using Azure Container Registry.')
Expand Down Expand Up @@ -99,9 +100,12 @@ param cosmosLocation string = 'eastus2'
param existingLogAnalyticsWorkspaceId string = ''

@description('Tag, Created by user name')
param createdBy string = contains(deployer(), 'userPrincipalName')
? split(deployer().userPrincipalName, '@')[0]
: deployer().objectId
param createdBy string = deployer().objectId

// Get the current deployer's information for local debugging permissions
var deployerInfo = deployer()
var deployingUserPrincipalId = deployerInfo.objectId
var deployingUserType = contains(deployerInfo, 'userPrincipalName') ? 'User' : 'ServicePrincipal'

@description('Optional. Resource ID of an existing Foundry project')
param existingFoundryProjectResourceId string = ''
Expand Down Expand Up @@ -469,6 +473,17 @@ module storageAccount 'br/public:avm/res/storage/storage-account:0.20.0' = {
principalId: appIdentity.outputs.principalId
principalType: 'ServicePrincipal'
}
// Add deployer permissions
{
roleDefinitionIdOrName: 'Storage Blob Data Contributor'
principalId: deployingUserPrincipalId
principalType: deployingUserType
}
{
roleDefinitionIdOrName: 'Storage Queue Data Contributor'
principalId: deployingUserPrincipalId
principalType: deployingUserType
}
]
// WAF aligned networking
networkAcls: {
Expand Down Expand Up @@ -655,6 +670,12 @@ module cosmosDb 'br/public:avm/res/document-db/database-account:0.15.0' = {
principalType: 'ServicePrincipal'
roleDefinitionIdOrName: 'DocumentDB Account Contributor'
}
// Add deployer for local debugging
{
principalId: deployingUserPrincipalId
principalType: deployingUserType
roleDefinitionIdOrName: 'DocumentDB Account Contributor'
}
]
// Create custom data plane role definition and assignment
dataPlaneRoleDefinitions: [
Expand All @@ -669,6 +690,8 @@ module cosmosDb 'br/public:avm/res/document-db/database-account:0.15.0' = {
]
assignments: [
{ principalId: appIdentity.outputs.principalId }
// ADD THIS for local debugging support:
{ principalId: deployingUserPrincipalId }
]
}
]
Expand Down Expand Up @@ -699,7 +722,7 @@ module existingAiFoundryAiServicesDeployments 'modules/ai-services-deployments.b
name: take('module.ai-services-model-deployments.${existingAiFoundryAiServices.name}', 64)
scope: resourceGroup(aiFoundryAiServicesSubscriptionId, aiFoundryAiServicesResourceGroupName)
params: {
name: existingAiFoundryAiServices.name
name: aiFoundryAiServicesResourceName // Fix: use variable instead of resource reference
deployments: [
{
name: aiModelDeploymentName
Expand All @@ -715,6 +738,7 @@ module existingAiFoundryAiServicesDeployments 'modules/ai-services-deployments.b
}
]
roleAssignments: [
// Service Principal permissions
{
principalId: appIdentity.outputs.principalId
principalType: 'ServicePrincipal'
Expand All @@ -723,12 +747,23 @@ module existingAiFoundryAiServicesDeployments 'modules/ai-services-deployments.b
{
principalId: appIdentity.outputs.principalId
principalType: 'ServicePrincipal'
roleDefinitionIdOrName: '64702f94-c441-49e6-a78b-ef80e0188fee' // Azure AI Developer
roleDefinitionIdOrName: '64702f94-c441-49e6-a78b-ef80e0188fee'
}
{
principalId: appIdentity.outputs.principalId
principalType: 'ServicePrincipal'
roleDefinitionIdOrName: '53ca6127-db72-4b80-b1b0-d745d6d5456d' // Azure AI User
roleDefinitionIdOrName: '53ca6127-db72-4b80-b1b0-d745d6d5456d'
}
// Deployer permissions
{
principalId: deployingUserPrincipalId
principalType: deployingUserType
roleDefinitionIdOrName: 'Cognitive Services OpenAI Contributor'
}
{
principalId: deployingUserPrincipalId
principalType: deployingUserType
roleDefinitionIdOrName: 'Cognitive Services User'
}
]
}
Expand All @@ -746,6 +781,7 @@ module aiFoundry 'br/public:avm/ptn/ai-ml/ai-foundry:0.4.0' = if(!useExistingAiF
accountName:aiFoundryAiServicesResourceName
allowProjectManagement: true
roleAssignments: [
// Service Principal permissions
{
principalId: appIdentity.outputs.principalId
principalType: 'ServicePrincipal'
Expand All @@ -761,6 +797,17 @@ module aiFoundry 'br/public:avm/ptn/ai-ml/ai-foundry:0.4.0' = if(!useExistingAiF
principalType: 'ServicePrincipal'
roleDefinitionIdOrName: '53ca6127-db72-4b80-b1b0-d745d6d5456d' // Azure AI User
}
// Deployer permissions for local debugging
{
principalId: deployingUserPrincipalId
principalType: deployingUserType
roleDefinitionIdOrName: 'Cognitive Services OpenAI Contributor'
}
{
principalId: deployingUserPrincipalId
principalType: deployingUserType
roleDefinitionIdOrName: 'Cognitive Services User'
}
]
// Remove networking configuration to avoid AML workspace creation issues
networking: enablePrivateNetworking? {
Expand Down Expand Up @@ -791,7 +838,7 @@ module aiFoundry 'br/public:avm/ptn/ai-ml/ai-foundry:0.4.0' = if(!useExistingAiF
}
}

var aiServicesName = useExistingAiFoundryAiProject ? existingAiFoundryAiServices.name : aiFoundry.outputs.aiServicesName
var aiServicesName = useExistingAiFoundryAiProject ? existingAiFoundryAiServices.name : aiFoundryAiServicesResourceName
module appConfiguration 'br/public:avm/res/app-configuration/configuration-store:0.9.1' = {
name: take('avm.res.app-config.store.${solutionSuffix}', 64)
params: {
Expand Down Expand Up @@ -898,6 +945,8 @@ module appConfiguration 'br/public:avm/res/app-configuration/configuration-store
sku: 'Standard'
publicNetworkAccess: 'Enabled'
}
// Add explicit dependency
dependsOn: useExistingAiFoundryAiProject ? [] : [aiFoundry]
}

module avmAppConfigUpdated 'br/public:avm/res/app-configuration/configuration-store:0.6.3' = if (enablePrivateNetworking) {
Expand Down Expand Up @@ -971,7 +1020,7 @@ module containerAppsEnvironment 'br/public:avm/res/app/managed-environment:0.11.
platformReservedDnsIP: '172.17.17.17'
zoneRedundant: (enablePrivateNetworking) ? true : false // Enable zone redundancy if private networking is enabled
infrastructureSubnetResourceId: (enablePrivateNetworking)
? virtualNetwork.outputs.containersSubnetResourceId // Use the container app subnet
? virtualNetwork!.outputs.containersSubnetResourceId // Use the container app subnet
: null // Use the container app subnet
}
}
Expand Down Expand Up @@ -1210,3 +1259,7 @@ output AZURE_SUBSCRIPTION_ID string = subscription().subscriptionId

@description('The Azure resource group name.')
output AZURE_RESOURCE_GROUP string = resourceGroup().name

// Log deployer information for debugging
output deployerObjectId string = deployingUserPrincipalId
output deployerType string = deployingUserType
Loading