You take some time to write a web API and love using it locally, but you want to share it with the world. Manually deploying an API is brutal, so what's the best and most efficient way of automating the deployment? Writing Python code is one piece of the puzzle. Deploying the code so the world can use the application, or so frontend can interact with backend in an automated fashion, is an entirely separate puzzle piece.

In this hands-on blog post, you will learn how to deploy a Python API to an app service using GitHub Actions CICD. In theory, this tutorial will work with any type of web API since it's not building any code, but instead, simply pulling the code from GitHub.

Microsoft is moving in the direction of implementing new features in GitHub Actions CICD instead of Azure DevOps/Azure Pipelines. With that being said, it's ideal to stay ahead of the curve and keep up with the direction that Microsoft is heading in to not only keep up with the latest DevOps tooling, but to ensure you know how to use GitHub Actions CICD when the time comes for an organization to switch over.


To follow along in this blog post, you will need the following:

  • An understanding of what Continuous Integration and Continuous Delivery (CICD) is used for.
  • An Azure account. If you don't have one, you can sign up for a 30-day free trial here.
  • Azure Command-Line-Interface (AZ CLI) installed and logged in to which you can find here.
  • A GitHub account. If you don't have one, you can sign up for free here.
  • The code for the blog post is under my GitHub, which you can find here. The hands-on section of this blog post assumes you have the PyWeb library either cloned or forked.
Although the PyWeb Flask API is certainly not a hard requirement, that is the code that will be used throughout this blog post. I can't guarantee other Python APIs will work fine, but theoretically there shouldn't be any difference from a deployment perspective.

Understanding GitHub Actions CICD

Before jumping into the hands-on demo, what is GitHub Actions CICD?

GitHub Actions CICD is a YAML based CICD platform that allows you to build and push code from a repository hosted on GitHub. GitHub Actions CICD is the newest CICD platform in the community. After Microsoft acquired GitHub in late 2018, GitHub Actions CICD began development.

You may be wondering But what about Azure DevOps Pipelines? and I think that's what a lot of people are wondering. The great thing is that YAML pipelines in Azure DevOps Pipelines are the same in GitHub Actions CICD, so you don't have to worry about learning a new syntax. The biggest difference between the two is that GitHub Actions CICD doesn't have a UI-based deployment method.  

New CICD pipelines in GitHub Actions CICD are called workflows, as you can see in the below screenshot. Workflows are where the YAML pipeline code is stored.

Now that you know about GitHub Actions CICD, let's dive into creating a new workflow and get our hands dirty with some hands-on lab goodness!

To learn more about GitHub Actions CICD, check out the official GitHub pages here.

Creating a New Workflow

Creating a new workflow on GitHub Actions CICD means you are doing two things:

  • The YAML pipeline to be created and run
  • A place for the pipeline to run

A workflow is you telling GitHub Actions CICD how to run the code. Does it need specific libraries? Credentials? Variables? Runtime parameters? In the workflow's YAML code is where you define the needed metadata to run the application properly.

Open up a web browser and log into GitHub.

Once you are in GitHub, go to the PyWeb repository as shown in the screenshot below.

Actions is where GitHub Actions workflows live. Click on Actions to access the workflows.

You will see a screenshot similar to the one below. There are a few suggestions based on the code in the repository for what workflow to use. Creating a workflow from scratch will allow you to add in any details you'd like from a deployment perspective. To do this, click on the blue Set up a workflow yourself button.

You will be presented with a YAML file similar to the one below. Delete everything after like 23 as it's just pseudo code. The YAML code that you write will go after line 23.

Before you start writing code, let's take a look at what each switch means.

  • name - Name is a label of the workflow. For example, you can name it PyWeb as that's the application that is being deployed.
  • on - On is when the workflow initiate to push out the code. For example, let's say you are using the exact steps as shown in the screenshot below. That means every time you push to the master branch and/or do a pull request from the master branch, the workflow will initialize and the YAML code will be run to deploy the Python application.
  • jobs - Under jobs you will see build and runs-on, which is what environment you are running the code from. If you are using Microsoft-hosted GitHub runner, you will be using a virtual environment that is maintained by Microsoft for you to use.
  • steps - Steps is what the YAML code is actually doing, for example, in the case of this blog post, the YAML code is deploying a Python web app to Azure App Services. Each step underneath steps is what helps automate the process of pushing the code out to Azure to run in app services.

Don't close out of the workflow file as you will be going back to it in the upcoming section Writing the YAML Code.

Setting up the Authentication

In the previous section you learned about the workflow, created a workflow, and what each switch in the YAML pipeline is used for.

For GitHub to connect to, or communicate with Azure, it needs credentials. The credentials can be built using AZ CLI.

Open up a terminal and run the following command to generate an app registration/service principal credential from Azure. The command below is generate a JSON output with secrets that GitHub needs for authentication to Azure.

az ad sp create-for-rbac --name "name_of_app" --role contributor --scopes /subscriptions/subscription_id --sdk-auth

After running the command, you should see a screenshot similar to the one below.

Ensure to copy the JSON output so it can be used to create the new GitHub secret.

Open up a web browser and go to the secrets pane in GitHub by going to the Python web API GitHub repository --> Settings --> Secrets.

Click the blue Add a new secret button as shown in the screenshot below.

Name the secret AZURE_CREDENTIALS (not mandatory, that name is just what the blog is following and is in the YAML code) and paste in the JSON output from the terminal in the value section. Once the JSON output is pasted, click the green Add secret button to create the new secret.

Writing the YAML Code

In the previous section you learned about how to create authentication with the AZ CLI and create a new section in GitHub. In this section you will start to write the YAML code that is needed to deploy the Python web application.

Go back to the workflow where the YAML file is.

Now that the GitHub secret has been created, you are ready to start putting in steps. Before adding in the steps, let's take a look at what each step means.

  • python-lint - The Python-lint step uses PEP8 standards to ensure the Python code that is being run is following best practices to the Python standards. This includes syntax, spacing, and tabs.
  • azure/login@v1 - The login switch is for authenticating to Azure. In the previous section Setting up Authentication, you were generating the authentication for this step. Notice in the creds: you are using the AZURE_CREDENTIALS secret that you created?
  • run: | - The run switch is used to run any commands that are needed. As you are deploying Python code to a web app, the web app and app service plan will need to exist so the code has somewhere to deploy to. The az appservice plan create and az webapp create AZ CLI commands will create what is needed.
  • Azure WebApp - The Azure WebApp step using the Azure/webapps-deploy@v2 API to deploy the Python code from GitHub to the web app.
If you look at each step in the uses portion of the YAML code, those are all API's that are being utilized from the workflow.

Below is the code that needs to be copy and pasted into the YAML workflow.

    - name: python-lint
      uses: CyberZHG/github-action-python-lint@0.0.2
    - uses: azure/login@v1
        creds: ${{ secrets.AZURE_CREDENTIALS }}
    - run: |
        az appservice plan create -g your_resource_group -n pywebplan
        az webapp create -g your_resource_group -p pywebplan -n pyweb
    - name: Azure WebApp
      uses: Azure/webapps-deploy@v2
        app-name: pyweb

You should end up with something similar to the screenshot below. Ensure that you edit the your_resource_group portion with a resource group that is available in the Azure subscription you are using.

Deploying the YAML Code

In the previous section you wrote the YAML code needed in the workflow to deploy a Python web API to Azure app services. Now it's time to deploy the workflow.

Click the green Start commit button as shown in the screenshot below.

What you will see, as shown in the screenshot below, is the YAML code being committed to the GitHub repo where the Python web API is. This is needed so the workflow knows where to find the Python code. You can keep everything default and click the green Commit new file button.

You will then be automatically brought back to the Python repository. Click on the Actions button.

You will now see a new deployment happening under Workflows. Click on the deployment where it says Create main.yml as shown in the screenshot below.

You will now see that the deployment was successful as shown in the screenshot below. Click on the blue build button to show the deployment steps.

The deployment steps are shown like in the screenshot below.

Congratulations! You have successfully deployed a Python web API to Azure using GitHub Actions CICD!


In this blog post you learned all about utilizing one of the newest CICD platforms, GitHub Actions CICD. You went over what GitHub Actions CICD is and why it's useful in today's world. After that you dove right in and got hands-on experience create a new workflow, designing a YAML file, and deploying that YAML file. After the workflow was deployed, you were able to see that the web app was successfully created and the Python code was deployed.

For your next challenge, try doing the same type of YAML file, but instead, maybe with a different programming language. Perhaps create a web API using C# and deploy that?