In this tutorial, I will walk through the process of creating a GitHub Action YAML script specifically designed for building and deploying a Blazor WebAssembly app to an existing AWS S3 bucket. Our focus will be on the YAML script itself, assuming you have prior knowledge of setting up AWS and creating a Blazor WebAssembly app. If you need assistance with those steps, I’ve included a link to a comprehensive video guide for your reference.

In addition to detailing the script, I will also detail the path I followed to generate the script and the issues I encountered.

The Full Script

For starters, here is the full script you can copy and use. We’ll follow up by going over each section in detail

Copy to Clipboard

Name

Copy to Clipboard

This is the name of the workflow and the name that will be displayed in the GitHub Actions tab on the GitHub website.

On

Copy to Clipboard

The “on” section defines the actions that automatically trigger the workflow. In my workflow I have it set to trigger on all pushes and pull_requests on the master branch.

There are several more actions and filters you can apply. Check the official documentation for more details.

Jobs

Copy to Clipboard

This section beings the meat of the script. The jobs sections contains all the jobs that will execute when the script is run. A script can have one or more jobs and all the jobs run in parallel by default. This script only contains one job.

Build and Publish

Copy to Clipboard

This is the id of my only job in this script.

Runs-On

Copy to Clipboard

This defines the type of machine the job will run on. In my case I don’t need anything fancy so I have it running on the latest ubuntu version.

There are several machine types you can choose from including Windows, macOS, and linux. You can see the full list here.

Steps

Copy to Clipboard

This section defines all the steps your job will execute. Each step begins with a “-“. Each step is made up of a set of actions that all execute as a single process.

The full list of available actions can be found here.

Checkout Code

Copy to Clipboard

This step is named “Checkout code” and executes version 2 of the public action “actions/checkout”. The action downloads the code from my repo onto the machine my job is running on so that the rest of the job can execute against it.

Setup .Net Core

Copy to Clipboard

This step is named “Setup .Net Core” and executes version 1 of the public action “actions/setup-dotnet”. The “with” section defines parameters passed into the action. This action installs the given version of .net core on the machine the job is running on.

Restore Dependencies

Copy to Clipboard

This step is named “Restore dependencies” and it executes the command “dotnet restore” on the command line of the machine the job is running on.

The command restores all the nuGet packages for the app being built.

Build Blazor WebAssembly

Copy to Clipboard

This step is named “Build Blazor WebAssembly” and it executes the command “dotnet publish -c Release – ./publish” on the command line of the machine the job is running on.

The command publishes the app using the Release build configuration and outputs it to a directory named “publish”.

Configure AWS credentials

Copy to Clipboard

This step is named “Configure ASW credentials” and it executes version 1 of the public action named “aws-actions/configure-aws-credentials”

The action sets variables with aws secrets stored in my repo that will be used in the next step.

Publish to AWS S3

Copy to Clipboard

This step is named “Publish to AWS S3” and it executes the command “aws s3 sync ./publish/wwwroot s3://${{ secrets.AWS_PRODUCTION_BUCKET_NAME }} –delete” on the command line of the machine the job is running on.

The command uploads the local directory “publish/wwwroot” to the s3 bucket named “{{ secrets.AWS_PRODUCTION_BUCKET_NAME }}” and deletes any files in the s3 bucket that do not exist in the local directory.

How I Got Here

Before I automated building and publishing the app, I started by figuring out how to do it manually. I followed this YouTube video which not only details how to build and publish the app, but it also goes in depth how to create the app and how to setup AWS so if you are starting from complete scratch I highly recommend it.

https://www.youtube.com/watch?v=8tR6W-lZVGw

To generate the script, I leveraged ChatGPT and it did create a script that was about 90% where I needed it, but I was not able to use the script as is. I’m not going to post the script it generated here because I don’t want it to show up in search results that someone may try to use, but you can see the full transcript of the chat here:

https://chat.openai.com/share/ab168a2b-c75e-4f14-ab5c-cdb1ad3fe177

The script did build my app and upload it to my s3 bucket, but the bucket was filled with a bunch of .dll files and not my html files needed to actually execute my site. After digging a bit, I found the “Build Blazor WebAssembly” step was executing “dotnet build” instead of “dotnet publish”. Build is used when you are building and running the app locally, but when you want to actually deploy the app you need to use the publish command so that it packages up the site so that it can be executed in a production environment.

With that change my S3 bucket now contained the wwwroot directory, but now the issue was that it didn’t copy the contents of the directory, it copied the entire directory so the only thing in the root of my s3 bucket was “wwwroot” and not index.html which needs to be in the root in order to execute. The problem here turned out to be in the “Publish to AWS S3” step. It was syncing “./publish” rather than “./publish/wwwroot”. Once I made that change, the contents of wwwroot were copied up and showed in the root of my s3 bucket and my application ran flawlessly!

I have used ChatGPT a few times now and I do believe it is an extremely powerful tool for HELPING find a solution to problems, but I have yet had it generate a solution that was flawless. My advise to anyone using it is always review the code it generates and make sure you understand everything it is doing. In this case it saved me potentially hours of work piecing together the steps by flipping through documentation and scouring stack overflow but I still had to tweak it and that was only possible because I reviewed the code and had a general understanding what it was executing.

Links