Skip to main content
Gorilla Tactics

Part V - Creating a CI/CD pipeline with EF migrations in Azure

·2 mins

This article is part of a series for setting up the single pipeline}

It’s now time to add the next stage, deploying to the Production environment.

Firstly, create a new Service Connection, rename the Service Principal, and get that user set up in your database, in the exactly the same way as we did for the test environment deployment.

Before adding the new stage, however, I want to have to approve the deployment to production, not just automatically deploy once the deployment to QA succeeds, which would be the default behaviour. The way to do this is to create a build Environment in Azure Devops. I’m going to name it Production, for obvious reasons.

Azure Devops will ask if you want to create a resource for the environment, but that isn’t required for what we want to do. Instead, click on the 3 dots in the top-right corner of the Environment page and select Approvals and checks, and select Approvals on the page that loads. Select the user(s) or user groups you want to require approval from and click Create.

With that done, we just need to add a stage to the build script.

Again, we first set the stage up:

- stage: Production
  dependsOn: QA
  jobs:
    - deployment: DeployProduction
      displayName: Deploy To Production
      pool:
        vmImage: 'windows-2022'
      environment: 'Production'
      strategy:
        runOnce:
          deploy:
            steps:
            - checkout: none
            - download: current
              artifact: drop
            - task: SqlAzureDacpacDeployment@1
              displayName: Run EF Migration
              inputs:
                azureSubscription: '<Service Connection Name>'
                AuthenticationType: 'servicePrincipal'
                ServerName: '<server name>.database.windows.net'
                DatabaseName: '<database name>'
                deployType: 'SqlTask'
                SqlFile: '$(Pipeline.Workspace)\drop\migration.sql'
                IpDetectionMethod: 'AutoDetect'
            - task: AzureRmWebAppDeployment@4
              displayName: Deploy Web App To Production
              inputs:
                ConnectionType: 'AzureRM'
                azureSubscription: '<Service Connection Name>'
                appType: 'webAppLinux'
                WebAppName: '<web app name>'
                deployToSlotOrASE: true
                SlotName: '<staging slot name>'
                packageForLinux: '$(Pipeline.Workspace)/drop/$(Build.BuildId).zip'
                RuntimeStack: 'DOTNETCORE|7.0'
                StartupCommand: 'dotnet <startup project name>.dll'

You will again be asked to give the pipeline permission to use the Service Connection we created earlier, as well as the environment. Merge this in, and it will automatically run. You should find that the Build stage successfully runs, but the Deploy stage doesn’t even start. You will hopefully see a message like this:

The Deploy to production stage waiting for approval

If you click to approve deployment, this stage will now hopefully successfully run:

A fully successful build & deploy to QA and Production

Now it’s working, it’s time to see if the build can be sped up, as if we look again at the build log:

The result of a successful run of the newly created pipeline

you can see that the longest tasks were installing the NuGet packages and running the tests, which I find annoying!

In the next post, we will look at speeding up the Nuget packages installation task.