Skip to content

Commit

Permalink
Add workflow for azd deployment on GitHub Actions and ADO (#1083)
Browse files Browse the repository at this point in the history
* Configure Azure Developer Pipeline

* Configure Azure Developer Pipeline

* Configure Azure Developer Pipeline

* Configure Azure Developer Pipeline

* Configure Azure Developer Pipeline

* Configure Azure Developer Pipeline

* rev

* rev

* rev

* r

* Configure Azure Developer Pipeline

* Configure Azure Developer Pipeline

* Configure Azure Developer Pipeline

* keep using interactive for CI

* Configure Azure Developer Pipeline

* update for daily azd

* update versions

* Update infra/main.parameters.json

---------

Co-authored-by: Pamela Fox <[email protected]>
  • Loading branch information
vhvb1989 and pamelafox authored Feb 15, 2024
1 parent 88056e1 commit 688e1c4
Show file tree
Hide file tree
Showing 5 changed files with 256 additions and 11 deletions.
88 changes: 88 additions & 0 deletions .azdo/pipelines/azure-dev.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
# Run when commits are pushed to mainline branch (main or master)
# Set this to the mainline branch you are using
trigger:
- main
- master

# Azure Pipelines workflow to deploy to Azure using azd
# To configure required secrets and service connection for connecting to Azure, simply run `azd pipeline config --provider azdo`
# Task "Install azd" needs to install setup-azd extension for azdo - https://marketplace.visualstudio.com/items?itemName=ms-azuretools.azd
# See below for alternative task to install azd if you can't install above task in your organization

pool:
vmImage: ubuntu-latest

steps:
- task: setup-azd@0
displayName: Install azd

# If you can't install above task in your organization, you can comment it and uncomment below task to install azd
# - task: Bash@3
# displayName: Install azd
# inputs:
# targetType: 'inline'
# script: |
# curl -fsSL https://aka.ms/install-azd.sh | bash

# azd delegate auth to az to use service connection with AzureCLI@2
- pwsh: |
azd config set auth.useAzCliAuth "true"
displayName: Configure AZD to Use AZ CLI Authentication.
- task: AzureCLI@2
displayName: Provision Infrastructure
inputs:
# azconnection is the service connection created by azd. You can change it to any service connection you have in your organization.
azureSubscription: azconnection
scriptType: bash
scriptLocation: inlineScript
inlineScript: |
azd provision --no-prompt
env:
AZURE_SUBSCRIPTION_ID: $(AZURE_SUBSCRIPTION_ID)
AZURE_ENV_NAME: $(AZURE_ENV_NAME)
AZURE_LOCATION: $(AZURE_LOCATION)
AZD_INITIAL_ENVIRONMENT_CONFIG: $(AZD_INITIAL_ENVIRONMENT_CONFIG)
AZURE_OPENAI_SERVICE: $(AZURE_OPENAI_SERVICE)
AZURE_OPENAI_RESOURCE_GROUP: $(AZURE_OPENAI_RESOURCE_GROUP)
AZURE_FORMRECOGNIZER_SERVICE: $(AZURE_FORMRECOGNIZER_SERVICE)
AZURE_FORMRECOGNIZER_RESOURCE_GROUP: $(AZURE_FORMRECOGNIZER_RESOURCE_GROUP)
AZURE_FORMRECOGNIZER_SKU: $(AZURE_FORMRECOGNIZER_SKU)
AZURE_SEARCH_INDEX: $(AZURE_SEARCH_INDEX)
AZURE_SEARCH_SERVICE: $(AZURE_SEARCH_SERVICE)
AZURE_SEARCH_SERVICE_RESOURCE_GROUP: $(AZURE_SEARCH_SERVICE_RESOURCE_GROUP)
AZURE_SEARCH_SERVICE_LOCATION: $(AZURE_SEARCH_SERVICE_LOCATION)
AZURE_SEARCH_SERVICE_SKU: $(AZURE_SEARCH_SERVICE_SKU)
AZURE_SEARCH_QUERY_LANGUAGE: $(AZURE_SEARCH_QUERY_LANGUAGE)
AZURE_SEARCH_QUERY_SPELLER: $(AZURE_SEARCH_QUERY_SPELLER)
AZURE_SEARCH_SEMANTIC_RANKER: $(AZURE_SEARCH_SEMANTIC_RANKER)
AZURE_STORAGE_ACCOUNT: $(AZURE_STORAGE_ACCOUNT)
AZURE_STORAGE_RESOURCE_GROUP: $(AZURE_STORAGE_RESOURCE_GROUP)
AZURE_STORAGE_SKU: $(AZURE_STORAGE_SKU)
AZURE_APP_SERVICE_SKU: $(AZURE_APP_SERVICE_SKU)
AZURE_OPENAI_CHATGPT_DEPLOYMENT: $(AZURE_OPENAI_CHATGPT_DEPLOYMENT)
AZURE_OPENAI_EMB_DEPLOYMENT: $(AZURE_OPENAI_EMB_DEPLOYMENT)
OPENAI_HOST: $(OPENAI_HOST)
OPENAI_API_KEY: $(OPENAI_API_KEY)
OPENAI_ORGANIZATION: $(OPENAI_ORGANIZATION)
AZURE_USE_APPLICATION_INSIGHTS: $(AZURE_USE_APPLICATION_INSIGHTS)
USE_VECTORS: $(USE_VECTORS)
USE_GPT4V: $(USE_GPT4V)
AZURE_USE_AUTHENTICATION: $(AZURE_USE_AUTHENTICATION)
AZURE_ENFORCE_ACCESS_CONTROL: $(AZURE_ENFORCE_ACCESS_CONTROL)
AZURE_TENANT_ID: $(AZURE_TENANT_ID)
AZURE_AUTH_TENANT_ID: $(AZURE_AUTH_TENANT_ID)
AZURE_SERVER_APP_ID: $(AZURE_SERVER_APP_ID)
AZURE_CLIENT_APP_ID: $(AZURE_CLIENT_APP_ID)
ALLOWED_ORIGIN: $(ALLOWED_ORIGIN)
AZURE_SERVER_APP_SECRET: $(AZURE_SERVER_APP_SECRET)
AZURE_CLIENT_APP_SECRET: $(AZURE_CLIENT_APP_SECRET)

- task: AzureCLI@2
displayName: Deploy Application
inputs:
azureSubscription: azconnection
scriptType: bash
scriptLocation: inlineScript
inlineScript: |
azd deploy --no-prompt
107 changes: 107 additions & 0 deletions .github/workflows/azure-dev.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
name: Deploy

on:
workflow_dispatch:
push:
# Run when commits are pushed to mainline branch (main or master)
# Set this to the mainline branch you are using
branches:
- main
- master

# GitHub Actions workflow to deploy to Azure using azd
# To configure required secrets for connecting to Azure, simply run `azd pipeline config`

# Set up permissions for deploying with secretless Azure federated credentials
# https://learn.microsoft.com/en-us/azure/developer/github/connect-from-azure?tabs=azure-portal%2Clinux#set-up-azure-login-with-openid-connect-authentication
permissions:
id-token: write
contents: read

jobs:
build:
runs-on: ubuntu-latest
env:
# azd required
AZURE_CLIENT_ID: ${{ vars.AZURE_CLIENT_ID }}
AZURE_TENANT_ID: ${{ vars.AZURE_TENANT_ID }}
AZURE_SUBSCRIPTION_ID: ${{ vars.AZURE_SUBSCRIPTION_ID }}
AZURE_ENV_NAME: ${{ vars.AZURE_ENV_NAME }}
AZURE_LOCATION: ${{ vars.AZURE_LOCATION }}
# project specific
AZURE_OPENAI_SERVICE: ${{ vars.AZURE_OPENAI_SERVICE }}
AZURE_OPENAI_RESOURCE_GROUP: ${{ vars.AZURE_OPENAI_RESOURCE_GROUP }}
AZURE_FORMRECOGNIZER_SERVICE: ${{ vars.AZURE_FORMRECOGNIZER_SERVICE }}
AZURE_FORMRECOGNIZER_RESOURCE_GROUP: ${{ vars.AZURE_FORMRECOGNIZER_RESOURCE_GROUP }}
AZURE_FORMRECOGNIZER_SKU: ${{ vars.AZURE_FORMRECOGNIZER_SKU }}
AZURE_SEARCH_INDEX: ${{ vars.AZURE_SEARCH_INDEX }}
AZURE_SEARCH_SERVICE: ${{ vars.AZURE_SEARCH_SERVICE }}
AZURE_SEARCH_SERVICE_RESOURCE_GROUP: ${{ vars.AZURE_SEARCH_SERVICE_RESOURCE_GROUP }}
AZURE_SEARCH_SERVICE_LOCATION: ${{ vars.AZURE_SEARCH_SERVICE_LOCATION }}
AZURE_SEARCH_SERVICE_SKU: ${{ vars.AZURE_SEARCH_SERVICE_SKU }}
AZURE_SEARCH_QUERY_LANGUAGE: ${{ vars.AZURE_SEARCH_QUERY_LANGUAGE }}
AZURE_SEARCH_QUERY_SPELLER: ${{ vars.AZURE_SEARCH_QUERY_SPELLER }}
AZURE_SEARCH_SEMANTIC_RANKER: ${{ vars.AZURE_SEARCH_SEMANTIC_RANKER }}
AZURE_STORAGE_ACCOUNT: ${{ vars.AZURE_STORAGE_ACCOUNT }}
AZURE_STORAGE_RESOURCE_GROUP: ${{ vars.AZURE_STORAGE_RESOURCE_GROUP }}
AZURE_STORAGE_SKU: ${{ vars.AZURE_STORAGE_SKU }}
AZURE_APP_SERVICE_SKU: ${{ vars.AZURE_APP_SERVICE_SKU }}
AZURE_OPENAI_CHATGPT_DEPLOYMENT: ${{ vars.AZURE_OPENAI_CHATGPT_DEPLOYMENT }}
AZURE_OPENAI_EMB_DEPLOYMENT: ${{ vars.AZURE_OPENAI_EMB_DEPLOYMENT }}
OPENAI_HOST: ${{ vars.OPENAI_HOST }}
OPENAI_API_KEY: ${{ vars.OPENAI_API_KEY }}
OPENAI_ORGANIZATION: ${{ vars.OPENAI_ORGANIZATION }}
AZURE_USE_APPLICATION_INSIGHTS: ${{ vars.AZURE_USE_APPLICATION_INSIGHTS }}
USE_VECTORS: ${{ vars.USE_VECTORS }}
USE_GPT4V: ${{ vars.USE_GPT4V }}
AZURE_USE_AUTHENTICATION: ${{ vars.AZURE_USE_AUTHENTICATION }}
AZURE_ENFORCE_ACCESS_CONTROL: ${{ vars.AZURE_ENFORCE_ACCESS_CONTROL }}
AZURE_AUTH_TENANT_ID: ${{ vars.AZURE_AUTH_TENANT_ID }}
AZURE_SERVER_APP_ID: ${{ vars.AZURE_SERVER_APP_ID }}
AZURE_CLIENT_APP_ID: ${{ vars.AZURE_CLIENT_APP_ID }}
ALLOWED_ORIGIN: ${{ vars.ALLOWED_ORIGIN }}

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Install azd
uses: Azure/[email protected]

- name: Install Nodejs
uses: actions/setup-node@v3
with:
node-version: 20

- name: Log in with Azure (Federated Credentials)
if: ${{ env.AZURE_CLIENT_ID != '' }}
run: |
azd auth login `
--client-id "$Env:AZURE_CLIENT_ID" `
--federated-credential-provider "github" `
--tenant-id "$Env:AZURE_TENANT_ID"
shell: pwsh

- name: Log in with Azure (Client Credentials)
if: ${{ env.AZURE_CREDENTIALS != '' }}
run: |
$info = $Env:AZURE_CREDENTIALS | ConvertFrom-Json -AsHashtable;
Write-Host "::add-mask::$($info.clientSecret)"
azd auth login `
--client-id "$($info.clientId)" `
--client-secret "$($info.clientSecret)" `
--tenant-id "$($info.tenantId)"
shell: pwsh
env:
AZURE_CREDENTIALS: ${{ secrets.AZURE_CREDENTIALS }}

- name: Provision Infrastructure
run: azd provision --no-prompt
env:
AZD_INITIAL_ENVIRONMENT_CONFIG: ${{ secrets.AZD_INITIAL_ENVIRONMENT_CONFIG }}
AZURE_SERVER_APP_SECRET: ${{ secrets.AZURE_SERVER_APP_SECRET }}
AZURE_CLIENT_APP_SECRET: ${{ secrets.AZURE_CLIENT_APP_SECRET }}

- name: Deploy Application
run: azd deploy --no-prompt
40 changes: 38 additions & 2 deletions azure.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,49 @@ services:
windows:
shell: pwsh
run: cd ../frontend;npm install;npm run build
interactive: true
interactive: false
continueOnError: false
posix:
shell: sh
run: cd ../frontend;npm install;npm run build
interactive: true
interactive: false
continueOnError: false
pipeline:
variables:
- AZURE_OPENAI_SERVICE
- AZURE_OPENAI_RESOURCE_GROUP
- AZURE_FORMRECOGNIZER_SERVICE
- AZURE_FORMRECOGNIZER_RESOURCE_GROUP
- AZURE_FORMRECOGNIZER_SKU
- AZURE_SEARCH_INDEX
- AZURE_SEARCH_SERVICE
- AZURE_SEARCH_SERVICE_RESOURCE_GROUP
- AZURE_SEARCH_SERVICE_LOCATION
- AZURE_SEARCH_SERVICE_SKU
- AZURE_SEARCH_QUERY_LANGUAGE
- AZURE_SEARCH_QUERY_SPELLER
- AZURE_SEARCH_SEMANTIC_RANKER
- AZURE_STORAGE_ACCOUNT
- AZURE_STORAGE_RESOURCE_GROUP
- AZURE_STORAGE_SKU
- AZURE_APP_SERVICE_SKU
- AZURE_OPENAI_CHATGPT_DEPLOYMENT
- AZURE_OPENAI_EMB_DEPLOYMENT
- OPENAI_HOST
- OPENAI_API_KEY
- OPENAI_ORGANIZATION
- AZURE_USE_APPLICATION_INSIGHTS
- USE_VECTORS
- USE_GPT4V
- AZURE_USE_AUTHENTICATION
- AZURE_ENFORCE_ACCESS_CONTROL
- AZURE_AUTH_TENANT_ID
- AZURE_SERVER_APP_ID
- AZURE_CLIENT_APP_ID
- ALLOWED_ORIGIN
secrets:
- AZURE_SERVER_APP_SECRET
- AZURE_CLIENT_APP_SECRET
hooks:
preprovision:
windows:
Expand Down
22 changes: 15 additions & 7 deletions infra/main.bicep
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,12 @@ var useKeyVault = useGPT4V || useSearchServiceKey
var tenantIdForAuth = !empty(authTenantId) ? authTenantId : tenantId
var authenticationIssuerUri = '${environment().authentication.loginEndpoint}${tenantIdForAuth}/v2.0'

@description('Whether the deployment is running on GitHub Actions')
param runningOnGh string = ''

@description('Whether the deployment is running on Azure DevOps Pipeline')
param runningOnAdo string = ''

// Organize resources in a resource group
resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = {
name: !empty(resourceGroupName) ? resourceGroupName : '${abbrs.resourcesResourceGroups}${environmentName}'
Expand Down Expand Up @@ -424,13 +430,15 @@ module storage 'core/storage/storage-account.bicep' = {
}

// USER ROLES
var principalType = empty(runningOnGh) && empty(runningOnAdo) ? 'User': 'ServicePrincipal'

module openAiRoleUser 'core/security/role.bicep' = if (openAiHost == 'azure') {
scope: openAiResourceGroup
name: 'openai-role-user'
params: {
principalId: principalId
roleDefinitionId: '5e0bd9bd-7b93-4f28-af87-19fc36ad61bd'
principalType: 'User'
principalType: principalType
}
}

Expand All @@ -440,7 +448,7 @@ module formRecognizerRoleUser 'core/security/role.bicep' = {
params: {
principalId: principalId
roleDefinitionId: 'a97b65f3-24c7-4388-baec-2e87135dc908'
principalType: 'User'
principalType: principalType
}
}

Expand All @@ -450,7 +458,7 @@ module storageRoleUser 'core/security/role.bicep' = {
params: {
principalId: principalId
roleDefinitionId: '2a2b9908-6ea1-4ae2-8e65-a410df84e7d1'
principalType: 'User'
principalType: principalType
}
}

Expand All @@ -460,7 +468,7 @@ module storageContribRoleUser 'core/security/role.bicep' = {
params: {
principalId: principalId
roleDefinitionId: 'ba92f5b4-2d11-453d-a403-e96b0029c9fe'
principalType: 'User'
principalType: principalType
}
}

Expand All @@ -471,7 +479,7 @@ module searchRoleUser 'core/security/role.bicep' = if (!useSearchServiceKey) {
params: {
principalId: principalId
roleDefinitionId: '1407120a-92aa-4202-b7e9-c0e197c71c8f'
principalType: 'User'
principalType: principalType
}
}

Expand All @@ -481,7 +489,7 @@ module searchContribRoleUser 'core/security/role.bicep' = if (!useSearchServiceK
params: {
principalId: principalId
roleDefinitionId: '8ebe5a00-799e-43f5-93ac-243d3dce84a7'
principalType: 'User'
principalType: principalType
}
}

Expand All @@ -491,7 +499,7 @@ module searchSvcContribRoleUser 'core/security/role.bicep' = if (!useSearchServi
params: {
principalId: principalId
roleDefinitionId: '7ca78c08-252a-4471-8644-bb5ff32d4ba0'
principalType: 'User'
principalType: principalType
}
}

Expand Down
10 changes: 8 additions & 2 deletions infra/main.parameters.json
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@
"embeddingDeploymentName": {
"value": "${AZURE_OPENAI_EMB_DEPLOYMENT=embedding}"
},
"openAiHost":{
"openAiHost": {
"value": "${OPENAI_HOST=azure}"
},
"openAiApiKey": {
Expand Down Expand Up @@ -119,8 +119,14 @@
"allowedOrigin": {
"value": "${ALLOWED_ORIGIN}"
},
"useIntegratedVectorization" :{
"useIntegratedVectorization": {
"value": "${USE_FEATURE_INT_VECTORIZATION}"
},
"runningOnGh": {
"value": "${GITHUB_ACTIONS}"
},
"runningOnAdo": {
"value": "${TF_BUILD}"
}
}
}

0 comments on commit 688e1c4

Please sign in to comment.