6 min read

Publishing Static Website to Azure Blob Storage via GitHub Actions

Justin Yoo

GitHub announced that GitHub Actions has been generally available in November. Since that, there have already been a huge number of Actions on the marketplace. As the usage of Actions is pretty simple and straight forward, as long as you know a few key concepts, you can easily get on-board. Throughout this post, I'm going to build a simple static web app and deploy it to Azure Blob Storage, through GitHub Actions.

You can download the sample codes used in this post at this GitHub repository.

Provisioning Azure Blob Storage

First things first. Let's provision an Azure Blob Storage to host a static website. You can create the instance through Azure Portal, or Azure CLI or Azure PowerShell commands. I'm going to use Azure CLI for it. The commands below create an Azure Resource Group and an Azure Storage Account instance.

# Create a new Azure Resource Group
az group create \
-n <RESOURCE_GROUP_NAME> \
-l <LOCATION>
# Create a new Azure Storage instance
az storage account create \
-g <RESOURCE_GROUP_NAME> \
-n <STORAGE_ACCOUNT_NAME> \
-l <LOCATION> \
--sku Standard_LRS \
--kind StorageV2
view raw az-storage-create.sh hosted with ❤ by GitHub

Then, inside the storage account, we need to create a special container for static website hosting. The special container is called $web, which is the only container of each Azure Blob Storage. In other words, one Azure Blob Storage can only host one static website. The command below creates the $web container automatically by enabling the static website option.

# Activate static website hosting feature
az storage blob service-properties update \
--account-name <STORAGE_ACCOUNT_NAME> \
--static-website true \
--index-document index.html \
--404-document 404/index.html

Now, we need to know the website URL. Let's run the command below:

# Get the endpoint URL
az storage account show \
-g <RESOURCE_GROUP_NAME> \
-n <STORAGE_ACCOUNT_NAME>
view raw az-storage-show.sh hosted with ❤ by GitHub

After running the command, it returns a massive JSON object that includes:

{
...
"primaryEndpoints": {
"blob": "https://<STORAGE_ACCOUNT_NAME>.blob.core.windows.net/",
"dfs": "https://<STORAGE_ACCOUNT_NAME>.dfs.core.windows.net/",
"file": "https://<STORAGE_ACCOUNT_NAME>.file.core.windows.net/",
"queue": "https://<STORAGE_ACCOUNT_NAME>.queue.core.windows.net/",
"table": "https://<STORAGE_ACCOUNT_NAME>.table.core.windows.net/",
"web": "https://<STORAGE_ACCOUNT_NAME>.<ARBITRARY_VALUE>.web.core.windows.net/"
},
...
}

As you can see, the web attribute has the URL of https://<STORAGE_ACCOUNT_NAME>.<ARBITRARY_VALUE>.web.core.windows.net/. This is the website URL that we're going to access.

Generating Static Website

There are many awesome tools for static website generation. It's totally up to your choice, but I'm going to use gridsome, based on Vue.js. First of all, install the gridsome CLI and create a sample project with the following commands.

# Install gridsome
npm install -g @gridsome/cli
# Create a website
gridsome create WebApp
view raw gridsome-create.sh hosted with ❤ by GitHub

Now we have a very simple web app displaying Hello World. I'm not going to dive too deep, as static website generation is not the main topic here. If you want to know more about gridsome follow the official website. In order to check the website on my local, run the following command:

cd WebApp
# Run the web app locally
gridsome develop
view raw gridsome-run.sh hosted with ❤ by GitHub

If you're happy with the result, let's deploy it to Azure Blob Storage. Artifacts are located in the /dist directory.

# Build the web app
gridsome build
view raw gridsome-build.sh hosted with ❤ by GitHub

Please note that both develop and build command can be run through the npm run command. This is particularly important to know because we're going to use both commands later in this post, through GitHub Actions.

# Run the web app locally
npm run develop
# Build the web app
npm run build
view raw gridsome-npm.sh hosted with ❤ by GitHub

Manual Publishing Static Website

Both web app and Azure Blob Storage are ready. Let's publish the app manually from the local first. We can use Azure CLI to publish the website with this following command:

az storage blob upload-batch \
-s dist \
-d \$web \
--account-name <STORAGE_ACCOUNT_NAME>

If you haven't logged into Azure yet, through Azure CLI, additional parameters like --account-key, --connection-string or sas-token should be provided.

Automated Publishing Static Website through GitHub Actions

There are core concepts on GitHub Actions. As a first timer, not all of them need to know, but these four concepts are the most fundamental ones – Workflow, Event, Runner and Action.

  • Workflow: The automated process definition to build, test and deploy codes. It contains Event, Runner and Action.
  • Event: It's an event to trigger Workflow. For example, events can be code push, pull request, and so on.
  • Runner: It's an operating system to run Workflow. GitHub offers pre-configured runners. You can also build a self-hosted runner and use it.
  • Action: Workflow orchestrates many actions inside. Through these actions, the workflow builds, tests and deploy codes, as well as many other tasks under many different scenarios.

The basic structure of Workflow looks like:

name: <WORKFLOW_NAME>
on: <EVENT>
jobs:
<JOB_NAME>:
runs-on: <RUNNER>
steps:
- name: <ACTION_NAME>
uses: <ACTION>
  • WORKFLOW_NAME: Name of the workflow. It shows on the GitHub Actions tab. One repository can have multiple workflows.
  • EVENT: Event to trigger the workflow. For example, the event can be push, pull_request, schedule, and so on.
  • RUNNER: Operating system to run the workflow. GitHub provided runners are Windows, Linux (Ubuntu) and Mac OS. You can also use your own self-hosted runner.
  • ACTION_NAME: Name of each action. Usually, it's a short description of the action. eg) Login to Azure, Build App
  • ACTION: Action reference.

Now, based on this understanding, let's build the workflow. We used four actions once or multiple times in this workflow.

  • checkout: Download repository into the workflow.
  • run: This is a built-in shell action that does npm package restore, build and test.
  • azure login: Login to Azure.
  • azure cli: Publish the website to Azure Blob Storage through this action.

With a combination of those actions above, here's the sample workflow:

name: Publish Static Web App to Azure Blob Storage
on: push
jobs:
build_and_publish:
runs-on: ubuntu-latest
steps:
- name: Checkout the repo
uses: actions/checkout@v1
- name: Login to Azure
uses: Azure/login@v1
with:
creds: ${{ secrets.AZURE_CREDENTIALS }}
- name: Install npm packages
shell: bash
run: |
cd $GITHUB_WORKSPACE/src/WebApp
npm install
- name: Build app
shell: bash
run: |
cd $GITHUB_WORKSPACE/src/WebApp
npm run build
- name: Test app
shell: bash
run: |
cd $GITHUB_WORKSPACE/src/WebApp
npm run test:unit
- name: Publish app
uses: Azure/cli@v1.0.0
with:
azcliversion: latest
inlineScript: |
az storage blob upload-batch -s $GITHUB_WORKSPACE/src/WebApp/dist -d \$web --account-name ${{ secrets.STORAGE_ACCOUNT_NAME }}
  • on: push: Only the push event triggers this workflow.
  • runs-on: Linux (Ubuntu) runner is assigned. ubuntu-latest means Ubuntu 18.04 LTS at the time of this writing.
  • name: Checkout the repo: This action downloads the repo into the workflow. This action MUST come the very first.
  • name: Login to Azure: This action logs into Azure. Security credentials are encrypted and stored at the repository settings with the name of AZURE_CREDENTIALS, and it's referred to ${{ secrets.AZURE_CREDENTIALS }}.
  • name: Install npm packages: This action restores the npm packages. Make sure that the directory traversing MUST be considered to find the packages.json file; otherwise, it will throw an unexpected consequence.
  • name: Build app: This action builds the website. Again, make sure the directory traversing first to run the npm run build command.
  • name: Test app: This action tests the web app. Don't forget the directory traversing to run the command, npm run test:unit.
  • name: Publish app: This action publishes the application to Azure Blob Storage. The storage account name is passed from the repository settings and referenced to ${{ secrets.STORAGE_ACCOUNT_NAME }}.

Save this workflow to the main.yml file and locate it into the .github/workflows directory. GitHub Actions look for the workflow files under the .github/workflows directory. Let's push your code to GitHub, and you'll find the successful result!

Open the Azure Blob Storage URL, and you'll see the static website just published!


So far, we've used GitHub Actions to publish static website to Azure Blob Storage. Let's discuss GitHub Actions further down on the following posts.