How To Deploy Your Application To Azure Using GitHub Actions | CI/CD Pipeline
AI Summary
This video demonstrates how to build a CI/CD pipeline from scratch using GitHub Actions to deploy a .NET 6 Web API to Azure App Service. The presenter walks through creating a GitHub Action workflow, configuring Azure App Service, and securely deploying the application using publish profiles stored as GitHub secrets.
Milan introduces the goal: build a CI/CD pipeline using GitHub Actions to deploy a .NET 6 Web API to Azure App Service.
The API has Swagger configured and a single endpoint returning current UTC time. Swagger is enabled for all environments.
Navigate to Actions tab in GitHub repository, choose to set up a workflow manually. Name the action 'publish' with a rocket emoji.
Add two triggers: workflow_dispatch (manual) and push to main branch.
Define job 'publish' on ubuntu-latest. Steps: setup .NET 6.x, restore, build (Release, no restore), publish (Release, no build).
The action runs successfully: restore, build, publish steps complete. The YAML file works for any .NET Web API.
In Azure portal, create App Service named 'current-time-service' with .NET 6, Linux, Free tier, Central US.
From Azure App Service dashboard, download the Publish Profile (XML file) for authentication.
Use 'azure/webapps-deploy@v2' action. Set app-name, publish-profile, and package path. Use environment variables for app name and package path.
In GitHub Settings > Secrets, create a new repository secret 'AZURE_PUBLISH_PROFILE' with the downloaded publish profile content.
Commit the updated workflow. The action completes successfully. Visit the Azure URL with /swagger to see the API live, returning UTC time.
By following this tutorial, you can set up a fully automated CI/CD pipeline that builds and deploys a .NET application to Azure App Service on every push to the main branch, using GitHub Actions and secure secrets management.
Clickbait Check
95% Legit"The title accurately describes the content: a step-by-step guide to deploying a .NET app to Azure using GitHub Actions."
Mentioned in this Video
Tutorial Checklist
Study Flashcards (8)
What are the two triggers defined in the GitHub Action?
easy
Click to reveal answer
What are the two triggers defined in the GitHub Action?
Workflow dispatch (manual) and push to main branch.
02:24
What is the purpose of the 'no restore' argument in the build step?
medium
Click to reveal answer
What is the purpose of the 'no restore' argument in the build step?
It avoids restoring dependencies again because they were already restored in the previous step.
04:24
What is the name of the Azure App Service instance created in the video?
easy
Click to reveal answer
What is the name of the Azure App Service instance created in the video?
current-time-service
07:24
How is the publish profile securely stored and accessed in GitHub Actions?
medium
Click to reveal answer
How is the publish profile securely stored and accessed in GitHub Actions?
It is stored as a GitHub secret named 'AZURE_PUBLISH_PROFILE' and accessed via ${{ secrets.AZURE_PUBLISH_PROFILE }}.
12:08
What is the runtime stack and operating system used for the Azure App Service?
easy
Click to reveal answer
What is the runtime stack and operating system used for the Azure App Service?
.NET 6 on Linux.
07:37
What is the purpose of the 'no build' argument in the publish step?
medium
Click to reveal answer
What is the purpose of the 'no build' argument in the publish step?
It avoids building the application again because it was already built in the previous step.
04:56
What action is used to deploy the application to Azure App Service?
medium
Click to reveal answer
What action is used to deploy the application to Azure App Service?
azure/webapps-deploy@v2
09:25
What is the URL path to access the Swagger UI after deployment?
easy
Click to reveal answer
What is the URL path to access the Swagger UI after deployment?
/swagger
13:31
🔥 Best Moments
Adding a rocket emoji to the action name
A fun touch that shows personalization in technical workflows.
02:12Call to smash like and subscribe
A humorous plea for engagement before revealing the secret solution.
11:29First successful API response from Azure
The moment of validation when the deployed API returns the current UTC time.
13:45Full Transcript
Download .txt[00:00] Hi everyone, my name is Milan and today I'm going to show you how you can build a CICD pipeline from scratch. We're going to be using GitHub Actions to deploy our .NET 6 Web API to Azure,
[00:14] where it's going to be running inside of an Azure App Service instance. So let's dive straight into the code and see how we can make this happen. I already prepared a .NET 6 Minimal API that we are going to be deploying to Azure through GitHub Actions.
[00:30] But first, let's see what I actually have inside of our web API. I'm configuring Swagger at the start, and we're going to be using that as interface for our API. I'm going to remove this check to only add Swagger in development, because I want it to be running when we deploy our API to Azure.
[00:49] I only defined one minimal API endpoint, and all this endpoint does is it returns the current UPC type. I'm going to run the application and quickly show you that what we have here is actually working.
[01:03] So we are inside of our Striker UI, where we have only one endpoint that returns the current UTC time. And when I execute it, we get the current UTC time in the response body.
[01:15] If I keep executing it again and again, you're going to see that the time is updating. So now I want to focus on adding our CICD pipeline using GitHub Actions. and then we're going to deal with deploying our API to Azure.
[01:31] I'm in the GitHub repository of our current time service and I'm going to add a GitHub Action from this UI. If you go to the Actions tab, you will get access to a bunch of pre-configured GitHub Actions.
[01:45] If you add this one, it's going to include build and test steps for your .NET application. Another one that could be interesting is deploying your container to an Azure web app. but we're going to build our pipeline ourselves.
[01:59] So I'm going to click here to set up a workflow on my own. So let's see how we can define a GitHub Action to publish a Web API to Azure. First, I'm going to give our Action a name.
[02:12] I'm going to call it publish and I'm going to add an emoji because I think it's pretty cool when you can add a rocket to your GitHub Action. We need to define a trigger for our Action.
[02:24] So I'm going to add two figures. One is going to be Workflow Dispatch, and this is going to allow me to run my action manually, on demand. And I also want to run my action whenever a push happens, and I can specify which branches I want the action to figure on.
[02:40] And I'm going to say I only want you to run the action when there's a push to the main branch. Now I need to define the next action, which is the Jobs. This is going to be our actual pipeline. I need to give it a name, for example, publish, and now I need to define our published job.
[02:56] First, I want to say where I want this job to run in terms of the operating system. I'm going to specify the latest Ubuntu version as the operating system where I want our GitHub Action to execute, and now I need to define a list of steps to get our application built
[03:12] and published to Azure. Now, I want to set up our .NET environment, so I'm going to make a name step, which is to be setup.net. It's going to use an existing action which is going to be setup.net and I'm
[03:27] going to use version 3 of this action and I need to specify which .net version I want to use. I going to say I want to use the version 6 where x is the wild card and resolves to the latest version Now that I have a version setup we want to restore our application so I going to
[03:46] create another step, which is going to be restore, and I want to use the run argument here because I want to execute my custom actions, so I'm going to say .NET restore and specify
[03:58] the path to our solution file, which is going to be current-time-service.sln, and this will take care of restoring our application. Now that we have our application restored, we want to build it.
[04:11] So I'm going to run .NET build and specify the phone path to our solution, so current-time-service.sln, and I want to specify the configuration for the build.
[04:24] I want to build in the release configuration, and I'm also going to specify the no restore argument because I have just restored the application in the previous step. So we have the restore step, the build step, and now I want to publish our action.
[04:38] So I'm going to add a new step, which is going to be publish, and in the run we want to call .net publish, specify the path to our solution file, current client service .sln. We want to publish in the release configuration and we're going to specify no build as the
[04:56] argument because we have already built the application in the previous step. So this is looking good so far. I think we are ready to commit our GitHub action and see if it is actually working. I'm going to commit it through the UI here and we're going to go to the Actions tab and
[05:12] see our action running. So I'm inside of the action that is running right now. You can see that the resource step has completed, the build step completed successfully, and the publish step completed, completing our GitHub action.
[05:27] So the YAML file that we just defined worked properly, and you can reuse this same GitHub action for any .NET Web API. To show you that this is actually triggering whenever I commit something to the main branch,
[05:39] I'm going to move to our application, and here I'm just going to add our simple comment so that we have something to commit. So I'm going to say get utc to describe the endpoint that we are defining in this line.
[05:53] Let's go ahead and commit this change and you'll see that this is going to trigger our action on GitHub. So I'm using GitHub Actions as my git GUI and I'm going to commit our comment and push
[06:06] it to GitHub and this is going to trigger our action. Now I'm going to move to GitHub and in the Actions tab you can see that we have our latest commit. It is now running. If I go inside, we're going to see the publish action executing.
[06:23] As you can see, our action completed in 20 seconds, which is pretty fast. Usually, you want to add another step between build and publish, which is going to run your automated tests, but I'm going to leave that for a separate video, where I'm going to show you how to run
[06:40] your unit tests, generate a code coverage report, and publish that to some service that allows you to store and view your code coverage results. So be on the lookout for that. Now that we have our GitHub Action configured and running, we want to set up our Azure App
[06:57] Service. So I'm going to head over to Azure, where we're going to create our App Service instance. So I'm here in Azure, and I want to create an Azure App Service where we're going to run our web API I already prepared a resource group where our Azure App Service is going to live I going to specify a name for our service I going to try to come up with something with current time service
[07:24] We're actually lucky and this isn't taken. I'm going to use code as a publish. The runtime stack is 1.6. We want to be running on Linux and let's say in the
[07:37] central US. I want to change the plan for our app service to be a free instance so that we don't rack up any costs while testing this. And I think we can go to the
[07:49] review and create step. So whenever you're creating a service on Azure, make sure that you carefully review what you're doing. So again, we are using a free Azure app service instance. We call it current time service and we need to
[08:04] remember this name because we're going to use it later for deployment. It's going to be running on a Linux machine somewhere in the central US. So let's create this instance. And this is going to take some time, so be patient when you're trying this out at home.
[08:19] So here's our Azure App Service that I just created. This is the URL where you can find our application. And if I go to that URL, we are going to be met with a dummy application
[08:32] that Azure prepares for us, but we're going to replace that with our actual Svager UI when we configure deployment for our application. What I need from our Azure App Service is this Publish Profile here.
[08:44] We're going to be using that to configure our GitHub Action to deploy our code to this Azure App Service instance. So I'm going to download the Publish Profile, which is just an XML file, and now we're going
[08:58] to update our GitHub action to use this published profile to deploy our application. I'm back in GitHub, and I'm editing our GitHub action to add the deployment step to Azure. And we already
[09:13] have an action from Azure that we can use for configuring the deployment. So I'm going to create a new step here and call it deployment. And the action that we are going to use is the web apps
[09:25] deploy action, so I'm going to specify it here. webapps slash deploy and I'm going to use the version 2, which is the latest version. And we need to specify a few arguments here so that our deployment works correctly.
[09:39] First, we need to specify the name of our application and the argument is app name. We're going to leave it empty for just a moment. Then we want to specify the published profile. I'm going to add that.
[09:52] And the last part that we need is the package, which is going to be the location where our application is actually published. So if you recall from a moment ago where we created our Azure App Service,
[10:05] we called it Current Time Service. So I'm going to specify that here. A better approach would probably be to create an environment variable. And I'm going to show you now how you can do that. So right before defining the job, I'm going to define a few environment variables.
[10:20] The first variable that we're going to define is the Azure Web App name, and I'm going to give it the value of current time service. Then I'm going to create a new one, which is going to be the path where our application
[10:33] is going to be published. I'm going to call it Azure Web App Package Path, and I'm going to give it the value of publish. So, let's use these environment variables in our pipeline.
[10:46] So how we can specify our environment variables here is like this. We also going to do the same for our package path and we shouldn forget to specify this in the previous step where we actually published our application so I going to do the same for our package path and we shouldn forget to specify this in the previous step where we actually publish our application So I going to add the output
[11:01] argument and use the environment variable that we just defined above. So I want our application to be published to the path that I specified here, and I'm using that same path here in the deployment step. And the last missing piece of the puzzle is our publish profile.
[11:17] You should never expose this in your GitHub Action because this would be linking sensitive information in your code. So how do you keep this value secret while being able to use it inside of your GitHub
[11:29] Action? Before I give you the answer, I'm going to need you to smash that like button and also subscribe to my channel to give me the strength to complete this video and get our application
[11:41] published and running on Azure. So GitHub has a way for us to store sensitive information inside of GitHub Secrets. I'm going to open the Settings tab in a new browser tab.
[11:55] And if you take a look at the menu here, we have a Secrets drop-down and we want to define a new secret for our GitHub action. I'm going to click the New Repository secret and I'm going to place our published profile
[12:08] inside of a secret. I'm going to name the secret Azure Publish Profile, and as the secret value, I'm going to paste in the Publish Profile that I downloaded from the Azure App Service dashboard.
[12:21] So I created the action, and you can see it here. I called it Azure Publish Profile, and we can access it as an environment variable inside of our GitHub actions. We are back in our YAML file,
[12:33] and we just need to specify the Publish Profile. We're going to do that by accessing the secrets, and accessing the Azure Publish Profile secret, which I just created. This completes the deployment step for our pipeline,
[12:48] and I'm going to commit this and run our pipeline, and hopefully this is going to get our application published on Azure. You can see that our updated GitHub action completed successfully.
[13:02] We managed to build and publish our web API, and we properly configured our deployment step to publish our action to Azure App Service. To be able to do that, we use the publish profile that we downloaded from the Azure App Service dashboard
[13:16] and we started as a GitHub secret, which we used in the deployment step to be able to authorize our deployment. I'm back in Azure and I'm going to open up our website again and I'm going to visit the Swagger URL.
[13:31] So you can see that our web application is live and running on Azure. If you made it this far into the video, I want to congratulate you for speaking with me because now we're going to fire our first request to the API and hopefully we're going
[13:45] to get back our response. And indeed, we do get the current UTC time. Let's fire it a few more times to be sure that it's working. I hope that you enjoyed this video of setting up a CICD pipeline from scratch.
[14:00] I usually only share the code with my Patreon supporters, but this time I'm going to make the repository open source and available to everyone. I'm going to leave the link to the repository in the description of this video, but still
[14:13] consider supporting me on Patreon, because creating these videos is a lot of work and every new Patreon gets me one step closer to becoming a content creator full time.
[14:25] Make sure that you take a look at these two videos that I prepared for you, and until next time, stay awesome!