Create a Unity to itch.io Deployment Pipeline Using Butler & Bash Scripting
Tags: unity3d, bash, automation, gamedev
Published: 2022-01-22 21:53:53

I recently uploaded my [first game to itch.io](https://donjuanjavier.itch.io/rexel-2d), and discovered that there is a nifty tool called [Butler](https://itch.io/docs/butler/) that allows uploading a build from the command line.

However, I wanted to streamline the build -> zip -> upload steps, so here's what I did:

## 1: Create WebGL build in Unity

First, I followed the [official Unity docs for publishing WebGL games](https://learn.unity.com/tutorial/creating-and-publishing-webgl-builds).

In the Unity Build Settings, I selected a WebGL build and made sure to turn compression off in **Player Settings** (`Project Settings -> Player`), after [running into an issue with the build not working in the browser](https://forum.unity.com/threads/webgl-build-doesnt-load-in-browser.948400/#post-6395847).

![Disable compression in Unity Player Settings](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7ld4qe4fkcxn3ahx14oa.png)

Finally, I made sure all of my scenes were checked that I wanted to include, and selected **Build** (I also always use the Clean Build option). I used the default build path of `./Build`.

![Unity Build Settings](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qtslynt17pj1xoloch2p.png)

## 2: (Optional) add docker-compose to test WebGL build

After the build completed, I wanted to test things out before uploading to itch.io. I followed [this guide](https://dev.to/tomowatt/running-an-unity-webgl-game-within-docker-5039) to set up my own docker-compose file to run things locally.

BTW, getting Docker to work on a Windows machine took some effort... I had to enable CPU virtualization in my BIOS settings. I'm a BIOS noob, so that was a little scary, but I finally got things working, and `docker-compose up` worked like a charm.

## 3: Adding `deploy.sh` script

I wanted my script to automate two things:

1. Packaging my build into a `.zip` file
2. Uploading to itch.io via Butler

My Windows machine uses 7-Zip for archive creation/extraction, so [I had to add 7-Zip to my Windows path](https://stackoverflow.com/questions/14122732/unzip-files-7-zip-via-cmd-command). (Alternatively, I could have used the `zip` command, but it wasn't working for me - I didn't feel like going through the hassle of [installing GoW](https://stackoverflow.com/questions/38782928/how-to-add-man-and-zip-to-git-bash-installation-on-windows) just to use `zip`).

Next, I needed to install Butler and add it to my Windows path. I just added a directory called `C:\Bin` and placed the downloaded Butler folder there, and set the Windows path to `C:\Bin\Butler`.

After all was said and done, I could run the following commands:

```bash
# zip file to archive
ZIPFILE="/path/to/zipfile-to-create"
7z a $ZIPFILE "/path/to/Build" > NUL
```

_(Note, the `> NUL` above simply silences the output from the zip command; also `NUL` would be `/dev/null` on Mac/Linux)._


```bash
# upload to itch.io
USERNAME="my-itch-io-username"
GAME="my-awesome-game"
CHANNEL="html"
VERSION=1.0.0
butler push $ZIPFILE "${USERNAME}/${GAME}:${CHANNEL}" --userversion $VERSION
```

Viola! Everything worked like a charm, and my newly-uploaded `.zip` file now showed up in my edit game page.

## Conclusion

Now that this script is in place, deploying new releases for my game is ridiculously easy. Hopefully this guide can help you streamline your game release cycle as well.

![Deploy script in action](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fdhye09rvh3m08d0d75w.png)

Here's my full `deploy.sh` script:

`Config/deploy.sh`

```bash
#!/bin/bash

USERNAME="my-itch-io-username"
GAME="my-awesome-game"
CHANNEL="html"

#
# COLORS
# see: https://stackoverflow.com/questions/5947742/how-to-change-the-output-color-of-echo-in-linux
#
NC='\033[0m'              # No Color
BLACK='\033[0;30m'        # Black
RED='\033[0;31m'          # Red
GREEN='\033[0;32m'        # Green
YELLOW='\033[0;33m'       # Yellow
BLUE='\033[0;34m'         # Blue
PURPLE='\033[0;35m'       # Purple
CYAN='\033[0;36m'         # Cyan
WHITE='\033[0;37m'        # White
GREY='\033[1;30m'         # Grey

#
# UTILS
#
log() {
  echo -e "${GREY}${1}${NC}"
}
info() {
  echo -e "${CYAN}${1}${NC}"
}
success() {
  echo -e "${GREEN}✓ ${1}${NC}"
}
warn() {
  echo -e "${YELLOW}${1}${NC}"
}
error() {
  echo -e "${RED}${1}${NC}"
}
prompt() {
  read -p "$1 " -n 1 -r
  echo    # (optional) move to a new line
  if [[ ! $REPLY =~ ^[Yy]$ ]]
  then
      warn "user cancelled."
      exit 1
  fi
}
assertFileExists() {
  if [ ! -f "$1" ]; then
      error "$1 does not exist."
      exit 1
  fi
}
assertDirExists() {
  if [ ! -d "$1" ]; then
      error "$1 does not exist."
      exit 1
  fi
}

#
# GET VERSION
#
VERSION=$(cat version.json \
  | grep version \
  | head -1 \
  | awk -F: '{ print $2 }' \
  | sed 's/[",]//g' \
  | tr -d '[[:space:]]')
SAFE_VERSION="${VERSION//./$'-'}"

#
# SCRIPT
#

info "WELCOME TO THE UNITY DEPLOYMENT SCRIPT!"
info "About to push version ${RED}${VERSION}${CYAN} - proceed?"
prompt "(y/n)"

assertFileExists "../Build/index.html"
mkdir -p "../Archives"
ZIPFILE="../Archives/build-${SAFE_VERSION}.zip"

log "creating zip archive for ${ZIPFILE}..."

# zip
7z a $ZIPFILE "../Build" > NUL

log "deploying to itch.io..."

# push to itch.io
butler push $ZIPFILE "${USERNAME}/${GAME}:${CHANNEL}" --userversion $VERSION

success "All done!"

```

I also added a simple version file containing version info for my game to make it easy to update without needing to alter my script:

`Config/version.json`

```json
{
  "version": "1.0.0"
}
```

Cover Photo by <a href="https://unsplash.com/@hellolightbulb?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText">Hello  Lightbulb</a> on <a href="https://unsplash.com/s/photos/gamedev?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText">Unsplash</a>