Git Hub Actions Deployment to Azure Static Website
I invite you to read my solution to the A Cloud Guru Azure Resume Challenge . I embarked on this latest challenge in in order to learn and practice Azure and also, to add to my Cloud Architect Portfolio.
Azure Resume Challenge
This is the diagram A Cloud Guru included to visualize the challenge:
and here is the solution that I implemented in response to this challenge:
Goal
The objective of this project was to create a static web site in Azure Blob storage with the following features:
- HTTPS
- Content Delivery Network (CDN)
- Azure Function integrated with Cosmos DB to count website loads
- Git Hub Actions to automate the deployment of website code (html, javascript, css, images, etc)
The objective was achieved by designing and building a solution using Blob Storage, CDN, Custom Domain, Function, Cosmos DB services from Azure and Git Hub Actions.
Outcome
In completing this project I was able to gain real-world skills in Git Hub Actions, Blob Storage Static Website, Cosmos DB and Functions.
Main Steps
This project was completed in five steps:
Step 1. Created 8 Azure CLI commands that create the necessary Azure infrastructure
## Azure CLI Resource Group Creation
> az group create --name StaticWebsiteRG --location canadacentral
## Azure CLI Storage Account Creation
> az storage account create --name briangithubactions --resource-group StaticWebsiteRG --location canadacentral --sku Standard_LRS
## Azure CLI Blob Static Website Creation
> az storage blob service-properties update --account-name briangithubactions --static-website --404-document 404.html --index-document index.html
## Azure CLI Create a Content Delivery Network (CDN) profile
> az cdn profile create --resource-group StaticWebsiteRG --name MyCDNProfile --sku Standard_Microsoft
## Azure CLI Create a Content Delivery Network (CDN) endpoint
> az cdn endpoint create --resource-group StaticWebsiteRG --name brian-gaber --profile-name MyCDNProfile --origin briangithubactions.z9.web.core.windows.net --origin-host-header briangithubactions.z9.web.core.windows.net
## Azure CLI Create URL Redirect rule to redirect any HTTP requests to HTTPS
> az cdn endpoint rule add --resource-group StaticWebsiteRG --name brian-gaber --profile-name MyCDNProfile --order 1 --rule-name "redirect" --match-variable RequestScheme --operator Equal --match-values HTTP --action-name "UrlRedirect" --redirect-protocol Https --redirect-type Moved
### Before you can use a custom domain with an Azure CDN endpoint, you must first create a canonical name (CNAME) record with Azure DNS or your DNS provider to point to your CDN endpoint.
### https://docs.microsoft.com/en-us/azure/cdn/cdn-map-content-to-custom-domain
## Azure CLI Create a custom domain for your endpoint
> az cdn custom-domain create --resource-group StaticWebsiteRG --endpoint-name brian-gaber --profile-name MyCDNProfile --name MyCustomDomain --hostname briangaber.esnap.ca
## Azure CLI Enable https
az cdn custom-domain enable-https --resource-group StaticWebsiteRG --endpoint-name brian-gaber --profile-name MyCDNProfile --name MyCustomDomain
Step 2. Created a Git Hub Actions main.yml to deploy the website code upon a push of the code to my Git Hub repository.
name: Blob storage website CI
on:
push:
branches: [ main ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: azure/login@v1
with:
creds: ${{ secrets.AZURE_CREDENTIALS }}
- name: Upload to blob storage
uses: azure/CLI@v1
with:
azcliversion: 2.23.0
inlineScript: |
az storage blob upload-batch --account-name briangithubactions -d '$web' -s . --pattern *.html
az storage blob upload-batch --account-name briangithubactions -d '$web' -s . --pattern *.css
az storage blob upload-batch --account-name briangithubactions -d '$web' -s . --pattern *.js
az storage blob upload-batch --account-name briangithubactions -d '$web' -s . --pattern *.png
az storage blob upload-batch --account-name briangithubactions -d '$web' -s . --pattern *.jpg
az storage blob upload-batch --account-name briangithubactions -d '$web' -s . --pattern *.gif
az storage blob upload-batch --account-name briangithubactions -d '$web' -s . --pattern *.xml
az storage blob upload-batch --account-name briangithubactions -d '$web' -s . --pattern *.thmx
az storage blob upload-batch --account-name briangithubactions -d '$web' -s . --pattern *.eot
az storage blob upload-batch --account-name briangithubactions -d '$web' -s . --pattern *.svg
az storage blob upload-batch --account-name briangithubactions -d '$web' -s . --pattern *.ttf
az storage blob upload-batch --account-name briangithubactions -d '$web' -s . --pattern *.woff
az storage blob upload-batch --account-name briangithubactions -d '$web' -s . --pattern *.less
az storage blob upload-batch --account-name briangithubactions -d '$web' -s . --pattern *.scss
- name: Purge CDN endpoint
uses: azure/CLI@v1
with:
azcliversion: 2.23.0
inlineScript: |
az cdn endpoint purge --content-paths "/*" --profile-name MyCDNProfile --name "brian-gaber" --resource-group StaticWebsiteRG
# Azure logout
- name: logout
run: |
az logout
Step 3. Created a canonical name (CNAME) record with my DNS provider to point to my CDN endpoint. In my case I use AWS Route 53 as my DNS provider.
Step 4. A simple static website was created and GitHub was used for source control.
Step 5. Created one Azure Function to integrate the static website with Cosmos DB.
Solution
The final solution is composed of these Azure Services:
Azure Services Used | Purpose |
Resource Group | Container for all Azure Services |
Storage Account | BLOB Storage Static Website Container to store all website objects |
CDN | Content Deliver Network to enable worldwide low latency |
CosmosDB | NoSQL Database that contains the JSON formatted User Documents |
Function App | Functions to read and update the website load counter from Cosmos DB |
Git Hub Actions | CICD of the Static Web Site code |
New Knowledge Acquired
I took two A Cloud Guru courses (Deployment Pipelines using GitHub Actions and Serverless Computing with Azure Functions) to prepare myself to complete this project.
Solution Artifacts
The Git Hub repository for this project is found at: Azure Git Hub Actions Project
Rewards and Lessons Learned
The hardest part of this challenge was creating one function that performed both the read and update of Cosmos DB. Initially, I thought I would require two Azure Functions: one to read the counter value and a second to update the counter value. I find it elegant that, with one Function triggered by a HTTP request, I can read a value from CosmosDB, change that value in my Function and then update CosmosDB with the new value. Learning and implementing Git Hub Actions was the part of this project I enjoyed the most because, for whatever reason, I find CICD a very interesting technology. The biggest takeaways were learning Git Hub Actions and enhancing both my DevOps and Azure function skills.
Azure Function CORS - The Azure Function that integrates with CosmosDB has a different origin than the CDN endpoint and CNAME record. Therefore, a CORS permission was required for the Function.
Azure Python Functions - since my Azure Function is written in Python then it needed to be deployed using VS Code with the Azure Functions extension.
Test Drive
You can find my creation at Brian's Online Resume. Make sure to pay close attention to the "View" counter. :)
The website may not function because cloud having a pay as you go fee structure means I will incur costs if I leave the solution up indefinitely. Therefore, with the goal of cost avoidance I will have shutdown most of the cloud resources associated with this project sometime in June 2021.
Conclusions
This is the fifth A Cloud Guru challenge I have completed and I have learned extensively through completing these challenges. Without a doubt, the highlight of this challenge has been learning Git Hub Actions. It has been a very valuable experience and I encourage anyone who wants to improve their Cloud Architect skills to complete these challenges.