chore: import upstream snapshot with attribution
CodeQL / Analyze (csharp) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled

This commit is contained in:
wehub-resource-sync
2026-07-13 13:21:23 +08:00
commit b957a53def
5423 changed files with 863745 additions and 0 deletions
@@ -0,0 +1,115 @@
param uniqueId string
param prefix string
param userAssignedIdentityResourceId string
param userAssignedIdentityClientId string
param openAiEndpoint string
param openAiApiKey string
param openAiApiVersion string = '2024-08-01-preview'
param openAiModel string = 'gpt-4o'
param applicationInsightsConnectionString string
param containerRegistry string = '${prefix}acr${uniqueId}'
param location string = resourceGroup().location
param logAnalyticsWorkspaceName string
param apiAppExists bool
param emptyContainerImage string = 'mcr.microsoft.com/azuredocs/containerapps-helloworld:latest'
param botAppId string
@secure()
param botPassword string
param botTenantId string
resource logAnalyticsWorkspace 'Microsoft.OperationalInsights/workspaces@2023-09-01' existing = {
name: logAnalyticsWorkspaceName
}
// see https://azureossd.github.io/2023/01/03/Using-Managed-Identity-and-Bicep-to-pull-images-with-Azure-Container-Apps/
resource containerAppEnv 'Microsoft.App/managedEnvironments@2023-11-02-preview' = {
name: '${prefix}-containerAppEnv-${uniqueId}'
location: location
identity: {
type: 'UserAssigned'
userAssignedIdentities: {
'${userAssignedIdentityResourceId}': {}
}
}
properties: {
appLogsConfiguration: {
destination: 'log-analytics'
logAnalyticsConfiguration: {
customerId: logAnalyticsWorkspace.properties.customerId
sharedKey: logAnalyticsWorkspace.listKeys().primarySharedKey
}
}
}
}
// When azd passes parameters, it will tell if apps were already created
// In this case, we don't overwrite the existing image
// See https://johnnyreilly.com/using-azd-for-faster-incremental-azure-container-app-deployments-in-azure-devops#the-does-your-service-exist-parameter
module fetchLatestImageApi './fetch-container-image.bicep' = {
name: 'api-app-image'
params: {
exists: apiAppExists
name: '${prefix}-api-${uniqueId}'
}
}
resource apiContainerApp 'Microsoft.App/containerApps@2023-11-02-preview' = {
name: '${prefix}-api-${uniqueId}'
location: location
tags: { 'azd-service-name': 'api' }
identity: {
type: 'UserAssigned'
userAssignedIdentities: {
'${userAssignedIdentityResourceId}': {}
}
}
properties: {
managedEnvironmentId: containerAppEnv.id
configuration: {
activeRevisionsMode: 'Single'
ingress: {
external: true
targetPort: 80
transport: 'auto'
}
registries: [
{
server: '${containerRegistry}.azurecr.io'
identity: userAssignedIdentityResourceId
}
]
}
template: {
scale: {
minReplicas: 1
maxReplicas: 1
}
containers: [
{
name: 'api'
image: apiAppExists ? fetchLatestImageApi.outputs.containers[0].image : emptyContainerImage
resources: {
cpu: 1
memory: '2Gi'
}
env: [
{ name: 'AZURE_CLIENT_ID', value: userAssignedIdentityClientId }
{ name: 'BOT_APP_ID', value: botAppId }
{ name: 'BOT_PASSWORD', value: botPassword }
{ name: 'BOT_TENANT_ID', value: botTenantId }
{ name: 'APPLICATIONINSIGHTS_CONNECTIONSTRING', value: applicationInsightsConnectionString }
{ name: 'APPLICATIONINSIGHTS_SERVICE_NAME', value: 'api' }
{ name: 'AZURE_OPENAI_ENDPOINT', value: openAiEndpoint }
{ name: 'AZURE_OPENAI_CHAT_DEPLOYMENT_NAME', value: openAiModel }
{ name: 'AZURE_OPENAI_API_KEY', value: '' }
{ name: 'AZURE_OPENAI_API_VERSION', value: openAiApiVersion }
]
}
]
}
}
}
output messagesEndpoint string = 'https://${apiContainerApp.properties.configuration.ingress.fqdn}/api/messages'
output manifestUrl string = 'https://${apiContainerApp.properties.configuration.ingress.fqdn}/manifest'
output homeUrl string = 'https://${apiContainerApp.properties.configuration.ingress.fqdn}'
@@ -0,0 +1,29 @@
param uniqueId string
param prefix string
param userAssignedIdentityPrincipalId string
param acrName string = '${prefix}acr${uniqueId}'
param location string = resourceGroup().location
resource acr 'Microsoft.ContainerRegistry/registries@2021-06-01-preview' = {
name: acrName
location: location
sku: {
name: 'Standard' // Choose between Basic, Standard, and Premium based on your needs
}
properties: {
adminUserEnabled: false
}
}
resource acrPullRoleAssignment 'Microsoft.Authorization/roleAssignments@2020-04-01-preview' = {
name: guid(acr.id, userAssignedIdentityPrincipalId, 'acrpull')
scope: acr
properties: {
roleDefinitionId: resourceId('Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d') // Role definition ID for AcrPull
principalId: userAssignedIdentityPrincipalId
principalType: 'ServicePrincipal'
}
}
output acrName string = acrName
output acrEndpoint string = acr.properties.loginServer
@@ -0,0 +1,46 @@
param uniqueId string
param prefix string
@secure()
param userAssignedIdentityPrincipalId string
param location string = resourceGroup().location
param appInsightsName string = '${prefix}-appin-${uniqueId}'
param logAnalyticsWorkspaceName string = '${prefix}-law-${uniqueId}'
// Create or reference an existing Log Analytics Workspace
resource logAnalyticsWorkspace 'Microsoft.OperationalInsights/workspaces@2020-08-01' = {
name: logAnalyticsWorkspaceName
location: location
properties: {
sku: {
name: 'PerGB2018'
}
retentionInDays: 30
}
}
// Create Application Insights resource linked to the Log Analytics Workspace
resource applicationInsights 'Microsoft.Insights/components@2020-02-02-preview' = {
name: appInsightsName
location: location
kind: 'web'
properties: {
Application_Type: 'web'
WorkspaceResourceId: logAnalyticsWorkspace.id
}
}
// Assign "Monitoring Metrics Publisher" role to the Application Insights resource
resource acrPullRoleAssignment 'Microsoft.Authorization/roleAssignments@2020-04-01-preview' = {
name: guid(applicationInsights.id, userAssignedIdentityPrincipalId, 'appinsightsPublisher')
scope: applicationInsights
properties: {
roleDefinitionId: resourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') // Role definition ID for Monitoring Metrics Publisher
principalId: userAssignedIdentityPrincipalId
principalType: 'ServicePrincipal'
}
}
output logAnalyticsWorkspaceId string = logAnalyticsWorkspace.id
output logAnalyticsWorkspaceName string = logAnalyticsWorkspaceName
output applicationInsightsInstrumentationKey string = applicationInsights.properties.InstrumentationKey
output applicationInsightsConnectionString string = applicationInsights.properties.ConnectionString
@@ -0,0 +1,37 @@
param uniqueId string
param prefix string
param messagesEndpoint string
param botAppId string
param botTenantId string
resource bot 'Microsoft.BotService/botServices@2023-09-15-preview' = {
name: '${prefix}bot${uniqueId}'
location: 'global'
sku: {
name: 'F0'
}
kind: 'azurebot'
properties: {
iconUrl: 'https://docs.botframework.com/static/devportal/client/images/bot-framework-default.png'
displayName: '${prefix}bot${uniqueId}'
endpoint: messagesEndpoint
description: 'Bot created by Bicep'
publicNetworkAccess: 'Enabled'
msaAppId: botAppId
msaAppTenantId: botTenantId
msaAppType: 'SingleTenant'
msaAppMSIResourceId: null
schemaTransformationVersion: '1.3'
isStreamingSupported: false
}
}
// Connect the bot service to Microsoft Teams
resource botServiceMsTeamsChannel 'Microsoft.BotService/botServices/channels@2021-03-01' = {
parent: bot
location: 'global'
name: 'MsTeamsChannel'
properties: {
channelName: 'MsTeamsChannel'
}
}
@@ -0,0 +1,8 @@
param exists bool
param name string
resource existingApp 'Microsoft.App/containerApps@2023-05-01' existing = if (exists) {
name: name
}
output containers array = exists ? existingApp.properties.template.containers : []
@@ -0,0 +1,141 @@
targetScope = 'subscription'
@minLength(1)
@maxLength(64)
@description('Name of the environment that can be used as part of naming resource convention')
param environmentName string
@description('The current user ID, to assign RBAC permissions to')
param currentUserId string
// Main deployment parameters
param prefix string = 'copstsk'
@minLength(1)
@description('Primary location for all resources')
param location string
@minLength(1)
@description('Name of the Azure OpenAI resource')
param openAIName string
@minLength(1)
@description('Name of the Azure Resource Group where the OpenAI resource is located')
param openAIResourceGroupName string
@description('Azure Bot app ID')
param botAppId string
@description('Azure Bot app password')
@secure()
param botPassword string
@description('Azure Bot tenant ID')
param botTenantId string
param openAIModel string
param openAIApiVersion string
param apiAppExists bool = false
param runningOnGh string = ''
var tags = {
'azd-env-name': environmentName
}
resource rg 'Microsoft.Resources/resourceGroups@2022-09-01' = {
name: 'rg-${environmentName}'
location: location
tags: tags
}
var uniqueId = uniqueString(rg.id)
var principalType = empty(runningOnGh) ? 'User' : 'ServicePrincipal'
module uami './uami.bicep' = {
name: 'uami'
scope: rg
params: {
uniqueId: uniqueId
prefix: prefix
location: location
}
}
module appin './appin.bicep' = {
name: 'appin'
scope: rg
params: {
uniqueId: uniqueId
prefix: prefix
location: location
userAssignedIdentityPrincipalId: uami.outputs.principalId
}
}
module acrModule './acr.bicep' = {
name: 'acr'
scope: rg
params: {
uniqueId: uniqueId
prefix: prefix
userAssignedIdentityPrincipalId: uami.outputs.principalId
location: location
}
}
module openAI './openAI.bicep' = {
name: 'openAI'
scope: resourceGroup(openAIResourceGroupName)
params: {
openAIName: openAIName
userAssignedIdentityPrincipalId: uami.outputs.principalId
}
}
module aca './aca.bicep' = {
name: 'aca'
scope: rg
params: {
uniqueId: uniqueId
prefix: prefix
userAssignedIdentityResourceId: uami.outputs.identityId
containerRegistry: acrModule.outputs.acrName
location: location
logAnalyticsWorkspaceName: appin.outputs.logAnalyticsWorkspaceName
applicationInsightsConnectionString: appin.outputs.applicationInsightsConnectionString
openAiApiKey: '' // Force ManId, otherwise set openAI.listKeys().key1
openAiEndpoint: openAI.outputs.openAIEndpoint
openAiModel: openAIModel
openAiApiVersion: openAIApiVersion
userAssignedIdentityClientId: uami.outputs.clientId
apiAppExists: apiAppExists
botAppId: botAppId
botPassword: botPassword
botTenantId: botTenantId
}
}
module bot 'bot.bicep' = {
name: 'bot'
scope: rg
params: {
uniqueId: uniqueId
prefix: prefix
botAppId: botAppId
botTenantId: botTenantId
messagesEndpoint: aca.outputs.messagesEndpoint
}
}
// These outputs are copied by azd to .azure/<env name>/.env file
// post provision script will use these values, too
output AZURE_RESOURCE_GROUP string = rg.name
output APPLICATIONINSIGHTS_CONNECTIONSTRING string = appin.outputs.applicationInsightsConnectionString
output AZURE_TENANT_ID string = subscription().tenantId
output AZURE_USER_ASSIGNED_IDENTITY_ID string = uami.outputs.identityId
output AZURE_CONTAINER_REGISTRY_ENDPOINT string = acrModule.outputs.acrEndpoint
output AZURE_OPENAI_MODEL string = openAIModel
output AZURE_OPENAI_ENDPOINT string = openAI.outputs.openAIEndpoint
output AZURE_OPENAI_API_VERSION string = openAIApiVersion
output ENDPOINT_URL string = aca.outputs.messagesEndpoint
output MANIFEST_URL string = aca.outputs.manifestUrl
output HOME_URL string = aca.outputs.homeUrl
output BOT_APP_ID string = botAppId
output BOT_TENANT_ID string = botTenantId
@@ -0,0 +1,42 @@
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"environmentName": {
"value": "${AZURE_ENV_NAME}"
},
"currentUserId": {
"value": "${AZURE_PRINCIPAL_ID}"
},
"runningOnGh": {
"value": "${GITHUB_ACTIONS}"
},
"location": {
"value": "${AZURE_LOCATION}"
},
"openAiName": {
"value": "${AZURE_OPENAI_NAME}"
},
"openAiResourceGroupName": {
"value": "${AZURE_OPENAI_RG}"
},
"openAIModel": {
"value": "${AZURE_OPENAI_MODEL=gpt-4o}"
},
"openAIApiVersion": {
"value": "${AZURE_OPENAI_API_VERSION=2024-08-01-preview}"
},
"apiAppExists": {
"value": "${SERVICE_API_RESOURCE_EXISTS=false}"
},
"botAppId": {
"value": "${BOT_APPID}"
},
"botPassword": {
"value": "${BOT_PASSWORD}"
},
"botTenantId": {
"value": "${BOT_TENANT_ID}"
}
}
}
@@ -0,0 +1,20 @@
targetScope = 'resourceGroup'
param openAIName string
param userAssignedIdentityPrincipalId string
resource openAI 'Microsoft.CognitiveServices/accounts@2022-03-01' existing = {
name: openAIName
}
resource roleAssignment 'Microsoft.Authorization/roleAssignments@2020-04-01-preview' = {
name: guid(openAI.id, userAssignedIdentityPrincipalId, 'Cognitive Services OpenAI User')
scope: openAI
properties: {
roleDefinitionId: resourceId('Microsoft.Authorization/roleDefinitions', '5e0bd9bd-7b93-4f28-af87-19fc36ad61bd') // Role definition ID for Cognitive Services OpenAI User
principalId: userAssignedIdentityPrincipalId
principalType: 'ServicePrincipal'
}
}
output openAIEndpoint string = openAI.properties.endpoint
@@ -0,0 +1,13 @@
param uniqueId string
param prefix string
param location string = resourceGroup().location
param identityName string = '${prefix}uami${uniqueId}'
resource userAssignedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = {
name: identityName
location: location
}
output identityId string = userAssignedIdentity.id
output clientId string = userAssignedIdentity.properties.clientId
output principalId string = userAssignedIdentity.properties.principalId