© Les Jackson 2020
L. JacksonThe Complete ASP.NET Core 3 API Tutorialhttps://doi.org/10.1007/978-1-4842-6255-9_12

12. The CI/CD Pipeline

Les Jackson1 
(1)
Melbourne, VIC, Australia
 

Chapter Summary

In this chapter we bring together what we’ve done so far: build activity, source control, and unit testing and frame it within the context of Continuous Integration/Continuous Delivery (CI/CD).

When Done, You Will

  • Understand what CI/CD is.

  • Understand what a CI/CD Pipeline is.

  • Setup Azure DevOps with GitHub to act as our CI/CD pipeline.

  • Automatically Build, Test, and Package our API solution using Azure DevOps.

  • Prepare for Deployment to Azure.

What Is CI/CD?

To talk about CI/CD is to talk about a pipeline of work” or, if you prefer another analogy: a production line, where a product (in this instance working software) is taken from is raw form (code1) and gradually transformed into working software that’s usable by the end users.

Clearly, this process will include a number of steps, most (if not all) we will want to automate.

It’s essentially about the faster realization of business value and is a central foundational idea of agile software development. (Fret not, I’m not going to bang that drum too much.)

CI/CD or CI/CD?

Don’t worry, the heading is not a typo (we’ll come on to that in a minute).

CI is easy; that stands for Continuous Integration. CI is the process of taking any code changes from one or more developers working on the same piece of software and merging those changes back into the main code “branch” by building and testing that code. As the name would suggest, this process is continuous, triggered usually when developers “check-in” code changes to the code repository (as you have already been doing with Git/GitHub).

The whole point of CI is to ensure that the main (or master) code branch remains healthy throughout the build activity and that any new changes introduced by the multiple developers working on the code don’t conflict and break the build.

CD can be a little bit more confusing. Why? We’ll you’ll hear people using both the following terms in reference to CD: Continuous Delivery and Continuous Deployment.

What’s the Difference?

Well, if you think of Continuous Delivery as an extension of Continuous Integration, it’s the process of automating the release process. It ensures that you can deploy software changes frequently and at the press of a button. Continuous Delivery stops just short of automatically pushing changes into production though; that’s where Continuous Deployment comes in.

Continuous Deployment goes further than Continuous Delivery, in that code changes will make their way through to production without any human intervention (assuming there are no failures in the CI/CD pipeline, e.g., failing tests).
../images/501438_1_En_12_Chapter/501438_1_En_12_Fig1_HTML.jpg
Figure 12-1

Continuous: integration, delivery, and deployment

So Which Is It?

Typically, when we talk about CI/CD, we talk about Continuous Integration and Continuous Delivery, although it can be dependent on the organization. Ultimately, the decision to deploy software into production is a business decision, so the idea of Continuous Deployment is still overwhelming for most organizations.

In this book though, we’re going to go all out and practice full-on Continuous Deployment!

The Pipeline

Google “CI/CD pipeline,” and you will come up with a multitude of examples; I, however, like this one.
../images/501438_1_En_12_Chapter/501438_1_En_12_Fig2_HTML.jpg
Figure 12-2

The DevOps Pipeline

You may also see it depicted as a “loop,” which kind of breaks the pipeline concept but is nonetheless useful when it comes to understanding the continuous cycle of DevOps activity.
../images/501438_1_En_12_Chapter/501438_1_En_12_Fig3_HTML.jpg
Figure 12-3

The DevOps "loop"

Coming back to the whole point of this chapter (which if you haven’t forgotten is to detail how to use Azure DevOps), we are going to focus on the following elements of the pipeline.
../images/501438_1_En_12_Chapter/501438_1_En_12_Fig4_HTML.jpg
Figure 12-4

Our Focus

What Is Azure DevOps?

Azure DevOps is a collection of tools that allow development teams to build and release software. It provides the following main features:
  • Dashboards: For example, Red–Amber–Green (RAG) status of your pipeline, team members, etc.

  • Boards: Allows you to capture and plan your work using methodologies like Scrum and Kanban.

  • Repos: You can commit code (like we have done with GitHub) direct to Azure DevOps own repository.

  • Pipelines: The automated CI/CD pipeline and our focus for Azure DevOps.

  • Test Plans: End-to-end testing traceability for entire solutions.

  • Artifacts: Package management, Artefact repo, etc.

In this chapter we are going to be focusing exclusively on the “Pipeline” feature and leave the other aspects untouched. As interesting as they are, to cover these would require a separate book and is outside our scope.

Alternatives

There are various on-premise and cloud-based alternatives to Azure DevOps: Jenkins is possibly the most “famous” of the on-premise solutions available, but you also have things like
  • Bamboo

  • Team City

  • Werker

  • Circle CI

That list is by no means exhaustive, but for now, we’ll leave these behind and focus on Azure DevOps.

Technology in Context

Referring to our pipeline, in terms of our technology overlay, this is what we will be working with to build a CI/CD pipeline.
../images/501438_1_En_12_Chapter/501438_1_En_12_Fig5_HTML.jpg
Figure 12-5

The Technology mix we'll be using

Indeed, Azure DevOps comes with its own “code repository” feature (as mentioned in Figure 12-5), which means we could do away with GitHub.
../images/501438_1_En_12_Chapter/501438_1_En_12_Fig6_HTML.jpg
Figure 12-6

Alternate technology mix

So, our mix could look like the following.

Or if you wanted to take Microsoft technologies out of the picture, see Figure 12-7.
../images/501438_1_En_12_Chapter/501438_1_En_12_Fig7_HTML.jpg
Figure 12-7

Non-Microsoft mix

Going further, you can even break down the Build ➤ Test ➤ Release ➤ Deploy, etc. components into specific technologies. I’m not going to do that here.

The takeaway points I wanted to make were
  1. 1.

    The relevant sequencing of technologies in our example.

     
  2. 2.

    Make sure you understand the importance of the code repository (GitHub) as the start point.

     
  3. 3.

    Be aware of the almost limitless choice of technology.

     

OK, enough theory; let’s build our pipeline!

Create a Build Pipeline

If you’ve not done so already, go to the Azure DevOPs site, https://dev.azure.com, and sign up for a free account (be careful that you actually login to Azure DevOps and not Azure). The landing screen should look something like this (minus the projects I have).
../images/501438_1_En_12_Chapter/501438_1_En_12_Fig8_HTML.jpg
Figure 12-8

Azure DevOps landing page

Warning!

../images/501438_1_En_12_Chapter/501438_1_En_12_Figa_HTML.jpgWhen working with both Azure and Azure DevOps, one thing I’ve noticed is that the user interfaces can change rapidly. At the time of writing this (May 2020), the screenshots are correct and current, but just be aware that given the nature of these products, they can change from time to time.

For the most part, these changes will be so small as to be inconsequential, for example, instead of “Create Project,” it becomes “New Project.” Other changes, while more significant, should still be easy enough to navigate through.

Once you have signed in/signed up, click “New Project.”
../images/501438_1_En_12_Chapter/501438_1_En_12_Fig9_HTML.jpg
Figure 12-9

Create New Project

You can call it anything you like, so let’s keep the theme going and call it Command API Pipeline.
../images/501438_1_En_12_Chapter/501438_1_En_12_Fig10_HTML.jpg
Figure 12-10

Name the project and select Public Visibility

Make sure
  • You select the same “visibility” setting that your GitHub repo has (recommend Public for test projects).

  • Version Control is set to Git – this is the default.

Once you’re happy, click “Create”; this will create your project and take you into the landing page.
../images/501438_1_En_12_Chapter/501438_1_En_12_Fig11_HTML.jpg
Figure 12-11

Select Pipelines

As discussed briefly, Azure DevOps has many features, but we’ll just be using the “Pipelines” for now. Select Pipelines, then
  1. 1.
    Create pipeline.
    ../images/501438_1_En_12_Chapter/501438_1_En_12_Fig12_HTML.jpg
    Figure 12-12

    Create a new Pipeline

     

This first thing that it asks us is: “Where is your code?”

Well, where do you think?

Yeah – that’s right – in GitHub!
../images/501438_1_En_12_Chapter/501438_1_En_12_Fig13_HTML.jpg
Figure 12-13

GitHub is our code source

Be careful to select GitHub, as opposed to GitHub Enterprise Server (which as the description states is the on-premise version of GitHub).

Important

If this is the first time you’re doing this, you’ll need to give Azure DevOps permission to view your GitHub account.

../images/501438_1_En_12_Chapter/501438_1_En_12_Fig14_HTML.jpg
Figure 12-14

You'll be asked to authenticate to GitHub

Supply your GitHub account details and sign in. Once you’ve given Azure DevOps permission to connect to GitHub, you’ll be presented with all your repositories.
../images/501438_1_En_12_Chapter/501438_1_En_12_Fig15_HTML.jpg
Figure 12-15

Select the relevant API Repository

Pick your repository (my example repository is shown in Figure 12-15); once you click it, Azure DevOps will go off and analyze it to suggest some common pipeline templates; you’ll see something like that in Figure 12-16.
../images/501438_1_En_12_Chapter/501438_1_En_12_Fig16_HTML.jpg
Figure 12-16

Pipeline Templates – we'll create our own

Note

../images/501438_1_En_12_Chapter/501438_1_En_12_Figb_HTML.jpgSome readers have reported an additional step appearing here (that I cannot replicate) requesting that you approve and install Azure Pipelines. If you see this, I’d suggest you approve and proceed.

All this step will do is preconfigure the azure-pipelines.yml file for you (more on this next, but it’s basically the instructions for our CI/CD pipeline). We are going to create our azure-pipelines.yml file from the ground up so it doesn’t really matter which one you choose as we’ll be overwriting it. Anyway, select an option and continue.

Les’ Personal Anecdote

../images/501438_1_En_12_Chapter/501438_1_En_12_Figc_HTML.jpgThis is one of the areas of Azure DevOps that appears to change a lot! I have at times in my career suggested using one of the off-the-shelf configurations as shown in Figure 12-16, but they seem to change so much that I felt a safer, more stable bet would be to create our own from the ground up.

Irrespective of which template you pick you’ll get a default azure-pipelines.yml file, take a quick look (chances are yours will look different).
../images/501438_1_En_12_Chapter/501438_1_En_12_Fig17_HTML.jpg
Figure 12-17

Example Azure-pipelines.yml

Select the entire contents, and press delete; your file should now be completely empty.
../images/501438_1_En_12_Chapter/501438_1_En_12_Fig18_HTML.jpg
Figure 12-18

Empty Azure-Pipelines .yml

We are now going to add the first step to our file, which is simply to build our API Project. Before we do that, please read the warning below on formatting YAML files!

Warning!

../images/501438_1_En_12_Chapter/501438_1_En_12_Figd_HTML.jpgYAML files are white case-sensitive, so you need to ensure the indentation is absolutely spot on! Thankfully the in-browser editor will complain if you’ve not indented correctly.

Add the following code you your azure-pipeline.yml file:
trigger:
- master
pool:
  vmImage: 'ubuntu-latest'
variables:
  buildConfiguration: 'Release'
steps:
- task: UseDotNet@2
- script: dotnet build --configuration $(buildConfiguration)
  displayName: 'dotnet build $(buildConfiguration)'
Your YAML file should look like this.
../images/501438_1_En_12_Chapter/501438_1_En_12_Fig19_HTML.jpg
Figure 12-19

Our Build Step

  1. 1.

    The trigger point for the pipeline (GitHub).

     
  2. 2.

    The image we will be performing the pipeline activities with.

     
  3. 3.

    Setup a variable to specify the build configuration.

     
  4. 4.

    A script task that performs a dotnet build for “Release.”

     
We’re now ready to Click Save and run.
../images/501438_1_En_12_Chapter/501438_1_En_12_Fig20_HTML.jpg
Figure 12-20

Manual Save and run

You’ll then be presented with the following.
../images/501438_1_En_12_Chapter/501438_1_En_12_Fig21_HTML.jpg
Figure 12-21

Commit the Azure-pipelines.yml to our GitHub repo

This is asking you where you want to store the azure-pipelines.yml file; in this case we want to add it directly to our GitHub repo (remember this selection though as it comes back later!), so select this option and click Save and run.

An “agent” is then assigned to execute the pipeline; you’ll see various screens, such as in the next figures.
../images/501438_1_En_12_Chapter/501438_1_En_12_Fig22_HTML.jpg
Figure 12-22

Job Preparation on Azure DevOps

../images/501438_1_En_12_Chapter/501438_1_En_12_Fig23_HTML.jpg
Figure 12-23

In-progress Job

And finally, you should see the completion screen.
../images/501438_1_En_12_Chapter/501438_1_En_12_Fig24_HTML.jpg
Figure 12-24

Successful completion

What Just Happened?

OK, to recap
  • We connected Azure DevOps to GitHub.

  • We selected a repository.

  • We said that we wanted the pipeline configuration file (azure-pipelines.yml) to be placed in our repository.

  • We manually ran the pipeline.

  • Pipeline ran through the azure-pipelines.yml file and executed the steps.

  • Our Solution was built.

Azure-Pipelines.yml File

Let’s pop back over to our GitHub repository and refresh – you should see the following.
../images/501438_1_En_12_Chapter/501438_1_En_12_Fig25_HTML.jpg
Figure 12-25

azure-pipelines.yml is in our repo

You’ll see that the azure-pipelines.yml file has been added to our repo (this is important later).

I Thought We Wanted to Automate?

One of the benefits of a CI/CD pipeline is the automation opportunities it affords, so why did we manually execute the pipeline?

Great question!

We are asked to execute when we created the pipeline that is true, but we can also set up “triggers,” meaning we can configure the pipeline to execute when it receives a particular event.

In your Azure DevOps project, click “Pipelines” under the Pipelines section, then select the pipeline.
../images/501438_1_En_12_Chapter/501438_1_En_12_Fig26_HTML.jpg
Figure 12-26

Navigating back to Azure-pipelines.yml

Then click “Edit” on the next screen (top right).
../images/501438_1_En_12_Chapter/501438_1_En_12_Fig27_HTML.jpg
Figure 12-27

Edit the pipeline

After doing that you should be returned to the azure-pipelines.yml file (we will return here to edit it later):
  1. 1.

    Click the Ellipsis.

     
  2. 2.

    Select Triggers.

     
../images/501438_1_En_12_Chapter/501438_1_En_12_Fig28_HTML.jpg
Figure 12-28

Select our Triggers

Here, you can see the Continuous Integration (CI) settings for our pipeline.
../images/501438_1_En_12_Chapter/501438_1_En_12_Fig29_HTML.jpg
Figure 12-29

Check if Pipeline triggers are enabled for GitHub commit

You can see that the automation trigger is enabled by default (we have also configured this in the azure-pipeline.yml file), so now let’s trigger a build! But how do we do that?

Triggering a Build

Triggering a build starts with a git push origin master to GitHub, so really any code change (including something trivial like adding or editing a comment) will suffice. With that in mind, back in VS Code, open CommandsController class in the “main” CommandAPI project, and put a comment in our GetCommandItems method .
../images/501438_1_En_12_Chapter/501438_1_En_12_Fig30_HTML.jpg
Figure 12-30

Some random change

Save the file, and perform the usual sequence of actions (make sure you are in the main Solution Folder – CommandAPISolution ):
  • git add .

  • git commit -m “Added a reminder to clean up code”

  • git push origin master

Everything should go as planned except when it comes to executing the final push command s .
../images/501438_1_En_12_Chapter/501438_1_En_12_Fig31_HTML.jpg
Figure 12-31

Our Local and Remote Repos are out of sync

What does this mean?

Well remember we added the azure-pipelines.yml file to the GitHub repo? Yes? Well that’s the cause, essentially the local repository and the remote GitHub repository are out of sync (the central GitHub repo has some newer changes than our local repository). To remedy this, we simply type
git pull
Or if that doesn’t work, use
git pull origin master
This pulls down the changes from the remote GitHub repository and merges them with our local one.
../images/501438_1_En_12_Chapter/501438_1_En_12_Fig32_HTML.jpg
Figure 12-32

Pull down the azure-pipelines.yml

Indeed, if you look the VS Code file tree, you’ll see our azure-pipelines.yml file has appeared!
../images/501438_1_En_12_Chapter/501438_1_En_12_Fig33_HTML.jpg
Figure 12-33

We have azure-pipelines.yml locally now

Now that we have synced our repositories, you can now attempt to push our combined local Git repo back up to GitHub (this includes the comment we inserted into our CommandsController class). Quickly jump over to Azure DevOps and click Pipelines ➤ Builds; you should see something like this.
../images/501438_1_En_12_Chapter/501438_1_En_12_Fig34_HTML.jpg
Figure 12-34

Auto-triggered build

A new build has been queued to start – this time triggered by a remote commit to GitHub!

Once it starts, all being well, this should succeed.

We are getting there, but there is still some work to do on our build pipeline before we move on to deploying – and that is ensuring that our unit tests are run – which currently they are not.

Revisit azure-pipelines.yml

Returning to our azure-pipelines.yml file in Azure DevOps (follow the steps earlier if you forgot how to get here), you should see the following.
../images/501438_1_En_12_Chapter/501438_1_En_12_Fig35_HTML.jpg
Figure 12-35

Our azure-pipelines.yml

This is of course the code we added before; you’ll notice it doesn’t perform any testing or packaging steps, yet.

Another VS Code Extension

As we are going to be doing a bit of editing of the azure-pipelines.yml file, there are two places you can do this:
  1. 1.

    Directly in the browser (we’ve already done this)

     
  2. 2.

    In VS Code

     

The advantage that editing in the browser had was that it gave you some Intellisense-like functionality where it suggested some code snippets, etc. However, Microsoft has now released a VS Code extension to provide similar functionality in VS Code, so we’re going to install and use that (it means we do all our coding in the one place).

In VS Code, click the Extensions button, and search for “Azure Pipelines”; you should see the following.
../images/501438_1_En_12_Chapter/501438_1_En_12_Fig36_HTML.jpg
Figure 12-36

Azure Pipelines Extension for VS Code

Install it, and then open azure-pipelines.yml file that we just pulled down from GitHub.

Running Unit Tests

Returning to the steps in our pipeline view, see Figure 12-37.
../images/501438_1_En_12_Chapter/501438_1_En_12_Fig37_HTML.jpg
Figure 12-37

The pipeline we'll be building

You’ll see the suggested sequencing is Build ➤ Test ➤ Release, so let’s add that task to our azure-pipelines.yml file now.

Move back to VS Code, open azure-pipelines.yml, and append the following Task after the build Task:
- task: DotNetCoreCLI@2
  displayName: 'dotnet test'
  inputs:
     command: test
     projects: '**/*Tests/*.csproj'
     testRunTitle: 'xUNit Test Run'
So, overall, the file should like this, again with our new task step highlighted.
../images/501438_1_En_12_Chapter/501438_1_En_12_Fig38_HTML.jpg
Figure 12-38

Testing step added

The steps are quite self-explanatory, so save the file in VS Code, and perform the necessary Git command-line steps to commit your code and push to GitHub – this should trigger another build of our pipeline.
../images/501438_1_En_12_Chapter/501438_1_En_12_Fig39_HTML.jpg
Figure 12-39

Pipeline triggered again

And this time the unit tests should execute too.
../images/501438_1_En_12_Chapter/501438_1_En_12_Fig40_HTML.jpg
Figure 12-40

Testing step has succeeded

Click the dotnet test step as shown to drill down to see what’s going on; you should see something like the following.
../images/501438_1_En_12_Chapter/501438_1_En_12_Fig41_HTML.jpg
Figure 12-41

More detail on testing

Clicking the link highlighted in Figure 12-41 takes you to the test result dashboard.
../images/501438_1_En_12_Chapter/501438_1_En_12_Fig42_HTML.jpg
Figure 12-42

Testing Dashboard

Very nice! Indeed, this is the type of Information Radiator that you should make highly visible when working in a team environment, as it helps everyone understand the health of the build and, if necessary, take action to remediate any issues.

Breaking Our Unit Tests

Now just to labor the point of unit tests and CI/CD pipelines, let’s deliberately break one of our tests.

Back in VS Code and back in our CommandAPI.Tests project, open our CommandsController tests, and edit one of your tests, and change the expected return type; I’ve chosen the test here and swapped NotFoundResult with OKResult:
../images/501438_1_En_12_Chapter/501438_1_En_12_Fig43_HTML.jpg
Figure 12-43

Break our unit test

Save the file, and (ensuing you’re “in” the CommandAPI.Tests project) run a build:
dotnet build
The build of the project will succeed as there is nothing here that would cause a compile-time error. However, if we try a
dotnet test
We’ll of course get a failing result.
../images/501438_1_En_12_Chapter/501438_1_En_12_Fig44_HTML.jpg
Figure 12-44

Test has failed locally

Now under normal circumstances, having just caused our unit test suite to fail locally, you would not then commit the changes and push them to GitHub! However, that is exactly what we are going to do just to prove the point that the tests will fail in the Azure DevOps build pipeline too.

Note

In this instance, we know that we have broken our tests locally, but there may be circumstances where the developer may be unaware that we have done so and commit their code; again this just highlights the value in a CI/CI build pipeline.

So, perform the three “Git” steps you should be familiar with now (ensure you do this at the solution level), and once you’ve pushed to GitHub, move back across to Azure DevOps, and observe what happens.
../images/501438_1_En_12_Chapter/501438_1_En_12_Fig45_HTML.jpg
Figure 12-45

In-progress Pipeline (it will error out)

Then as expected, our test fails.
../images/501438_1_En_12_Chapter/501438_1_En_12_Fig46_HTML.jpg
Figure 12-46

Failed!

Again, you can drill down to see what caused the error, and if, for example, you were displaying test results on a large LCD screen, it would be immediately apparent that there is something wrong with the build pipeline and that remedial action needs to be taken. Looking at the individual steps, see Figure 12-47.
../images/501438_1_En_12_Chapter/501438_1_En_12_Fig47_HTML.jpg
Figure 12-47

Detail of failures

And then drilling further in to the dotnet test step and going to the test results dashboard (see Figure 12-48).
../images/501438_1_En_12_Chapter/501438_1_En_12_Fig48_HTML.jpg
Figure 12-48

Dashboard represents the failure

Testing – The Great Catch All?

Now, this shows us the power of unit testing in that it will cause the build pipeline to fail and buggy software won’t be released or even worse deployed to production! It also means we can take steps to remediate the failure.

So conversely, does this mean that if all tests pass, you won’t have failed code in production? No, it doesn’t for the simple reason that your tests are only as good as, well, your tests. The point that I’m making (maybe rather depressingly) is that even if all your tests pass, the confidence you have in your code will only be as good as your test coverage – ours is not bad at this stage though – so we can be quite confident in moving to the next step.

Before we do that though, revert the change we just made to ensure that all our unit tests are passing and that our pipeline returns to a green state.

Warning!

../images/501438_1_En_12_Chapter/501438_1_En_12_Fige_HTML.jpgDo not progress to the next section without ensuring that all your tests are passing!

../images/501438_1_En_12_Chapter/501438_1_En_12_Fig49_HTML.jpg
Figure 12-49

Make sure you fix your pipeline before continuing

Release/Packaging

Referring to our pipeline again, we’re now at the Release stage; this is where we need to package our build ready to be deployed.
../images/501438_1_En_12_Chapter/501438_1_En_12_Fig50_HTML.jpg
Figure 12-50

Revisit our pipeline

So once again, move back into VS Code, and open azure-pipelines.yml file, and append the following steps:
- task: DotNetCoreCLI@2
  displayName: 'dotnet publish'
  inputs:
    command: publish
    publishWebProjects: false
    projects: 'src/CommandAPI/*.csproj'
    arguments: '--configuration $(buildConfiguration) --output $(Build.ArtifactStagingDirectory)'
- task: PublishBuildArtifacts@1
  displayName: 'publish artifacts'
So overall, your file should look like this, with the new code highlighted (again watch those spaces – the VS Code plugin we just installed should help you with this).
../images/501438_1_En_12_Chapter/501438_1_En_12_Fig51_HTML.jpg
Figure 12-51

Package and publish steps

The steps are explained in more detail in the Microsoft Documents,2 but in short
  • A dotnet publish command is issued for our CommandAPI project only.3

  • The output of that is zipped.

  • The zipped artifact is published.

Les’ Personal Anecdote

../images/501438_1_En_12_Chapter/501438_1_En_12_Figf_HTML.jpgEnsure that you put in the following line:

publishWebProjects: false

When researching this, I spent about 2-3 hours trying to understand why the packaging step was not working – it was because of this! The default is true, so if you don’t include that, the step fails. ARGHHHH!

Save the file, and again: add, commit, and push your code. The pipeline should succeed, and if you drill into the successful build, you’ll see our two additional task steps.
../images/501438_1_En_12_Chapter/501438_1_En_12_Fig52_HTML.jpg
Figure 12-52

Steps shown in the running Job

Celebration Checkpoint

../images/501438_1_En_12_Chapter/501438_1_En_12_Figg_HTML.jpg Excellent work! You have completed the: build, test, and release steps of our pipeline using Azure DevOps.

Wrap It Up

A lot of ground covered here, where we
  • Setup a CI/CD pipeline on Azure DevOps

  • Connected Azure DevOps to GitHub (and ensured CI triggers were enable)

  • Added: Build, Test, and Packaging steps to our azure-pipeline.yml file

We are now almost ready to deploy to Azure!

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.226.165.131