Deploying to Azure App Service with GitHub Actions
Tags: azure, github, devops
Published: 2020-07-02 16:37:38

{% youtube tQv6Y5jLUlM %}

Get started with GitHub Actions in this step-by-step tutorial on deploying to Azure App Service. This video will show you how to hit the ground running with GitHub Actions.

Looking for more resources? Here are a few key resources that will help you get started with GitHub Actions:

* [GitHub Actions for Azure](https://docs.microsoft.com/en-us/azure/developer/github/)
* [Action Samples for Deploying to Azure](https://github.com/Azure/actions-workflow-samples/tree/master/AppService#choose-a-sample-workflow-template)
* [Core Concepts for GitHub Actions](https://help.github.com/en/actions/getting-started-with-github-actions/core-concepts-for-github-actions)

**Full Transcript:**

Mike Pfeiffer:
All right. So let's review the infrastructure we're going to deploy to. When we're using workflows and GitHub Actions, we could deploy infrastructure, but we're not going to do that in this video. We're just going to focus on the basics. We're going to deploy to some existing infrastructure in this resource group right here and I'll explain this for you. This is just a simple web application. So with an app service, you can see we've got an app service plan and an application insights resource. So everything we need to run a basic .NET Core web application, let me show you how I built this. I went over to app services and just went up to add. And on the screen, what I did is I just filled out all the information, I created a resource group, I gave my web app a name, I select code for the publication option.

Mike Pfeiffer:
And then for the runtime stack, I did .NET Core 3.1. That defaulted to the Windows operating system and then I just changed the region to a region that's close to me, I did West US 2. The region is important, but the other important thing here is the SKU size. So we're doing an S1 SKU size. So basically, the entry level production grade service plan option. So that's the important thing; it's the operating system, the runtime stack, and I just run off and create a dime. And so with that, let's head over to GitHub. I'm going to get out of this because I've already got an app service that we're going to use. We'll go over to GitHub repositories. On signed in to GitHub, I'm going to create a brand new repository here, and I'm just going to call this appservicedemo.

Mike Pfeiffer:
I'll scroll down and we'll keep this as a public repository. And then what we'll do is we'll initialize this repository with a README so we can eventually document everything. We'll add a gitignore based on the Visual Studio gitignore file. And then I'll add a license, just say, hey, this is an Apache License open source project. So let's go ahead and create this repository and what this repository now builds, we're ready to start setting things up. So first thing I'm going to do is I'm going to go over to settings on the top. We're going to set up a secret. So over here on the left hand side, go to secrets for this GitHub repository, and we're going to build a new secret. I'm going to call this AZURE_CREDENTIALS. You can see I've already done this in the past for some other repository, so it's caching that.

Mike Pfeiffer:
And we need to put the value for a service principle into this box. So we'll use service principle delegation to make sure that GitHub Actions can authenticate to our Azure subscription and do a deployment. And the way that we're going to do that here is just jumped into the command line interface. So I'll open up the cloud show here. Let me go ahead and maximize this. It's coming up as PowerShell because I was using that before. Let me switch it over to Bash because I'm going to use the AZ CLI. And the first thing I'm going to do is an AZ group list because I want to delegate control to a specific resource group. In this case, the resource group called webapps-dev-rg. So I'm going to scroll up here, I'm going to get this unique ID for this resource group.

Mike Pfeiffer:
So this will include the subscription ID, the actual name of the resource group, and this will be the scope for the service principle that we build and set up. So let's do this. We'll go ahead and run az ad creates or az ad sp creates-for-rbac. So we're going to create a service principle and set up the RBAC role assignment at the same time. I'm going to say -n here. So what's the name of the service principle? So we'll just say AppsSvcDemo, and then we're going to go --roll to indicate the role based access control role. In this case, I'm just going to say contributor. So the contributor role, and then the important part here is the scopes. And so in this case, I'm just going to do one scope, it's just going to be the resource group that we were looking at a second ago. So I'm going to paste in the resource ID for this particular resource group.

Mike Pfeiffer:
And then finally, this is important. Last thing on the list here, one last parameter, we're going to say sdk-auth. And so far, this looks good. Let me go and hit enter. Let's make sure this actually works. So it's creating the service principle, creating the role assignment and here's our output. So this is the important part. This JSON output is what we're going to use for our secret in the GitHub repository. So I'm just going to copy this, we're going to head over to secrets and in this field here, we'll go ahead and click on add, and there we go. So keep in mind that you're not going to be able to retrieve that data. So we've created the secret with this information, right? And it's not going to be viewable in this window here. Also, notice that the secrets are going to be encrypted and they're only exposed to selected actions.

Mike Pfeiffer:
So it's not like we're going to expose this information, this sensitive data to a bunch of people. But now that we understand the infrastructure, we've got our GitHub repo set up, let's move to the next step and we'll actually start setting up an ASP.NET Web Application project. All right. So back in the code tab here in this repository, what we're going to do is we're going to clone this locally and then we're going to add an ASP.NET project, push it back up to GitHub. So I'm going to go to a clone or a download section and just grab the clone URL. I'm going to jump over to my terminal and in an empty folder here, I'm going to do a git clone on that clone URL. I'm going to switch into that directory. So cd appservicedemo, and then I'm going to run code space period. So I've got Visual Studio Code installed.

Mike Pfeiffer:
I'm going to open this folder as a workspace in Visual Studio Code. So now that I'm in Visual Studio Code, what we'll do is open up a terminal here and inside this empty folder, what we're going to do is dotnet new webapp. So this will create a basic ASP.NET Core Web Application using one of the default templates that's available. This is going to be an ASP.NET Core razor pages web application. Don't worry if you're not a programmer, that's not really important. We're not going to do any big changes to this application. Let me close out of this and what we're going to do here, now that we've got some application code, I'm going to add a new file to this project. So I'm going to click on new file here and we're going to create this file in a hidden folder called GitHub/workflows/main.yml, main.yml.

Mike Pfeiffer:
And that takes us into the editor here. So let's go ahead and collapse this so we can kind of see what's going on. So let's go ahead and define this workflow file. What I'm going to do here is I'm going to start off writing some yml. I'm going to say name, what's the name of this workflow? We're going to call this Deploy ASP.NET CORE. And then the next thing we're going to do is we're going to use the on command here to basically create a trigger. So we're going to say on push, anytime we push two branches called master. In this case, just the master branch. Anytime we do a push to the master branch, we're going to kick off this workflow. So that looks good. I'm not going to do anything more sophisticated than that. And then we're going to set up some environment variables in this workflow.

Mike Pfeiffer:
So underneath env, I'm going to say, AZURE_WEBAPP_NAME, and I'm going to set this to csweb06192020, And that was the actual web app name in the portal. So this is my existing infrastructure. From there, I'm going to create another variable called AZURE_WEBAPP_PATH, and basically, I'm just going to set this to the current folder. And we're going to use this variable when we're doing things like building the project, producing the published files that we're going to deploy, all that stuff. And then I'm going to specify the dotnet version that we're going to use. So I'm going to create a variable called DOTNET_VERSION. I'm going to set this to 2.2.101. And let me show you why I'm doing that. Let me bring up my terminal again, let's clean this up a little bit so we can see what's going on.

Mike Pfeiffer:
I'm going to do a dotnet --version. You can see that this is currently set to 2.2.101. Now, remember when I built the app service, I was showing you that I use the .NET Core 3.1 runtime. .NET Core is backwards compatible. I'm still using an old version of .NET Core on this machine. I need to update that, but I wanted to be explicit and kind of let you know what's going on here exactly with this. So that's why I'm using a specific version. If you're using .NET 3.1, that's perfectly fine. And so let's kind of continue here. And what we're going to do now is we're going to define our jobs. This workflow is just going to have one job. So underneath jobs, I'm just going to say, build-and-deploy. We could call the job whatever we want here and once we define the build and deploy job, we'll hit return and what we're going to say is runs-on.

Mike Pfeiffer:
What does this actually run on? What does this job run on? So we're going to use ubuntu-latest. So if you're familiar with Azure Pipelines, you know that there's the concept of hosted agents, self hosted agents, and in GitHub Actions and GitHub workflows, we have the same things. We have runners. So we're going to use an Ubuntu system to run this workflow and it's going to run all the steps inside this job. So we're going to say steps:, and then hit return. And then down here, this is where we'll indicate our steps. These steps are going to be GitHub Actions, and here's kind of the way this works. So steps, this is going to be like a list of steps, right? So when we're doing steps, we want to indicate these with a dash.

Mike Pfeiffer:
So we'll say, this first step uses, and here, we're actually going to define the name of the action that we want to use. So what we're going to say is actions/checkouts, and this is a specific GitHub Action that'll allow us to check out the code from the GitHub repo. So think about it this way, we commit code to the master branch, that kicks off the workflow because we've got a trigger for that, and then once we start running our job, we'll get access to an Ubuntu machine and the first thing we're going to do is check the code out from the repository. So we can then go build the application, deploy it to Azure. Now, just to show you, let me copy this. Let me go back to my browser. And if you just search for these actions, there's tons of them out there, of course. But if you search for these, you'll find them on GitHub.

Mike Pfeiffer:
And so this particular one is well documented and all of them should be well-documented. When you come down here, when you're looking at one, they'll talk about how it works, what the usage is, what the syntax is, what the supported inputs are, all that kind of stuff. So let me close out of this and go back over to Visual Studio Code, and that's step one. So that's the first thing we need to do. We don't need to fill out anything else for that particular action. The next one, we're going to basically specify a name here. So when we're looking at the logs during kind of a real time execution of a workflow, or later on after the fact, we can identify what it is in that sequence of steps that's actually happening. So I'm going to say, this one is a step forward logging into Azure. So Login via Azure CLI.

Mike Pfeiffer:
And so this step is something that uses an action called azure/login, and then what I'm going to do here is say @v1. As time goes on, there's going to be different versions of these actions and sometimes, it makes sense to be explicit on the actual version of the action itself, as well as the .NET Core runtime, all that kind of stuff, right? Does that make sense? You want to make sure that it's consistent and it's repeatable, and that's why I'm using the version one here. New versions might come along with different capabilities, but this will ensure we don't have any breaking changes. Now, when we use this action, we're going to use this action with certain credentials. So I'm going to say, with, hit return, and we're going to say creds. Creds are going to be equal to the credentials we've got stored in the secrets in the repository.

Mike Pfeiffer:
So the value I'm going to use here, and I would use this syntax when referencing my variables as well, so a dollar sign, a couple of open and closed curly braces, and inside here, I'll be able to access my secrets or work with my secrets. So I can say, secrets.AZURE_CREDENTIALS. And then that action will be able to use those stored credentials based on the service principle, recreate it and all that stuff. So it looks good. We'll hit return and then what we're going to do is add another step. So this one will be called SETUP .NET CORE. So this will make sure we've got the right .NET Core SDK runtime available on our runner to do the build and all that stuff. So we need to configure this one. So in addition to the name, we actually have to set what it uses, right?

Mike Pfeiffer:
So this step uses an action. So it's actions/setup-dotnet, and just like before, I'm going to pin this to version one. And then finally, what is this going to actually use? What we're going to do this with, we're going to say, dotnet-version. We're going to set that to what I did before, which is in my variables, right? So if we want to reference our variables in this workflow, same syntaxes before. But I'm going to say, env., and then it's going to be, DOTNET_VERSION. That was one of the variables, right? That I put up here. So we're just referencing it right there. So that's going to get the .NET Core SDK ready for us so we can build our application. And then our next step is actually going to be to do that. So we're going to say, name: dotnet build and publish, and with this action, what we're going to do here is we're going to run a command.

Mike Pfeiffer:
So what I'm going to do here is say, run, I'm going to do a pipe character, hit return, this is going to be an inline script. So we're going to say, let's run a dotnet build. We'll make this a release configuration. So we'll say configuration release, and then we'll do, dotnet publish, and then we'll say, -c, this is going to be a release and we're going to say, -o for the output location. So again, referencing variables here inside this workflow, we'll say, env.AZURE_WEBAPP_PATH. Now, I'm going to do something a little bit different here because I want to reference an actual sub folder of that path. So what I'm going to do here is just make a slight change. Inside single quotes, what I'll do is place that and then say, /myapp. So in a sub folder, what we'll do there is we'll publish the zip file that will be our deployment source for our application.

Mike Pfeiffer:
And then all we need to do beyond that is simply deploy this .NET application. So this step is going to be specific doing a deployment in Azure. We're going to say, deploy to App Service. This task, or this step uses the azure/webapps-deploy action. We're going to use the version two version of this action. And we're going to use this action with two things; an app named, and then we'll reference our variable, our actual application name that's in this workflow document. We'll say env.AZURE_WEBAPP_NAME. And then from here, we'll say package, and then that's going to be our path. So I'm going to actually just steal it from right here. So grab that, plug that in right here, click on save and so far, so good. So now that we've built this workflow configuration, let's go to the next step, which will be committing our code, pushing it to GitHub.

Mike Pfeiffer:
All right, so we're ready to publish this thing. Let's go ahead and bring up the terminal. We're going to just clear the screen here and we're going to do a git ad. I'm just going to go ahead and stage all these changes. We're going to do a git commits -m. We'll just say, this is the initial commit, and then we'll clear this and then we'll do a git push. This will send the code back up to the repository in GitHub and that'll kick off our workflow, right? Because we just committed a change to the master branch. So let's go back over to the browser. Let's do a refresh on this page. Remember, this is the kind of old version. Now, we see all of our code that's been pushed up into GitHub in this repository, and here's the key to understanding Actions and working with this. If we come over here to Actions, we can see that we've got this initial commit, but we're seeing that there is a failure, right?

Mike Pfeiffer:
So let's dig into this, take a look down here, and it says the workflow is not valid. And so line 18 is this guy right here, that's the action for checking out the code. And you know what? I've got a typo here and it's a good thing we run into this because we always run into these little issues, right? So let's do this. Let's close out of the terminal. Let me scroll up here. What I should have done for this checkout action is done @master because I want to check out the master branch. So let me save that. Let's reopen the terminal and we'll just do what we did before. We'll go ahead and stage that change, we'll do a git commits -m, updates yml file, and then a git push. In the real world, I would probably do a better commit message than that, but you get the idea. So we just updated that so let's go back over. Let's go back to actions to do a refresh.

Mike Pfeiffer:
We can see this one's queued. Let's drill into this one. And then here we can see everything that's going on, right? So we got a job in progress. We don't have any artifacts just yet, but let's go over to build and deploy this job and then we can monitor what's going on. So we can see that the setup is done, we're checking on our code, and now we're trying to log in to Azure with the CLI and it looks like that worked just fine. And now it's setting up .NET Core and it's going to run through the whole publication process. So let's give this thing just a second to go. All right. Couple of minutes later, almost everything worked except the deployment to App Service, so that's kind of important, right? So if we drill into that, we can see that it's complaining because that resource doesn't exist. Actually, you must have fat fingered that. It looks like the year was wrong.

Mike Pfeiffer:
If I go back over here just to confirm it, let me close out of the shell. Here's the actual name of the webapp that I should be trying to deploy to. So one last time, let's go back over and let's update this document. I'll take the webapp name, save it, and then of course I could have done this just straight in GitHub, but you get the idea, right? So we'll go ahead and say, git add, git commit -m, fixed apps service name, and then git push. So that'll kick off our workflow and then we'll go back and check one last time. Let's go to GitHub, let's go to actions. We can see this one is now running. So let's keep an eye on this and see what happens next. All right. Couple of minutes later, it looks good. No errors. If we jump over to the Azure portal, here's the URL for the app, right?

Mike Pfeiffer:
So let's head over there, and there we go. There is the default kind of template for ASP.NET Core Web Application. Everything worked just fine. So now you see kind of the process of just doing a basic setup, right? Deploying a simple application. And in future videos, I'll take you through this in more depth. But I will leave this repository here, if you want to come in here and grab the workflow file. And keep an eye on this channel, I'll be posting a lot more stuff about Azure DevOps, GitHub Actions and a whole lot more.

** This article was originally published on CloudSkills.io **
[https://cloudskills.io/blog/github-actions-azure](https://cloudskills.io/blog/github-actions-azure)