Create two deployment workflows using GitHub Actions and Microsoft Azure.
Tags: GitHub Actions, Microsoft Azure, Workflows, CD, Deployment
This course is about continuous delivery, or CD, with GitHub Actions. CD is a crucial part of modern software development, and it can have a monumental impact on development projects.
Continuous Delivery is the practice of delivering software faster and with higher quality. Doing so successfully requires many different practices, behaviors, and technologies. GitHub Actions makes implementing CD easier, faster, and more reliable.
In this course, we focus on using workflows in GitHub Actions to deploy pull requests automatically to a staging environment, and to deploy all merged commits to production using Microsoft Azure.
Please note: You may need a credit card to create an account with Azure. If you're a student, you may also be able to take advantage of the Student Developer Pack for access to Azure. If you'd like to continue with the course without an Azure account, Learning Lab will still respond, but none of the deployments will work.
We'll answer common questions like:
- What is Continuous Delivery?
- What is a workflow file and how are workflows used with GitHub Actions?
- What are deployment triggers and how are they used with deployments?
- How can secrets store tokens?
And when you're done you'll be able to:
- Use GitHub Actions and create workflow files
- Use secrets to store tokens
- Deploy to staging and production using GitHub Actions to implement CD
In this course, we'll be walking through a CD deployment using GitHub Actions, and creating a Tic Tac Toe game!
Before you start, you should be familiar with GitHub and Continuous Integration. We recommend taking the following three Learning Labs prior to this course:
This course makes use of the following technologies:
- Azure/actions: Automate your GitHub workflows using Azure Actions
- Azure/login: Connect to Azure
- Azure/docker-login: Enable GitHub developers to deploy to Kubernetes service using GitHub Actions
- Azure/webapps-container-deploy: Enable GitHub developers to deploy to Azure WebApp for containers using GitHub Actions
- actions/checkout: Action for checking out a repo
- actions/upload-artifact: Upload artifacts from GitHub's built-in artifact storage.
- actions/download-artifact: Download artifacts from GitHub's built-in artifact storage.
- mattdavis0351/actions/docker-gpr: A GitHub Action to upload Docker images to the GitHub Package Registry.
Developers, DevOps Engineers, students, teams
We'll learn how to create a workflow that enables Continuous Delivery. You'll:
- create a workflow to deploy to staging based on a label
- create a workflow to deploy to production based on merging to main
Before you start, you should be familiar with GitHub and Continuous Integration. If you aren't sure where to start, you may want to check out these two Learning Lab courses:
Martin Fowler defined Continuous Delivery very simply in a 2013 post as follows:
Continuous Delivery is a software development discipline where you build software in such a way that the software can be released to production at any time.
A lot of things go into delivering "continuously". These things can range from culture and behavior to specific automation. In this course, we're going to focus on deployment automation.
Automation works at its best when a set of triggers work harmoniously to set up and deploy to target environments. Engineers at many companies, like at GitHub, typically use a ChatOps command as a trigger. The trigger itself isn't incredibly important.
In our use case, we'll use labels as triggers for multiple tasks:
- When someone applies a "spin up environment" label to a pull request, that'll tell GitHub Actions that we'd like to set up our resources on an Azure environment.
- When someone applies a "stage" label to a pull request, that'll be our indicator that we'd like to deploy our application to a staging environment.
- When someone applies a "destroy environment" label to a pull request, we'll tear down any resources that are running on our Azure account.
For now, we'll focus on staging. We'll spin up and destroy our environment in a later step.
In a GitHub Actions workflow, the on
step defines what causes the workflow to run. In this case, we want the workflow to run whenever a label is applied to the pull request.
- Edit the
deploy-staging.yml
file on this branch, or [use this quick link]({{ repoUrl }}/edit/staging-workflow/.github/CHANGETHIS/deploy-staging.yml?) (We recommend opening the quick link in another tab) - Change the name of the directory
CHANGETHIS
toworkflows
, so the title of this file with the path is.github/workflows/deploy-staging.yml
. If you're working on the GitHub.com user interface, see the suggestion below for how to rename. - Edit the contents of this file to trigger a job called
build
on a label
Changing the name of a directory
If you're working locally, rename your file or drag-and-drop the file into the proper directory as you'd normally do. If you're working on GitHub.com, you can change the name of a directory by changing its filename and using the Backspace key until you reach the directory, as follows:
- In the file name field, click in front of the first character in the file name
- Press Backspace or Delete on your keyboard until you see the path you want to keep. You can continue to press Backspace even if the text box with the file name is empty.
- Enter the new name for your directory.
- Enter
/
to let GitHub know this should be a new directory.
Your resulting file should be in .github/workflows/deploy-staging.yml
and it should look like this:
name: Stage the app
on:
pull_request:
types: [labeled]
jobs:
build:
runs-on: ubuntu-latest
I'll respond when you push a commit on this branch.
It looks like you took an action I didn't expect.
I expected you to {{ expected }}. Please try that to continue!
GitHub Actions features powerful controls for when to execute jobs and the steps within them. One of these controls is if
, which allows you run a job only when a specific condition is met. See jobs.<job_id>.if
in Workflow syntax for GitHub Actions for more information.
Workflows are part of the GitHub ecosystem, so each workflow run gives you access to a rich set of data that you can use to take fine-grained control.
We'd like to run our workflow on a specific label name, suppose that it's peacock. We can run the workflow based on that label name with the following single line that packs a punch: if: contains(github.event.pull_request.labels.*.name, 'peacock')
. Here's how it works:
if:
is the conditional that will decide if the job will runcontains()
is a function that allows us to determine if a value like say, a label named"peacock"
, is contained within a set of values like say, a label array["bug", "stage", "peacock", "feature request"]
github.event.pull_request.labels
is specifically accessing the set of labels that triggered the workflow to run. It does this by accessing thegithub
object, and thepull_request
event that triggered the workflow.github.event.pull_request.labels.*.name
uses object filters to filter out all information about the labels, like their color or description, and lets us focus on just the label names.
Let's put all this together to run our job only when a labeled named "stage" is applied to the pull request.
- Edit the
deploy-staging.yml
file on this branch, or [use this quick link]({{ repoUrl }}/edit/staging-workflow/.github/workflows/deploy-staging.yml?) (We recommend opening the quick link in another tab) - Edit the contents of the file to add a block for environment variables before your jobs, as follows.
env: DOCKER_IMAGE_NAME: {{user.login}}-azure-ttt IMAGE_REGISTRY_URL: docker.pkg.github.com ################################################# ### USER PROVIDED VALUES ARE REQUIRED BELOW ### ################################################# ################################################# ### REPLACE USERNAME WITH GH USERNAME ### AZURE_WEBAPP_NAME: {{user.login}}-ttt-app #################################################
- Edit the contents of the file to add a conditional that filters the
build
job using a label called "stage".
Your results should look like this:
name: Stage the app
on:
pull_request:
types: [labeled]
env:
DOCKER_IMAGE_NAME: {{user.login}}-azure-ttt
IMAGE_REGISTRY_URL: docker.pkg.github.com
#################################################
### USER PROVIDED VALUES ARE REQUIRED BELOW ###
#################################################
#################################################
### REPLACE USERNAME WITH GH USERNAME ###
AZURE_WEBAPP_NAME: {{user.login}}-ttt-app
#################################################
jobs:
build:
runs-on: ubuntu-latest
if: contains(github.event.pull_request.labels.*.name, 'stage')
I'll respond when you push a commit on this branch.
It looks like you took an action I didn't expect.
I expected you to {{ expected }}. Please try that to continue!
It looks like you took an action I didn't expect.
I expected you to {{ expected }}. Please try that to continue!
So far, the workflow knows what the trigger is and what environment to run in. But, what exactly is supposed to run? The "steps" section of this workflow specifies actions and scripts to be run in the Ubuntu environment when new labels are added.
We won't be going into detail on the steps of this workflow, but it would be a good idea to become familiar with the actions we're using. They are:
The course Using GitHub Actions for CI also teaches how to use most of these actions in details.
- In a new tab, create an Azure account if you don't already have one. If your Azure account is created through work, you may encounter issues accessing the necessary resources -- we recommend creating a new account for personal use and for this course.
Note: You may need a credit card to create an Azure account. If you're a student, you may also be able to take advantage of the Student Developer Pack for access to Azure. If you'd like to continue with the course without an Azure account, Learning Lab will still respond, but none of the deployments will work.
- Create a new subscription in the Azure Portal.
Note: your subscription must be configured "Pay as you go" which will require you to enter billing information. This course will only use a few minutes from your free plan, but Azure requires the billing information.
- Install Azure CLI on your machine.
- In your terminal, run:
az login
- Copy the value of the
id:
field to a safe place. We'll call thisAZURE_SUBSCRIPTION_ID
. Here's an example of what it looks like:[ { "cloudName": "AzureCloud", "id": "f****a09-****-4d1c-98**-f**********c", # <-- Copy this id field "isDefault": true, "name": "some-subscription-name", "state": "Enabled", "tenantId": "********-a**c-44**-**25-62*******61", "user": { "name": "mdavis******@*********.com", "type": "user" } } ]
- In your terminal, run the command below. Note: The
\
character works as a line break on Unix based systems. If you are on a Windows based system the\
character will cause this command to fail. Place this command on a single line if you are using Windows.az ad sp create-for-rbac --name "GitHub-Actions" --role contributor \ --scopes /subscriptions/{subscription-id} \ --sdk-auth # Replace {subscription-id} with the same id stored in AZURE_SUBSCRIPTION_ID.
- Copy the entire contents of the command's response, we'll call this
AZURE_CREDENTIALS
. Here's an example of what it looks like:{ "clientId": "<GUID>", "clientSecret": "<GUID>", "subscriptionId": "<GUID>", "tenantId": "<GUID>", (...) }
- Back on GitHub, click on this repository's [Secrets]({{ repoUrl }}/settings/secrets) in the Settings tab.
- Click New secret
- Name your new secret AZURE_SUBSCRIPTION_ID and paste the value from the
id:
field in the first command. - Click Add secret.
- Click New secret again.
- Name the second secret AZURE_CREDENTIALS and paste the entire contents from the second terminal command you entered.
- Click Add secret
- Back in this pull request, edit the
.github/workflows/deploy-staging.yml
file to use some new actions, or [use this quick link]({{ repoUrl }}/edit/staging-workflow/.github/workflows/deploy-staging.yml?) (We recommend opening the quick link in another tab)
If you'd like to copy the full workflow file, it should look like this:
name: Stage the app
on:
pull_request:
types: [labeled]
env:
DOCKER_IMAGE_NAME: {{user.login}}-azure-ttt
IMAGE_REGISTRY_URL: docker.pkg.github.com
#################################################
### USER PROVIDED VALUES ARE REQUIRED BELOW ###
#################################################
#################################################
### REPLACE USERNAME WITH GH USERNAME ###
AZURE_WEBAPP_NAME: {{user.login}}-ttt-app
#################################################
jobs:
build:
if: contains(github.event.pull_request.labels.*.name, 'stage')
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- name: npm install and build webpack
run: |
npm install
npm run build
- uses: actions/upload-artifact@main
with:
name: webpack artifacts
path: public/
Build-Docker-Image:
runs-on: ubuntu-latest
needs: build
name: Build image and store in GitHub Packages
steps:
- name: Checkout
uses: actions/checkout@v1
- name: Download built artifact
uses: actions/download-artifact@main
with:
name: webpack artifacts
path: public
- name: create image and store in Packages
uses: mattdavis0351/actions/[email protected]
with:
repo-token: {% raw %}${{secrets.GITHUB_TOKEN}}{% endraw %}
image-name: {% raw %}${{env.DOCKER_IMAGE_NAME}}{% endraw %}
Deploy-to-Azure:
runs-on: ubuntu-latest
needs: Build-Docker-Image
name: Deploy app container to Azure
steps:
- name: "Login via Azure CLI"
uses: azure/login@v1
with:
creds: {% raw %}${{ secrets.AZURE_CREDENTIALS }}{% endraw %}
- uses: azure/docker-login@v1
with:
login-server: {% raw %}${{env.IMAGE_REGISTRY_URL}}{% endraw %}
username: {% raw %}${{ github.actor }}{% endraw %}
password: {% raw %}${{ secrets.GITHUB_TOKEN }}{% endraw %}
- name: Deploy web app container
uses: azure/webapps-deploy@v2
with:
app-name: {% raw %}${{env.AZURE_WEBAPP_NAME}}{% endraw %}
images: {% raw %}${{env.IMAGE_REGISTRY_URL}}/${{ github.repository }}/${{env.DOCKER_IMAGE_NAME}}:${{ github.sha }}{% endraw %}
- name: Azure logout
run: |
az logout
I'll respond when you push a commit on this branch.
It looks like you took an action I didn't expect.
I expected you to {{ expected }}. Please try that to continue!
Nice job, you've done it!
It won't be "working" yet, because our next step is to work on the configuration files that our cloud provider will need. But, the logic for this workflow is complete.
- Merge this pull request
- Delete the
staging-workflow
branch
I'll respond when you merge this pull request.
It looks like you took an action I didn't expect.
I expected you to {{ expected }}. Please try that to continue!
GitHub Actions is cloud agnostic, so any cloud will work. We'll show how to deploy to Azure in this course.
We'll use the following Azure resources in this course:
- A web app is how we'll be deploying our application to Azure.
- A resource group is a collection of resources, like web apps and virtual machines (VMs).
- An App Service plan is what runs our web app and manages the billing (our app should run for free).
Through the power of GitHub Actions, we can create, configure, and destroy these resources through our workflow files.
- Edit the
.github/CHANGETHIS/spinup-destroy.yml
file on this branch, or [use this quick link]({{ repoUrl }}/edit/azure-configuration/.github/CHANGETHIS/spinup-destroy.yml?). (We recommend opening the quick link in another tab.) - Rename the file to
.github/workflows/spinup-destroy.yml
- Change the value of the
AZURE_WEBAPP_NAME:
to{{ user.login }}-ttt-app
- Commit your changes.
The file should look like this:
name: Configure Azure environment
on:
pull_request:
types: [labeled]
env:
AZURE_RESOURCE_GROUP: cd-with-actions
AZURE_APP_PLAN: actions-ttt-deployment
AZURE_LOCATION: '"Central US"'
#################################################
### USER PROVIDED VALUES ARE REQUIRED BELOW ###
#################################################
#################################################
### REPLACE USERNAME WITH GH USERNAME ###
AZURE_WEBAPP_NAME: {{user.login}}-ttt-app
#################################################
jobs:
setup-up-azure-resources:
runs-on: ubuntu-latest
if: contains(github.event.pull_request.labels.*.name, 'spin up environment')
steps:
- name: Checkout repository
uses: actions/checkout@v2
- name: Azure login
uses: azure/login@v1
with:
creds: {% raw %}${{ secrets.AZURE_CREDENTIALS }}{% endraw %}
- name: Create Azure resource group
if: success()
run: |
{% raw %}az group create --location ${{env.AZURE_LOCATION}} --name ${{env.AZURE_RESOURCE_GROUP}} --subscription ${{secrets.AZURE_SUBSCRIPTION_ID}}{% endraw %}
- name: Create Azure app service plan
if: success()
run: |
{% raw %}az appservice plan create --resource-group ${{env.AZURE_RESOURCE_GROUP}} --name ${{env.AZURE_APP_PLAN}} --is-linux --sku F1 --subscription ${{secrets.AZURE_SUBSCRIPTION_ID}}{% endraw %}
- name: Create webapp resource
if: success()
run: |
{% raw %}az webapp create --resource-group ${{ env.AZURE_RESOURCE_GROUP }} --plan ${{ env.AZURE_APP_PLAN }} --name ${{ env.AZURE_WEBAPP_NAME }} --deployment-container-image-name nginx --subscription ${{secrets.AZURE_SUBSCRIPTION_ID}}{% endraw %}
- name: Configure webapp to use GitHub Packages
if: success()
run: |
{% raw %}az webapp config container set --docker-custom-image-name nginx --docker-registry-server-password ${{secrets.GITHUB_TOKEN}} --docker-registry-server-url https://docker.pkg.github.com --docker-registry-server-user ${{github.actor}} --name ${{ env.AZURE_WEBAPP_NAME }} --resource-group ${{ env.AZURE_RESOURCE_GROUP }} --subscription ${{secrets.AZURE_SUBSCRIPTION_ID}}{% endraw %}
destroy-azure-resources:
runs-on: ubuntu-latest
if: contains(github.event.pull_request.labels.*.name, 'destroy environment')
steps:
- name: Checkout repository
uses: actions/checkout@v2
- name: Azure login
uses: azure/login@v1
with:
creds: {% raw %}${{ secrets.AZURE_CREDENTIALS }}{% endraw %}
- name: Destroy Azure environment
if: success()
run: |
{% raw %}az group delete --name ${{env.AZURE_RESOURCE_GROUP}} --subscription ${{secrets.AZURE_SUBSCRIPTION_ID}} --yes{% endraw %}
I'll respond when I detect a commit on this branch.
{% if url contains "pull" %} You can find your next steps in the [next pull request]({{ url }}). {% else %} You can find your next steps in the [next issue]({{ url }}). {% endif %}
It looks like you took an action I didn't expect.
I expected you to {{ expected }}. Please try that to continue!
It looks like you took an action I didn't expect.
I expected you to {{ expected }}. Please try that to continue!
To deploy successfully to our Azure environment, we've created a new workflow with two jobs:
- Set up Azure resources will run if the pull request contains a label with the name "spin up environment".
- Destroy Azure resources will run if the pull request contains a label with the name "destroy environment".
In addition to each job, there's a few global environment variables:
AZURE_RESOURCE_GROUP
,AZURE_APP_PLAN
, andAZURE_WEBAPP_NAME
are names for our resource group, app service plan, and web app, respectively, which we'll reference over multiple steps and workflowsAZURE_LOCATION
lets us specify the region for the data centers, where our app will ultimately be deployed.
The first job sets up the Azure resources as follows:
- Logs into your Azure account with the
azure/login
action. TheAZURE_CREDENTIALS
secret you created earlier is used for authentication. - Creates an Azure resource group by running
az group create
on the Azure CLI, which is pre-installed on the GitHub-hosted runner. - Creates an App Service plan by running
az appservice plan create
on the Azure CLI. - Creates a web app by running
az webapp create
on the Azure CLI. - Configures the newly created web app to use GitHub Packages by using
az webapp config
on the Azure CLI. Azure can be configured to use its own Azure Container Registry, DockerHub, or a custom (private) registry. In this case, we'll configure GitHub Packages as a custom registry.
The second job destroys Azure resources so that you do not use your free minutes or incur billing. The job works as follows:
- Logs into your Azure account with the
azure/login
action. TheAZURE_CREDENTIALS
secret you created earlier is used for authentication. - Deletes the resource group we created earlier using
az group delete
on the Azure CLI.
I've requested your approval on this pull request. Once you approve this, I will merge.
- Apply the "spin up environment" label to this pull request
- Wait for the GitHub Actions workflow to run and spin up your Azure environment. You can follow along in the Actions tab or in the pull request merge box.
- Once the workflow succeeds, approve this pull request
I'll respond when I receive an approval on this pull request.
Uh oh - I was looking for you to review the pull request titled Configure cloud provider.
It looks like you took an action I didn't expect.
I expected you to {{ expected }}. Please try that to continue!
Now that the proper configuration and workflow files are present, let's test our actions!
In this pull request, there's a small change to the game. Once you add the label, you should be able to see the deployment!
- On the right hand side, click Labels or the gear next to it
- Select the label titled stage
I'll respond when you apply a label to this pull request.
{% if url contains "pull" %} You can find your next steps in the [next pull request]({{ url }}). {% else %} You can find your next steps in the [next issue]({{ url }}). {% endif %}
It looks like you took an action I didn't expect.
I expected you to {{ expected }}. Please try that to continue!
Deployments to production can be manual (like through a Chat Ops command), or automated (if, say, we trust our pull request review process and we've followed continuous integration practices).
We'll trigger a deployment to the production environment whenever something is committed to main. Our main branch is protected, so the only way for commits to appear on main is for a pull request to have been created and gone through the proper review process and merged.
Let's create a new workflow that deals specifically with commits to main and handles deployments to prod.
- Edit the
deploy-prod.yml
file on this branch, or [use this quick link]({{ repoUrl }}/edit/production-deployment-workflow/.github/CHANGETHIS/deploy-prod.yml?) (We recommend opening the quick link in another tab) - Rename the file in this pull request to
.github/workflows/deploy-prod.yml
- Add a
push
trigger - Add
branches
inside the push block - Add
- main
inside the branches block - Add the same environment block as before:
env: AZURE_RESOURCE_GROUP: cd-with-actions AZURE_APP_PLAN: actions-ttt-deployment AZURE_LOCATION: '"Central US"' ################################################# ### USER PROVIDED VALUES ARE REQUIRED BELOW ### ################################################# ################################################# ### REPLACE USERNAME WITH GH USERNAME ### AZURE_WEBAPP_NAME: {{user.login}}-ttt-app #################################################
- Commit your changes to this branch
The file should look like this when you're finished:
name: Production deployment
on:
push:
branches:
- main
env:
AZURE_RESOURCE_GROUP: cd-with-actions
AZURE_APP_PLAN: actions-ttt-deployment
AZURE_LOCATION: '"Central US"'
#################################################
### USER PROVIDED VALUES ARE REQUIRED BELOW ###
#################################################
#################################################
### REPLACE USERNAME WITH GH USERNAME ###
AZURE_WEBAPP_NAME: {{user.login}}-ttt-app
#################################################
I'll respond when you push a commit on this branch.
The deployment may take a few moments but you've done the right thing. Once the deployment is successful, you'll see green check marks for each run, and you'll see a URL for your deployment.
You can wait for the deployment, or move on to the next steps in the [next pull request]({{ url }}).
If you'd like to come back and merge this once the other workflow is done, just approve this pull request and merge. 🎉
It looks like you took an action I didn't expect.
I expected you to {{ expected }}. Please try that to continue!
Great! The syntax you used tells GitHub Actions to only run that workflow when a commit is made to the main branch.
Just like with the other workflow, we'll need to build our application and deploy to Azure using the same action as before because we are working with the same Node.js
app.
Continuous delivery is a concept that contains many behaviors and other, more specific concepts. One of those concepts is test in production. That can mean different things to different projects and different companies, and isn't a strict rule that says you are or aren't "doing CD".
In our case, we can match our production environment to be exactly like our staging environment. This minimizes opportunities for surprises once we deploy to production.
- Edit the
deploy-prod.yml
file on this branch, or [use this quick link]({{ repoUrl }}/edit/production-deployment-workflow/.github/workflows/deploy-prod.yml?) (We recommend opening the quick link in another tab) - Add a
build
anddeploy
job to the workflow
It should look like the file below when you are finished. Note that not much has changed from our staging workflow, except for our trigger, and that we won't be filtering by labels.
name: Production deployment
on:
push:
branches:
- main
env:
DOCKER_IMAGE_NAME: {{user.login}}-azure-ttt # Must not exist as a package associated with a different repo!
IMAGE_REGISTRY_URL: docker.pkg.github.com
#################################################
### USER PROVIDED VALUES ARE REQUIRED BELOW ###
#################################################
#################################################
### REPLACE USERNAME WITH GH USERNAME ###
AZURE_WEBAPP_NAME: {{user.login}}-ttt-app
#################################################
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- name: npm install and build webpack
run: |
npm install
npm run build
- uses: actions/upload-artifact@main
with:
name: webpack artifacts
path: public/
Build-Docker-Image:
runs-on: ubuntu-latest
needs: build
name: Build image and store in GitHub Packages
steps:
- name: Checkout
uses: actions/checkout@v1
- name: Download built artifact
uses: actions/download-artifact@main
with:
name: webpack artifacts
path: public
- name: create image and store in Packages
uses: mattdavis0351/actions/[email protected]
with:
repo-token: {% raw %}${{secrets.GITHUB_TOKEN}}{% endraw %}
image-name: {% raw %}${{env.DOCKER_IMAGE_NAME}}{% endraw %}
Deploy-to-Azure:
runs-on: ubuntu-latest
needs: Build-Docker-Image
name: Deploy app container to Azure
steps:
- name: "Login via Azure CLI"
uses: azure/login@v1
with:
creds: {% raw %}${{ secrets.AZURE_CREDENTIALS }}{% endraw %}
- uses: azure/docker-login@v1
with:
login-server: {% raw %}${{env.IMAGE_REGISTRY_URL}}{% endraw %}
username: {% raw %}${{ github.actor }}{% endraw %}
password: {% raw %}${{ secrets.GITHUB_TOKEN }}{% endraw %}
- name: Deploy web app container
uses: azure/webapps-deploy@v2
with:
app-name: {% raw %}${{env.AZURE_WEBAPP_NAME}}{% endraw %}
images: {% raw %}${{env.IMAGE_REGISTRY_URL}}/${{ github.repository }}/${{env.DOCKER_IMAGE_NAME}}:${{ github.sha }}{% endraw %}
- name: Azure logout
run: |
az logout
I'll respond when you push a commit on this branch.
It looks like you took an action I didn't expect.
I expected you to {{ expected }}. Please try that to continue!
Nice job, you've done it!
- Merge this pull request
- Delete the branch
I'll respond when you merge this pull request.
It looks like you took an action I didn't expect.
I expected you to {{ expected }}. Please try that to continue!
Now, we just have to wait for the deployment to occur, and for the package to be published to GitHub Packages. When it's completed, you should be able to see it in the [Packages]({{ repoUrl }}/packages) section of your repository. You can get the deployment URL in the [Actions]({{ repoUrl }}/actions) log, just like the staging URL.
Throughout the course you've spun up resources that, if left unattended, could incur billing or consume your free minutes from the cloud provider. Let's tear down those environments so that you can keep your minutes for more learning!
- Apply the destroy environment label to this pull request.
I'll respond when you apply a label to this pull request.
It looks like you took an action I didn't expect.
I expected you to {{ expected }}. Please try that to continue!
Now that you've applied the proper label, let's wait for the GitHub Actions workflow to complete. When it's finished, you can confirm that your environment has been destroyed by visiting your app's URL, or by logging into the Azure portal to see it is not running.
This course is now complete! I'll stop responding but the fun doesn't have to stop here.
Now...[what will you learn next]({{ host }}/courses)?