Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add workflow for azd deployment on GitHub Actions and ADO #1083

Merged
merged 20 commits into from
Feb 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
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}"
}
}
}
Loading