We now have a finished product and we are ready to share it with the world!
The first step of showing off our new game is to package it up into a form that is compatible with a web server. This is fairly easily done using dotnet’s publish
command.
dotnet publish Website/Website.fsproj -o ./dist -c Release --nologo
This creates a working website in the “./dist” folder with all the extra debug stuff stripped out for release.
If you look at what is produced, you get a web config file, the program, and all the framework libraries to make F# work.
Technically, this is all you need - you could upload this to a webserver using plain old FTP and point to the index.html file and it would just work. But this is and F# and dotnet series, so let’s see what it takes to get things running on Azure.
Farmer is a community build project for generating the definition file (called a ARM template) that is used to manage Azure resources. A resource might be a storage account, or a website, or maybe even a database, that is hosted in Azure.
To use Farmer, we describe the Azure resources and how they link together using an F# script file, just like the first versions of our game. The Farmer library is referenced at the top of the script directly from NuGet.org and used to create a description of the resources we desire and then save that as a ARM template file. We can even execute the creation of the resources in Azure directly from within the script!
Note that this is just a normal F# script, and so can be as simple or complex as we want.
#r "nuget: Farmer" // Get the Farmer libraries directly from NuGet
open System
open Farmer
open Farmer.Builders
// We'll pass the path to our published game in as an argument
let pathToGame = Environment.GetCommandLineArgs() |> Array.last
printfn "THE PATH TO THE GAME IS: %s" pathToGame
let storage = storageAccount {
name "solitairestorage"
sku Storage.Sku.Standard_LRS
use_static_website pathToGame "index.html"
static_website_error_page "error.html"
}
let deployment = arm {
location Location.AustraliaSoutheast
add_resource storage
}
// Save as a ARM template file, just to check we got it right (optional)
deployment
|> Writer.quickWrite "output"
// Deploy into resource group directly to Azure
deployment
|> Deploy.execute "solitaire-rg" Deploy.NoParameters
|> printfn "%A" // (print out any results - not expecting any)
dotnet publish Website/Website.fsproj -o ./dist -c Release --nologo
dotnet fsi ./deploy.fsx ./dist/wwwroot
To run this, you will need to have signed up for an Azure account, and will need to install the Azure CLI to login from the terminal. You may need to execute az login
first.
Once this has run, you can the url of the new website by:
solitaire-rg
solitairestorage
Data management > Static website
https://solitairestorage.1234.web.core.windows.net/
Open the URL in a browser and there you go - your own game on the internet for anyone to enjoy!
This is an alternative to hosting the game on Azure. As this game is after all a static website, with no backend program, we COULD host it anywhere. So let’s try getting GitHub Pages to build and host our game without have a separate host at all!
Github Pages can use a build action to compile the F# code and then use the index.html
file as the “Page”.
To make this work we need a couple of things:
gh-pages
branch as the place to store our pages. If you haven’t done this before read thisTo do this we need to give it a “workflow” yaml file and store it in the special location .github/workflows/main.yml
.
If all goes well, you should see something going on in the “Workflows” tab on the github portal every time you push a change to the repo, and be able to see the game at
https://<your organisation/account name>.github.io/<your repo name>
There is an example of this (using a custom domain 😊) at https://pete-the-programmer.com/Solitaire-Demo/
name: Deploy to GitHub Pages
# Run workflow on every push to the main branch
on:
push:
branches: [ main ]
jobs:
deploy-to-github-pages:
# use ubuntu-latest image to run steps on
runs-on: ubuntu-latest
steps:
# uses GitHub's checkout action to checkout code form the main branch
- uses: actions/checkout@v2
# sets up .NET 6.0
- name: Setup .NET
uses: actions/[email protected]
with:
dotnet-version: '6.0.x'
# publishes Blazor project to the release-folder
- name: Publish .NET Project
run: dotnet publish Website/Website.fsproj -c Release -o release --nologo
# copy index.html to 404.html to serve the same file when a file is not found
- name: copy index.html to 404.html
run: cp release/wwwroot/index.html release/wwwroot/404.html
# add .nojekyll file to tell GitHub pages to not treat this as a Jekyll project. (Allow files and folders starting with an underscore)
- name: Add .nojekyll file
run: touch release/wwwroot/.nojekyll
- name: Commit wwwroot to GitHub Pages
uses: JamesIves/[email protected]
with:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
BRANCH: gh-pages
FOLDER: release/wwwroot
Note: If you’re using GitLab, or Bitbucket, or something similar, then these hosts will usually be able to do something like this as well