AZ-400: Designing and Implementing Microsoft DevOps Solutions
Design and Implement Pipelines
Deployment Automation with GitHub Actions
In this article, we explore how to automate deployments using GitHub Actions. We'll deploy a Node.js application to Azure—a scenario that represents real-world CI/CD implementations and is also relevant to the AZ-400: Designing and Implementing Microsoft DevOps Solutions exam. Our sample application is the KodeKloud copy shop running on your screen. With stakeholder approval, the website is ready to be deployed to Azure.
We'll cover the complete process—from setting up a GitHub Actions workflow to deploying your application on Azure.
Setting Up the Workflow
GitHub Actions uses workflows defined in YAML files stored in the repository’s .github/workflows
directory. You can create a new YAML file or navigate to the Actions tab in your repository to get started.
While the Actions tab offers several pre-built workflows, we will manually build one to gain a better understanding of each step.
Workflow Structure Overview
Below is a basic GitHub Actions workflow configuration for our Node.js application. This workflow is triggered on pushes to the main
branch and runs on the latest Ubuntu runner:
name: Deploy to Azure
on:
push:
branches: [ main ]
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
Understanding GitHub Actions Events
The on
section in the YAML config specifies the events that trigger the workflow. In our example, a push to the main
branch starts the workflow. GitHub Actions supports a variety of events, such as pull requests and scheduled events using cron syntax:
name: Deploy to Azure
on:
schedule:
- cron: '*/15 * * * *'
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
For this demo, we rely on the push event.
Jobs and Steps
Workflows consist of jobs, each running in a fresh virtual environment. Every job comprises several steps, which can execute commands or run pre-built actions. In the following snippet, the steps include checking out the repository, setting up Node.js, installing dependencies, building the project, and running tests:
name: Deploy to Azure
on:
push:
branches: [ main ]
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Use Node.js
uses: actions/setup-node@v2
with:
node-version: '14.x'
- run: npm install
- run: npm run build --if-present
- run: npm test
These modular actions, available from both GitHub and the community, help streamline common tasks in your deployment pipeline.
Enhancing the Workflow with Environment Variables and Upgraded Actions
To better support custom deployments, we update the workflow with environment variables and manual triggers using workflow_dispatch
. Additionally, these variables allow you to parameterize your build and deployment configuration.
name: Deploy to Azure
on:
push:
branches: [ main ]
workflow_dispatch:
env:
AZURE_WEBAPP_NAME: kodekloudcoffee
AZURE_WEBAPP_PACKAGE_PATH: '.'
NODE_VERSION: '20.x'
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Use Node.js
uses: actions/setup-node@v2
with:
node-version: '14.x'
- run: npm install
- run: npm ci
- run: npm run build --if-present
- run: npm test
Manual Trigger
The workflow_dispatch
event enables manual execution of the workflow directly from the GitHub Actions interface.
Next, we refine our workflow by separating the build and deploy jobs. This separation ensures that deployment only occurs after a successful build.
name: Deploy to Azure
on:
push:
branches: [ main ]
workflow_dispatch:
env:
AZURE_WEBAPP_NAME: kodekloudcoffee
AZURE_WEBAPP_PACKAGE_PATH: '.'
NODE_VERSION: '20.x'
permissions:
contents: read
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: 'npm'
- name: npm install, build, and test
run: |
npm install
npm run build --if-present
npm test
- name: Upload artifacts
uses: actions/upload-artifact@v3
with:
name: node-app
path: .
deploy:
permissions:
contents: none
runs-on: ubuntu-latest
needs: build
environment:
name: 'Development'
url: ${{ steps.deploy-to-webapp.outputs.webapp-url }}
steps:
- name: Download artifacts from build
uses: actions/download-artifact@v3
- name: Deploy to Azure WebApp
id: deploy-to-webapp
uses: azure/webapps-deploy@v2
with:
app-name: ${{ env.AZURE_WEBAPP_NAME }}
publish-profile: ${{ secrets.AZURE_WEBAPP_PUBLISH_PROFILE }}
package: ${{ env.AZURE_WEBAPP_PACKAGE_PATH }}
In this configuration:
- The build job checks out the code, prepares the Node.js environment (with caching), installs dependencies, builds the project, runs tests, and uploads the build artifacts.
- The deploy job downloads the artifacts and uses a pre-built GitHub Action to deploy your application to Azure. The
needs: build
keyword ensures that the deploy job only runs after a successful build.
Setting Up Your Azure Web App
Before deploying your application, create a web app in the Azure portal:
- Log in to the Azure portal and navigate to App Services.
- Create a new Web App:
- Select your subscription and resource group.
- Name the web app (e.g., "KodeKloudCoffee").
- Choose “Publish: Code” and select the Node.js runtime.
- Set the region (e.g., Central US) and select Linux as the operating system.
- Choose a free plan if applicable.
- Configure the deployment settings. Note that GitHub Actions auto-configuration for Windows deployments is not supported with manual workflows.
- Enable basic authentication if required.
- Complete the review and creation process.
After setting up the web app, navigate to its resource page and download the Publish Profile. Store this file securely; you'll use it later by adding it as a repository secret.
Security Notice
Never commit your Publish Profile directly to your repository. Always store sensitive credentials as encrypted GitHub Secrets.
If desired, the Azure portal offers GitHub integration settings (currently optimized for Windows deployments), but for this demo, we continue with our custom workflow.
Double-check that basic authentication is enabled along with the correct networking and monitoring configurations.
Once your Azure web app is configured, commit your changes to the main
branch to trigger the GitHub Actions workflow.
Configuring GitHub Secrets and Final Deployment
Before the workflow can deploy your application to Azure, add the Publish Profile as a repository secret:
- Go to your repository’s Settings → Secrets and variables → Actions.
- Create a new repository secret named "AZURE_WEBAPP_PUBLISH_PROFILE" and paste the content of your downloaded Publish Profile.
Once the secret is added and changes have been pushed, the workflow will run automatically. In the GitHub Actions interface, you should see two jobs: the build job and the deploy job. The deploy job will only initiate once the build job finishes without errors.
After deployment, review the deployment logs in the Azure portal to ensure your website is running correctly.
Conclusion
In this article, we set up a streamlined CI/CD pipeline using GitHub Actions to deploy a Node.js application to an Azure App Service. Here's a quick recap of what we covered:
- We configured a workflow triggered by pushes to the
main
branch and allowed for manual triggering viaworkflow_dispatch
. - The build job checked out the repository, set up Node.js, installed dependencies, built the project, ran tests, and uploaded artifacts.
- The deploy job downloaded these artifacts and deployed them to Azure, ensuring a structured flow by using the
needs
keyword. - GitHub Secrets were used to securely store the Azure Publish Profile.
- Key GitHub Actions concepts such as jobs, steps, environment variables, and dependency management were demonstrated.
GitHub Actions simplifies many aspects of your development workflow, providing a robust platform for automating deployments. Familiarity with these configurations is also beneficial for those preparing for the AZ-400: Designing and Implementing Microsoft DevOps Solutions exam.
Happy deploying!
Watch Video
Watch video content