Continuous integration and deployment with Azure DevOps
Tip
This content is an excerpt from the eBook, DevOps for ASP.NET Core Developers, available on .NET Docs or as a free downloadable PDF that can be read offline.
Note
This section details continuous integration and deployment with Azure DevOps. You can achieve that with GitHub Actions as well. GitHub Actions is a workflow engine built into GitHub that can also be used for continuous integration and deployment. To follow the guide for building and deploying to Azure using GitHub, complete the Publish the app's code to GitHub and Disconnect local Git deployment sections below and then proceed to the GitHub Actions section.
In the previous chapter, you created a local Git repository for the Simple Feed Reader app. In this chapter, you'll publish that code to a GitHub repository and construct an Azure DevOps Services pipeline using Azure Pipelines. The pipeline enables continuous builds and deployments of the app. Any commit to the GitHub repository triggers a build and a deployment to the Azure Web App's staging slot.
In this section, you'll complete the following tasks:
- Publish the app's code to GitHub
- Disconnect local Git deployment
- Create an Azure DevOps organization
- Create a team project in Azure DevOps organization
- Configure a self-hosted agent if necessary
- Create a build definition
- Create a release pipeline
- Commit changes to GitHub and automatically deploy to Azure
- Examine the Azure Pipelines pipeline
Publish the app's code to GitHub
Open a browser window, and navigate to
https://github.com
.Click the + drop-down in the header, and select New repository:
Select your account in the Owner drop-down, and enter simple-feed-reader in the Repository name textbox.
Click the Create repository button.
Open your local machine's command shell. Navigate to the directory in which the simple-feed-reader Git repository is stored.
Rename the existing origin remote to upstream. Execute the following command:
git remote rename origin upstream
Add a new origin remote pointing to your copy of the repository on GitHub. Execute the following command:
git remote add origin https://github.com/<GitHub_username>/simple-feed-reader/
Publish your local Git repository to the newly created GitHub repository. Execute the following command:
git push -u origin main
Open a browser window, and navigate to
https://github.com/<GitHub_username>/simple-feed-reader/
. Validate that your code appears in the GitHub repository.
Disconnect local Git deployment
Remove the local Git deployment with the following steps. Azure Pipelines (an Azure DevOps service) both replaces and augments that functionality.
Open the Azure portal, and navigate to the staging (mywebapp<unique_number>/staging) Web App. The Web App can be quickly located by entering staging in the portal's search box:
Click Deployment Center. A new panel appears. Click Disconnect to remove the local Git source control configuration that was added in the previous chapter. Confirm the removal operation by clicking the Yes button.
Navigate to the mywebapp<unique_number> App Service. As a reminder, the portal's search box can be used to quickly locate the App Service.
Click Deployment Center. A new panel appears. Click Disconnect to remove the local Git source control configuration that was added in the previous chapter. Confirm the removal operation by clicking the Yes button.
Create an Azure DevOps organization
- Open a browser, and navigate to the Azure DevOps organization creation page.
- Select New organization
- Confirm the information, and then select Continue.
- Sign in to your organization at any time,
https://dev.azure.com/{yourorganization}
Create a team project in Azure DevOps organization
- Choose the organization, and then select New project.
- Enter the project name as MyFirstProject and select the Visibility as Private
- Select Create project.
For more information, see Create a project
Configure a self-hosted agent if necessary
To build your code or deploy your software using Azure Pipelines, you need at least one agent. In Azure Pipelines, you can run parallel jobs on either Microsoft-hosted or self-hosted agent. But with the recent change in Azure Pipelines free grant of parallel jobs is temporarily disable for the public projects.For more details, refer Configure and pay for parallel jobs.
Go to Organization Settings and then Pipelines > Parallel jobs. If you see value 0 under Microsoft-hosted that means you need a Self-hosted agent to run your pipeline.
You can create that by following details mentioned in Self-hosted agents. After successful configuration, you'll be able to see available agent under Organization Settings > Agent pools > {youragentname}
Configure the Azure Pipelines pipeline
There are three distinct steps to complete. Completing the steps in the following three sections results in an operational DevOps pipeline.
Grant Azure DevOps access to the GitHub repository
In your project, navigate to the Pipelines page. Then choose the action to create a new pipeline:
Use
Use the classic editor
to create the pipeline.Select the GitHub option from the Select a source section::
Authorization is required before Azure DevOps can access your GitHub repository. Enter <GitHub_username> GitHub connection in the Connection name textbox. For example:
If two-factor authentication is enabled on your GitHub account, a personal access token is required. In that case, click the Authorize with a GitHub personal access token link. See the official GitHub personal access token creation instructions for help. Only the repo scope of permissions is needed. Otherwise, click the Authorize using OAuth button.
When prompted, sign in to your GitHub account. Then select Authorize to grant access to your Azure DevOps organization. If successful, a new service endpoint is created.
Click the ellipsis button next to the Repository button. Select the <GitHub_username>/simple-feed-reader repository from the list. Click the Select button.
Select the default branch (main) from the Default branch for manual and scheduled builds drop-down. Click the Continue button. The template selection page appears.
Create the build definition
From the template selection page, enter ASP.NET Core in the search box:
The template search results appear. Hover over the ASP.NET Core template, and click the Apply button.
The Tasks tab of the build definition appears. Select the self-hosted Agent pool if you have created that in the earlier step.
Note
If you are using MS-hosted agent then select the Hosted > Azure Pipelines from drop down.
Click the Triggers tab.
Check the Enable continuous integration box. Under the Branch filters section, confirm that the Type drop-down is set to Include. Set the Branch specification drop-down to main.
These settings cause a build to trigger when any change is pushed to the default branch (main) of the GitHub repository. Continuous integration is tested in the Commit changes to GitHub and automatically deploy to Azure section.
Click the Save & queue button, and select the Save option:
The following modal dialog appears:
Use the default folder of \, and click the Save button.
Create the release pipeline
Click the Releases tab of your team project. Click the New pipeline button.
The template selection pane appears.
From the template selection page, enter App Service Deployment in the search box:
The template search results appear. Hover over the Azure App Service Deployment with Slot template, and click the Apply button. The Pipeline tab of the release pipeline appears.
Click the Add button in the Artifacts box. The Add artifact panel appears:
Select the Build tile from the Source type section. This type allows for the linking of the release pipeline to the build definition.
Select MyFirstProject from the Project drop-down.
Select the build definition name, MyFirstProject-ASP.NET Core-CI, from the Source (Build definition) drop-down.
Select Latest from the Default version drop-down. This option builds the artifacts produced by the latest run of the build definition.
Replace the text in the Source alias textbox with Drop.
Click the Add button. The Artifacts section updates to display the changes.
Click the lightning bolt icon to enable continuous deployments:
With this option enabled, a deployment occurs each time a new build is available.
A Continuous deployment trigger panel appears to the right. Click the toggle button to enable the feature. It isn't necessary to enable the Pull request trigger.
Click the Add drop-down in the Build branch filters section. Choose the Build Definition's default branch option. This filter causes the release to trigger only for a build from the GitHub repository's default branch (main).
Click the Save button. Click the OK button in the resulting Save modal dialog.
Click the Stage 1 box. An Stage panel appears to the right. Change the Stage 1 text in the Stage name textbox to Production.
Click the 1 phase, 2 tasks link in the Production box:
The Tasks tab of the environment appears.
Click the Deploy Azure App Service to Slot task. Its settings appear in a panel to the right.
Select the Azure subscription associated with the App Service from the Azure subscription drop-down. Once selected, click the Authorize button.
Select Web App from the App type drop-down.
Select mywebapp/<unique_number/> from the App service name drop-down.
Select AzureTutorial from the Resource group drop-down.
Select staging from the Slot drop-down.
Select Run on agent* under Tasks. On the right pane, you'll see Agent Job.
Select the self-hosted Agent pool if you have created that in the earlier step.
Note
If you are using MS-hosted agent then select the Hosted > Azure Pipelines from drop down.
Click the Save button.
Hover over the default release pipeline name. Click the pencil icon to edit it. Use MyFirstProject-ASP.NET Core-CD as the name.
Click the Save button.
Commit changes to GitHub and automatically deploy to Azure
Open SimpleFeedReader.sln in Visual Studio.
In Solution Explorer, open Pages\Index.cshtml. Change
<h2>Simple Feed Reader - V3</h2>
to<h2>Simple Feed Reader - V4</h2>
.Press Ctrl+Shift+B to build the app.
Commit the file to the GitHub repository. Use either the Changes page in Visual Studio's Team Explorer tab, or execute the following using the local machine's command shell:
git commit -a -m "upgraded to V4"
Push the change in the default branch (main) to the origin remote of your GitHub repository. In the following command, replace the placeholder
{BRANCH}
with the default branch (usemain
):git push origin {BRANCH}
The commit appears in the GitHub repository's default branch (main). You'll be able to see the commit history in
https://github.com/<GitHub_username>/simple-feed-reader/commits/main
.The build is triggered, since continuous integration is enabled in the build definition's Triggers tab:
Navigate to the Pipelines. You'll see the CI pipeline details and monitor each steps if you drill down Jobs details.
Similarly, go to the Releases tab to see the details of CD pipeline. You can always drill down further to see more details of each step.
Once the build succeeds, a deployment to Azure occurs. Navigate to the app in the browser. Notice that the "V4" text appears in the heading:
Examine the Azure Pipelines pipeline
Build definition
A build definition was created with the name MyFirstProject-ASP.NET Core-CI. Upon completion, the build produces a .zip file including the assets to be published. The release pipeline deploys those assets to Azure.
The build definition's Tasks tab lists the individual steps being used. There are five build tasks.
Restore — Executes the
dotnet restore
command to restore the app's NuGet packages. The default package feed used is nuget.org.Build — Executes the
dotnet build --configuration release
command to compile the app's code. This--configuration
option is used to produce an optimized version of the code, which is suitable for deployment to a production environment. Modify the BuildConfiguration variable on the build definition's Variables tab if, for example, a debug configuration is needed.Test — Executes the
dotnet test --configuration release --logger trx --results-directory <local_path_on_build_agent>
command to run the app's unit tests. Unit tests are executed within any C# project matching the **/Tests/.csproj glob pattern. Test results are saved in a .trx file at the location specified by the--results-directory
option. If any tests fail, the build fails and isn't deployed.Note
To verify the unit tests work, modify SimpleFeedReader.Tests\Services\NewsServiceTests.cs to purposefully break one of the tests. For example, change
Assert.True(result.Count > 0);
toAssert.False(result.Count > 0);
in theReturns_News_Stories_Given_Valid_Uri
method. Commit and push the change to GitHub. The build is triggered and fails. The build pipeline status changes to failed. Revert the change, commit, and push again. The build succeeds.Publish — Executes the
dotnet publish --configuration release --output <local_path_on_build_agent>
command to produce a .zip file with the artifacts to be deployed. The--output
option specifies the publish location of the .zip file. That location is specified by passing a predefined variable named$(build.artifactstagingdirectory)
. That variable expands to a local path, such as c:\agent_work\1\a, on the build agent.Publish Artifact — Publishes the .zip file produced by the Publish task. The task accepts the .zip file location as a parameter, which is the predefined variable
$(build.artifactstagingdirectory)
. The .zip file is published as a folder named drop.
Click the build definition's Summary link to view a history of builds with the definition:
On the resulting page, click the individual build for more details.
A summary of this specific build is displayed. Click the published link, and notice the drop folder produced by the build is listed:
Use the ellipsis and click on Downloads artifacts links to inspect the published artifacts.
Release pipeline
A release pipeline was created with the name MyFirstProject-ASP.NET Core-CD:
The two major components of the release pipeline are the Artifacts and the Stages. Clicking the box in the Artifacts section reveals the following panel:
The Source (Build definition) value represents the build definition to which this release pipeline is linked. The .zip file produced by a successful run of the build definition is provided to the Production environment for deployment to Azure. Click the 1 phase, 2 tasks link in the Production environment box to view the release pipeline tasks:
The release pipeline consists of two tasks: Deploy Azure App Service to Slot and Manage Azure App Service - Slot Swap. Clicking the first task reveals the following task configuration:
The Azure subscription, service type, web app name, resource group, and deployment slot are defined in the deployment task. The Package or folder textbox holds the .zip file path to be extracted and deployed to the staging slot of the mywebapp<unique_number> web app.
Clicking the slot swap task reveals the following task configuration:
The subscription, resource group, service type, web app name, and deployment slot details are provided. The Swap with Production check box is checked. Consequently, the bits deployed to the staging slot are swapped into the production environment.
Additional reading
Feedback
Submit and view feedback for