In this post, we are going to publish our WebGL game by uploading it to Azure cloud. In the previous part, we created a web game in Unity and built it with the help of GitHub Actions. Here, we’ll go on to upload the completed game to the cloud.
Building Your Cloud Infrastructure
Our main aim is to create an AppService in the Microsoft Azure cloud so as to be able to host our WebGL game and we will be making use of Terraform to build the resources.
If you haven’t carried out the steps so far, create an Azure account, and download Terraform. You will also need the Azure CLI, to manage Azure from the command line.
Let’s start by creating a sub-folder “infra” into your Unity’s game folder. We will store the infrastructure code here. Then, log in to our Azure account:
az login
We have to create a storage account for Terraform in Azure. Terraform stores the state of the infrastructure in a file. This could also be local on your machine, but we want to execute Terraform from GitHub Actions.
az group create --location westeurope --resource-group mygamesa-rg
az storage account create --name mygamestorageacc --resource-group mygamesa-rg
az storage container create --name mygamestoragecontainer --account-name mygamestorageacc
Create a main.tf file and add the following code to it:
terraform {
required_providers {
azurerm = {
source = "hashicorp/azurerm"
version = "=2.98.0"
}
}
backend "azurerm" {
resource_group_name = "mygamesa-rg"
storage_account_name = "mygamestorageacc"
container_name = "mygamestoragecontainer"
key = "mygame.terraform.tfstate"
}
}
provider "azurerm" {
features {}
}
resource "azurerm_resource_group" "this" {
name = "mygame-resources"
location = "West Europe"
}
resource "azurerm_app_service_plan" "this" {
name = "mygame-appserviceplan"
location = azurerm_resource_group.this.location
resource_group_name = azurerm_resource_group.this.name
sku {
tier = "Standard"
size = "F1"
}
}
resource "azurerm_app_service" "this" {
name = "mygame-app-service"
location = azurerm_resource_group.this.location
resource_group_name = azurerm_resource_group.this.name
app_service_plan_id = azurerm_app_service_plan.this.id
}
Code language: JavaScript (javascript)
Terraform can be used to create infrastructure for a variety of cloud providers. As we build it now for Azure, you have to configure the Azure (azurerm) provider. You inform Terraform in the backend block to put the state file in the storage we established earlier.
You have to declare the attributes of the Azure services you intend to build in each resource block. We create a resource group which is a logical grouping of all related resources. We also create a free (F1) app service plan and and AppService named mygame-app-service. We will upload our WebGL application to here.
The Terraform will make sure that the resources you have in Azure are the same as what you see in your state file. Let’s execute the following commands to deploy the resources:
terraform init
terraform apply
Check the Azure portal, if Terraform successfully deployed the AppService.
Deploy the Infrastructure with GitHub
We want to execute our Terraform script from GitHub. At first, extend our .gitignore file, so that Git uploads only the script files:
*.lock.hcl
*.tfstate
*.tfstate.backup
**/.terraform/*
Code language: JavaScript (javascript)
Create a new workflow, which will execute Terraform on our script. Earlier we did that locally, now it should work in GitHub. Create a new file .github/workflows/Terraform.yml:
name: Terraform
on: [workflow_dispatch]
env:
ARM_CLIENT_ID: ${{secrets.AZURE_CLIENT_ID}}
ARM_CLIENT_SECRET: ${{secrets.AZURE_CLIENT_SECRET}}
ARM_SUBSCRIPTION_ID: ${{secrets.AZURE_SUBSCRIPTION_ID}}
ARM_TENANT_ID: ${{secrets.AZURE_TENANT_ID}}
jobs:
buildInfrastructureWithTerraform:
name: Build Infrastructure with Terraform
defaults:
run:
working-directory: ./infra
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v2
- name: Terraform Setup
uses: hashicorp/setup-terraform@v1
with:
terraform_version: 1.1.7
- name: Terraform Format
run: terraform fmt -check
- name: Terraform Init
run: terraform init
- name: Terraform Validate
run: terraform validate -no-color
- name: Terraform Apply
run: terraform apply -auto-approve
Code language: HTTP (http)
By default, Terraform has no access to Azure. We need to create a service principle in Azure and grant at least a contributor role to it on our subscription:
az account show --query=id
az ad sp create-for-rbac --name "github-action" --role contributor --scopes /subscriptions/<subscription_id> --sdk-auth
{
"clientId": "<clientId>",
"clientSecret": "<clientSecret>",
"subscriptionId": "<subscriptionId>",
"tenantId": "<tenantId>",
"activeDirectoryEndpointUrl": "https://login.microsoftonline.com",
"resourceManagerEndpointUrl": "https://management.azure.com/",
"activeDirectoryGraphResourceId": "https://graph.windows.net/",
"sqlManagementEndpointUrl": "https://management.core.windows.net:8443/",
"galleryEndpointUrl": "https://gallery.azure.com/",
"managementEndpointUrl": "https://management.core.windows.net/"
}
Code language: PHP (php)
Terraform requires four environment variables set for it to be able to access Azure. Copy these values from the output of the above command into the related secrets in GitHub (Settings > Secrets > Actions):
ARM_CLIENT_ID: ${{secrets.AZURE_CLIENT_ID}}
ARM_CLIENT_SECRET: ${{secrets.AZURE_CLIENT_SECRET}}
ARM_SUBSCRIPTION_ID: ${{secrets.AZURE_SUBSCRIPTION_ID}}
ARM_TENANT_ID: ${{secrets.AZURE_TENANT_ID}}
Then commit and push your code to the GitHub repository. This also will now contain the Terraform infrastructure code and the new workflow.
Start the Terraform workflow manually from GitHub (Actions > Terraform > Run workflow) and check if it runs with no issue.
Deploy The Client with GitHub
In this step, we will implement the deployment workflow of our game in GitHub Actions. You can add this step right after you build the workflow, too. In this example, we will separate them, and configure manual start for the workflows.
Create in your project folder a file such as .github/workflows/DeployClient.yml. Copy this into it:
name: Deploy WebGL Client
on:
workflow_dispatch: {}
jobs:
deployClientToAppService:
name: Deploy Client to App Service
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Download artifact
uses: dawidd6/action-download-artifact@v2
with:
workflow: BuildClient.yml
workflow_conclusion: success
name: mygame
path: build/
- name: copy file
uses: canastro/copy-file-action@master
with:
source: "WebConfig/web.config"
target: "build/WebGL/web.config"
- name: Deploy Client to App Service
uses: azure/webapps-deploy@v2
with:
app-name: 'mygame-app-service'
slot-name: 'production'
publish-profile: ${{ secrets.AZURE_PUBLISH_PROFILE }}
package: build/WebGL/
Code language: JavaScript (javascript)
By using the workflow_dispatch, we’ll only be able to start the workflow manually from GitHub. By default, GitHub supports passing files between jobs, but not between workflows. As the result of our build was uploaded in another workflow, we have to use a special action from GitHub Marketplace (dawidd6/action-download-artifact@v2), so that we will be able to download the built artifact from the BuildClient.yml workflow.
To avoid a WebGL-specific issue, you need to carry out some extra steps. Create a WebConfig folder in your project folder, and create a web.config file:
<configuration>
<system.webServer>
<staticContent>
<mimeMap fileExtension=".unityweb" mimeType ="TYPE/SUBTYPE" />
</staticContent>
</system.webServer>
</configuration>
Code language: HTML, XML (xml)
We will commit and push this file to GitHub, and the workflow will copy it (by using canastro/copy-file-action@master) next to our web game build. Also, set the Decompression Fallback checkbox in Unity Editor > File > Build Settings… > Player Settings… > Player > Publishing Settings.
Finally, we deploy the build folder to Azure. By default, GitHub has no access to Azure AppService. We can simply download the publish profile in Azure Portal > App Services > mygame-app-service > Get publish profile. Copy the content of this file into the AZURE_PUBLISH_PROFILE secret, in GitHub > Actions > Settings > Secrets > Actions.
Now push your code with Git to your GitHub repository. Under the Actions, find your new workflow, and click on Run workflow.
If the workflow run with no error, you can test if you can reach the game by typing the hostname in your browser:
az webapp config hostname list --webapp-name mygame-app-service -g mygame-resources --query=[0].name
"mygame-app-service.azurewebsites.net"
Code language: PHP (php)
Conclusion
We used GitHub Actions and Terraform to upload our WebGL game to Azure in this second part of the series, completing the CD (Continuous Deployment) section of our CI/CD pipeline. In the next article, we’ll create and upload a server in Azure. Players will be able to play the game in multiplayer mode as a result of this. Keep an eye out for updates.