Skip to content
Merged
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
68 changes: 29 additions & 39 deletions .github/workflows/Build-Test-And-Deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ jobs:
- name: Azure Login
uses: azure/login@v3
with:
client-id: ${{ secrets.ESSENTIALCSHARPDEV_CLIENT_ID }}
client-id: ${{ secrets.AZURE_CLIENT_ID }}
tenant-id: ${{ secrets.ESSENTIALCSHARP_APPIDENTITY_TENANT_ID }}
subscription-id: ${{ secrets.ESSENTIALCSHARP_SUBSCRIPTION_ID }}

Expand All @@ -113,45 +113,38 @@ jobs:
docker image ls -a

- name: Log in to container registry
uses: docker/login-action@v4
with:
registry: ${{ vars.DEVCONTAINER_REGISTRY }}
username: ${{ secrets.ESSENTIALCSHARP_ACR_USERNAME }}
password: ${{ secrets.ESSENTIALCSHARP_ACR_PASSWORD }}
run: |
REGISTRY="${{ vars.DEVCONTAINER_REGISTRY }}"
az acr login --name "${REGISTRY%.azurecr.io}"

- name: Push Image to Container Registry
run: docker push --all-tags ${{ vars.DEVCONTAINER_REGISTRY }}/essentialcsharpweb

- name: Create and Deploy to Container App
- name: Configure Container App Identity and Registry
uses: azure/CLI@v3
env:
CONTAINER_APP_NAME: ${{ vars.CONTAINER_APP_NAME }}
RESOURCEGROUP: ${{ vars.RESOURCEGROUP }}
CONTAINER_REGISTRY: ${{ vars.DEVCONTAINER_REGISTRY }}
CONTAINER_APP_ENVIRONMENT: ${{ vars.CONTAINER_APP_ENVIRONMENT }}
ACR_USERNAME: ${{ secrets.ESSENTIALCSHARP_ACR_USERNAME }}
ACR_PASSWORD: ${{ secrets.ESSENTIALCSHARP_ACR_PASSWORD }}
with:
inlineScript: |
az config set extension.use_dynamic_install=yes_without_prompt
az containerapp up -n $CONTAINER_APP_NAME -g $RESOURCEGROUP --image $CONTAINER_REGISTRY/essentialcsharpweb:${{ github.sha }} --environment $CONTAINER_APP_ENVIRONMENT --registry-server $CONTAINER_REGISTRY --ingress external --target-port 8080 --registry-username $ACR_USERNAME --registry-password $ACR_PASSWORD
# Assumes container app already exists (provisioned by Terraform)
az extension add --name containerapp --upgrade
az containerapp identity assign --name $CONTAINER_APP_NAME --resource-group $RESOURCEGROUP --user-assigned ${{ secrets.WEB_UAMI_RESOURCE_ID }}
az containerapp registry set --name $CONTAINER_APP_NAME --resource-group $RESOURCEGROUP --server $CONTAINER_REGISTRY --identity ${{ secrets.WEB_UAMI_RESOURCE_ID }}

- name: Assign Managed Identity to Container App and Set Secrets and Environment Variables
Copy link

Copilot AI Apr 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The step name says it assigns a managed identity, but the identity assignment was moved to the prior step. Rename this step to reflect what it now does (setting Key Vault-backed secrets and updating Container App env vars/image) to avoid confusion during ops/debugging.

Suggested change
- name: Assign Managed Identity to Container App and Set Secrets and Environment Variables
- name: Set Key Vault-backed secrets and update Container App environment variables and image

Copilot uses AI. Check for mistakes.
uses: azure/CLI@v3
env:
CONTAINER_APP_NAME: ${{ vars.CONTAINER_APP_NAME }}
RESOURCEGROUP: ${{ vars.RESOURCEGROUP }}
CONTAINER_REGISTRY: ${{ vars.DEVCONTAINER_REGISTRY }}
CONTAINER_APP_ENVIRONMENT: ${{ vars.CONTAINER_APP_ENVIRONMENT }}
KEYVAULTURI: ${{ secrets.ESSENTIALCSHARP_KEYVAULT_URI }}
MANAGEDIDENTITYID: ${{ secrets.ESSENTIALCSHARP_APPIDENTITY_ID }}
ACR_USERNAME: ${{ secrets.ESSENTIALCSHARP_ACR_USERNAME }}
ACR_PASSWORD: ${{ secrets.ESSENTIALCSHARP_ACR_PASSWORD }}
AZURECLIENTID: ${{ secrets.IDENTITY_CLIENT_ID }}
MANAGEDIDENTITYID: ${{ secrets.WEB_UAMI_RESOURCE_ID }}
AZURECLIENTID: ${{ secrets.WEB_UAMI_CLIENT_ID }}
TRYDOTNET_ORIGIN: ${{ vars.TRYDOTNET_ORIGIN }}
with:
inlineScript: |
az containerapp identity assign -n ${{ vars.CONTAINER_APP_NAME }} -g ${{ vars.RESOURCEGROUP }} --user-assigned ${{ vars.CONTAINER_APP_IDENTITY }}
az containerapp secret set -n $CONTAINER_APP_NAME -g $RESOURCEGROUP --secrets github-clientid=keyvaultref:$KEYVAULTURI/secrets/authentication-github-clientid,identityref:$MANAGEDIDENTITYID \
github-clientsecret=keyvaultref:$KEYVAULTURI/secrets/authentication-github-clientsecret,identityref:$MANAGEDIDENTITYID msft-clientid=keyvaultref:$KEYVAULTURI/secrets/authentication-microsoft-clientid,identityref:$MANAGEDIDENTITYID \
msft-clientsecret=keyvaultref:$KEYVAULTURI/secrets/authentication-microsoft-clientsecret,identityref:$MANAGEDIDENTITYID emailsender-apikey=keyvaultref:$KEYVAULTURI/secrets/authmessagesender-apikey,identityref:$MANAGEDIDENTITYID \
Expand All @@ -163,7 +156,9 @@ jobs:
ai-vectordeployment=keyvaultref:$KEYVAULTURI/secrets/AIOptions--VectorGenerationDeploymentName,identityref:$MANAGEDIDENTITYID ai-chatdeployment=keyvaultref:$KEYVAULTURI/secrets/AIOptions--ChatDeploymentName,identityref:$MANAGEDIDENTITYID \
ai-systemprompt=keyvaultref:$KEYVAULTURI/secrets/AIOptions--SystemPrompt,identityref:$MANAGEDIDENTITYID \
postgres-vectorstore-connectionstring=keyvaultref:$KEYVAULTURI/secrets/ConnectionStrings--PostgresVectorStore,identityref:$MANAGEDIDENTITYID
az containerapp update --name $CONTAINER_APP_NAME --resource-group $RESOURCEGROUP --replace-env-vars Authentication__github__clientId=secretref:github-clientid Authentication__github__clientSecret=secretref:github-clientsecret \
az containerapp update --name $CONTAINER_APP_NAME --resource-group $RESOURCEGROUP \
--image $CONTAINER_REGISTRY/essentialcsharpweb:${{ github.sha }} \
--replace-env-vars Authentication__github__clientId=secretref:github-clientid Authentication__github__clientSecret=secretref:github-clientsecret \
Authentication__microsoft__clientId=secretref:msft-clientid Authentication__microsoft__clientSecret=secretref:msft-clientsecret AuthMessageSender__ApiKey=secretref:emailsender-apikey AuthMessageSender__SecretKey=secretref:emailsender-secret \
AuthMessageSender__SendFromName=secretref:emailsender-name AuthMessageSender__SendFromEmail=secretref:emailsender-email ConnectionStrings__EssentialCSharpWebContextConnection=secretref:connectionstring ASPNETCORE_ENVIRONMENT=Staging \
AZURE_CLIENT_ID=$AZURECLIENTID HCaptcha__SiteKey=secretref:captcha-sitekey HCaptcha__SecretKey=secretref:captcha-secretkey APPLICATIONINSIGHTS_CONNECTION_STRING=secretref:appinsights-connectionstring \
Expand All @@ -186,15 +181,15 @@ jobs:
needs: [deploy-development]
concurrency:
group: deploy-production
cancel-in-progress: true
cancel-in-progress: false
Copy link

Copilot AI Apr 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Setting cancel-in-progress: false for the production deploy concurrency group allows multiple production deployments to run at the same time. Because both runs mutate the same Container App (identity/registry/secrets/image), overlapping runs can race and leave production on an unexpected image or env-var set. Consider reverting to cancel-in-progress: true (or use a more granular concurrency group keyed by environment/app name if parallelism is needed).

Suggested change
cancel-in-progress: false
cancel-in-progress: true

Copilot uses AI. Check for mistakes.
environment:
name: "Production"

steps:
- name: Azure Login
uses: azure/login@v3
with:
client-id: ${{ secrets.ESSENTIALCSHARP_CLIENT_ID }}
client-id: ${{ secrets.AZURE_CLIENT_ID }}
tenant-id: ${{ secrets.ESSENTIALCSHARP_TENANT_ID }}
subscription-id: ${{ secrets.ESSENTIALCSHARP_SUBSCRIPTION_ID }}

Expand All @@ -210,45 +205,38 @@ jobs:
docker image ls -a

- name: Log in to container registry
uses: docker/login-action@v4
with:
registry: ${{ vars.PRODCONTAINER_REGISTRY }}
username: ${{ secrets.ESSENTIALCSHARP_ACR_USERNAME }}
password: ${{ secrets.ESSENTIALCSHARP_ACR_PASSWORD }}
run: |
REGISTRY="${{ vars.PRODCONTAINER_REGISTRY }}"
az acr login --name "${REGISTRY%.azurecr.io}"

- name: Push Image to Container Registry
run: docker push --all-tags ${{ vars.PRODCONTAINER_REGISTRY }}/essentialcsharpweb

- name: Create and Deploy to Container App
- name: Configure Container App Identity and Registry
uses: azure/CLI@v3
env:
CONTAINER_APP_NAME: ${{ vars.CONTAINER_APP_NAME }}
RESOURCEGROUP: ${{ vars.RESOURCEGROUP }}
CONTAINER_REGISTRY: ${{ vars.PRODCONTAINER_REGISTRY }}
CONTAINER_APP_ENVIRONMENT: ${{ vars.CONTAINER_APP_ENVIRONMENT }}
ACR_USERNAME: ${{ secrets.ESSENTIALCSHARP_ACR_USERNAME }}
ACR_PASSWORD: ${{ secrets.ESSENTIALCSHARP_ACR_PASSWORD }}
with:
inlineScript: |
az config set extension.use_dynamic_install=yes_without_prompt
az containerapp up -n $CONTAINER_APP_NAME -g $RESOURCEGROUP --image $CONTAINER_REGISTRY/essentialcsharpweb:${{ github.sha }} --environment $CONTAINER_APP_ENVIRONMENT --registry-server $CONTAINER_REGISTRY --ingress external --target-port 8080 --registry-username $ACR_USERNAME --registry-password $ACR_PASSWORD
# Assumes container app already exists (provisioned by Terraform)
az extension add --name containerapp --upgrade
az containerapp identity assign --name $CONTAINER_APP_NAME --resource-group $RESOURCEGROUP --user-assigned ${{ secrets.WEB_UAMI_RESOURCE_ID }}
az containerapp registry set --name $CONTAINER_APP_NAME --resource-group $RESOURCEGROUP --server $CONTAINER_REGISTRY --identity ${{ secrets.WEB_UAMI_RESOURCE_ID }}

- name: Assign Managed Identity to Container App and Set Secrets and Environment Variables
Copy link

Copilot AI Apr 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The step name says it assigns a managed identity, but the identity assignment was moved to the prior step. Rename this step to reflect what it now does (setting Key Vault-backed secrets and updating Container App env vars/image) to avoid confusion during ops/debugging.

Suggested change
- name: Assign Managed Identity to Container App and Set Secrets and Environment Variables
- name: Set Key Vault-backed Secrets and Update Container App Environment Variables and Image

Copilot uses AI. Check for mistakes.
uses: azure/CLI@v3
env:
CONTAINER_APP_NAME: ${{ vars.CONTAINER_APP_NAME }}
RESOURCEGROUP: ${{ vars.RESOURCEGROUP }}
CONTAINER_REGISTRY: ${{ vars.PRODCONTAINER_REGISTRY }}
CONTAINER_APP_ENVIRONMENT: ${{ vars.CONTAINER_APP_ENVIRONMENT }}
KEYVAULTURI: ${{ secrets.ESSENTIALCSHARP_KEYVAULT_URI }}
MANAGEDIDENTITYID: ${{ secrets.ESSENTIALCSHARP_APPIDENTITY_ID }}
ACR_USERNAME: ${{ secrets.ESSENTIALCSHARP_ACR_USERNAME }}
ACR_PASSWORD: ${{ secrets.ESSENTIALCSHARP_ACR_PASSWORD }}
AZURECLIENTID: ${{ secrets.IDENTITY_CLIENT_ID }}
MANAGEDIDENTITYID: ${{ secrets.WEB_UAMI_RESOURCE_ID }}
AZURECLIENTID: ${{ secrets.WEB_UAMI_CLIENT_ID }}
TRYDOTNET_ORIGIN: ${{ vars.PROD_TRYDOTNET_ORIGIN }}
with:
inlineScript: |
az containerapp identity assign -n ${{ vars.CONTAINER_APP_NAME }} -g ${{ vars.RESOURCEGROUP }} --user-assigned ${{ vars.CONTAINER_APP_IDENTITY }}
az containerapp secret set -n $CONTAINER_APP_NAME -g $RESOURCEGROUP --secrets github-clientid=keyvaultref:$KEYVAULTURI/secrets/authentication-github-clientid,identityref:$MANAGEDIDENTITYID \
github-clientsecret=keyvaultref:$KEYVAULTURI/secrets/authentication-github-clientsecret,identityref:$MANAGEDIDENTITYID msft-clientid=keyvaultref:$KEYVAULTURI/secrets/authentication-microsoft-clientid,identityref:$MANAGEDIDENTITYID \
msft-clientsecret=keyvaultref:$KEYVAULTURI/secrets/authentication-microsoft-clientsecret,identityref:$MANAGEDIDENTITYID emailsender-apikey=keyvaultref:$KEYVAULTURI/secrets/authmessagesender-apikey,identityref:$MANAGEDIDENTITYID \
Expand All @@ -260,7 +248,9 @@ jobs:
ai-vectordeployment=keyvaultref:$KEYVAULTURI/secrets/AIOptions--VectorGenerationDeploymentName,identityref:$MANAGEDIDENTITYID ai-chatdeployment=keyvaultref:$KEYVAULTURI/secrets/AIOptions--ChatDeploymentName,identityref:$MANAGEDIDENTITYID \
ai-systemprompt=keyvaultref:$KEYVAULTURI/secrets/AIOptions--SystemPrompt,identityref:$MANAGEDIDENTITYID \
postgres-vectorstore-connectionstring=keyvaultref:$KEYVAULTURI/secrets/ConnectionStrings--PostgresVectorStore,identityref:$MANAGEDIDENTITYID
az containerapp update --name $CONTAINER_APP_NAME --resource-group $RESOURCEGROUP --replace-env-vars Authentication__github__clientId=secretref:github-clientid Authentication__github__clientSecret=secretref:github-clientsecret \
az containerapp update --name $CONTAINER_APP_NAME --resource-group $RESOURCEGROUP \
--image $CONTAINER_REGISTRY/essentialcsharpweb:${{ github.sha }} \
--replace-env-vars Authentication__github__clientId=secretref:github-clientid Authentication__github__clientSecret=secretref:github-clientsecret \
Authentication__microsoft__clientId=secretref:msft-clientid Authentication__microsoft__clientSecret=secretref:msft-clientsecret AuthMessageSender__ApiKey=secretref:emailsender-apikey AuthMessageSender__SecretKey=secretref:emailsender-secret \
AuthMessageSender__SendFromName=secretref:emailsender-name AuthMessageSender__SendFromEmail=secretref:emailsender-email ConnectionStrings__EssentialCSharpWebContextConnection=secretref:connectionstring ASPNETCORE_ENVIRONMENT=Production \
AZURE_CLIENT_ID=$AZURECLIENTID HCaptcha__SiteKey=secretref:captcha-sitekey HCaptcha__SecretKey=secretref:captcha-secretkey APPLICATIONINSIGHTS_CONNECTION_STRING=secretref:appinsights-connectionstring \
Expand Down
Loading