Want to know how to deploy a .NET API to Azure? For .NET 7 and a Minimal API?
Since I covered an example of continuous integration for a .NET MinimalAPI demo project in my series on Better Practices in CI, in this post I move on to deploying the demo API to Azure.
Pipeline Parallels
The script has the test and publish jobs dependent on the build job. This allows the test and publish to run in parallel. The deploy job then requires both test and publish jobs to run.
We get the speed of running test and publish jobs concurrently, yet we still block the deploy if either fails.
The Deploy Yaml
From the Github Actions Workflow yaml:
deploy_azure:
name: Manually deploy to Azure
runs-on: ubuntu-latest
defaults:
run:
shell: bash
# this relies on GitHub settings for the production environment
# that require manual approval before deployment
environment:
name: production
needs: [test, publish]
steps:
- name: Manually validate version
run: |
dotnet --version
- name: Download artifact from publish job
uses: actions/download-artifact@v3
with:
name: ${{env.PUBLISH_ARTIFACT_NAME}}
path: ${{env.PUBLISH_PATH}}
- name: Validate artifact presence
run: |
if [ -z "$(ls -A ${{env.PUBLISH_PATH}})" ]; then
exit 1
fi
- name: Validate directory state
run: |
du -sh ./*
- name: Deploy to Azure WebApp
uses: azure/webapps-deploy@v2
with:
app-name: ${{ env.AZURE_WEBAPP_NAME }}
package: publish
publish-profile: ${{ secrets.LabDemoAPI_628F }}
- name: Azure Login
uses: azure/login@v1
with:
creds: ${{ secrets.LabDemoApiService_SPN }}
- name: Import API into Azure API Management
run: az apim api import --path "${{ env.AZURE_APIM_RESOURCE_PATH }}" --resource-group "${{ env.AZURE_APIM_RESOURCEGROUP }}" --service-name "${{ env.AZURE_APIM_SERVICENAME }}" --api-id "${{ env.AZURE_APIM_API_ID }}" --service-url "${{ env.AZURE_APIM_APPSERVICEURL }}" --specification-path "${{ env.API_IMPORT_SPECIFICATION_PATH }}" --specification-format OpenApi --subscription-required false
- name: logout
run: >
az logout
# FUTURE: ideally, we'd pull the url from a previous step's output
- name: Basic validation that the api is running
uses: lakuapik/gh-actions-http-status@v1
with:
sites: '["https://labdemoapi.azurewebsites.net/"]'
expected: '[200]'
Manual Deploy of the .NET API
If I had full confidence in my CI testing stage, I could deploy automatically to production. Instead, I configured my GitHub production settings to have manual deployment only.
Validation
The script will fail if the publish artifact is not available, per line 27 of the yaml above.
I can also visually inspect the workflow’s steps to confirm the published artifact’s existence and size.
Once the deploy to Azure has happened successfully (line 37 on), I perform an automatic validation that the API is up and running, per line 56.
Further validation will depend on the availability of tools like DataDog or NewRelic monitoring the API and alerting. However, as an alternative, I can add more extensive did-it-deploy-well testing in the GitHub Actions.
More Information
You can check out other articles online on .NET Minimal API and deployment. There’s scaffolding you can create from Visual Studio 2022‘s project publish option, and there’s scaffolding you can generate within the Azure portal, and there’s a mixed approach from Microsoft.
What I covered in this article is a mashup of those two and my own approach.
If you’re interested in Azure DevOps instead of GitHub, or need details on using GitHub as a source control, see Les Jackson’s post over on Dotnet Playbook.