Building and Publishing Games to Steam Directly from GitHub Actions
I have been using GitHub Actions extensively both at work and in personal projects, as shown in this post What I’ve been automating with GitHub Actions, an automated life.
In my free time, I’m working on a 2D hide-and-seek game, and as you might expect, I’ve automated the entire release pipeline for publishing on Steam. After a few attempts, when it finally worked, it felt like magic: all I had to do was create a new tag, and within minutes, the Steam client was downloading the update.
As I mentioned earlier, I have a 2D engine that, while simple, is quite comprehensive. With each new tag, I compile it in parallel for Windows, macOS, Linux, and WebAssembly. Once compilation is complete, I create a release and publish it on GitHub. Releases · willtobyte/carimbo
This way
name: Release
on:
push:
tags:
- "v*.*.*"
jobs:
release:
runs-on: ${{ matrix.config.os }}
permissions:
contents: write
strategy:
fail-fast: true
matrix:
config:
- name: macOS
os: macos-latest
- name: Ubuntu
os: ubuntu-latest
- name: WebAssembly
os: ubuntu-latest
- name: Windows
os: windows-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Cache Dependencies
uses: actions/cache@v4
with:
path: |
~/.conan2/p
C:/Users/runneradmin/.conan2/p
key: ${{ matrix.config.name }}-${{ hashFiles('**/conanfile.py') }}
restore-keys: |
${{ matrix.config.name }}-
- name: Prepare Build Directory
run: mkdir build
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: "3.12"
- name: Install Conan
run: pip install conan
- name: Detect Conan Profile
run: conan profile detect --force
- name: Set Conan Center
run: conan remote update conancenter --url https://center2.conan.io
- name: Detect WebAssembly Conan Profile
if: matrix.config.name == 'WebAssembly'
run: |
cat > ~/.conan2/profiles/webassembly <<EOF
include(default)
[settings]
arch=wasm
os=Emscripten
[tool_requires]
*: emsdk/3.1.73
EOF
- name: Install Windows Or macOS Dependencies
if: matrix.config.name == 'Windows' || matrix.config.name == 'macOS'
run: conan install . --output-folder=build --build=missing --settings compiler.cppstd=20 --settings build_type=Release
- name: Install Ubuntu Dependencies
if: matrix.config.name == 'Ubuntu'
run: conan install . --output-folder=build --build=missing --settings compiler.cppstd=20 --settings build_type=Release --conf "tools.system.package_manager:mode=install" --conf "tools.system.package_manager:sudo=True"
- name: Install WebAssembly Dependencies
if: matrix.config.name == 'WebAssembly'
run: conan install . --output-folder=build --build=missing --profile=webassembly --settings compiler.cppstd=20 --settings build_type=Release
- name: Configure
run: cmake .. -DCMAKE_TOOLCHAIN_FILE="conan_toolchain.cmake" -DCMAKE_BUILD_TYPE=Release
working-directory: build
- name: Build
run: cmake --build . --parallel 8 --config Release --verbose
working-directory: build
- name: Create Artifacts Directory
run: mkdir artifacts
- name: Compress Artifacts
if: matrix.config.name == 'macOS'
working-directory: build
run: |
chmod -R a+rwx carimbo
tar -cpzvf macOS.tar.gz carimbo
mv macOS.tar.gz ../artifacts
- name: Compress Artifacts
if: matrix.config.name == 'Ubuntu'
working-directory: build
run: |
chmod +x carimbo
tar -czvf Ubuntu.tar.gz --mode='a+rwx' carimbo
mv Ubuntu.tar.gz ../artifacts
- name: Compress Artifacts
if: matrix.config.name == 'WebAssembly'
working-directory: build
run: |
zip -jr WebAssembly.zip carimbo.wasm carimbo.js
mv WebAssembly.zip ../artifacts
- name: Compress Artifacts
if: matrix.config.name == 'Windows'
working-directory: build
shell: powershell
run: |
Compress-Archive -LiteralPath 'Release/carimbo.exe' -DestinationPath "../artifacts/Windows.zip"
- name: Release
uses: softprops/action-gh-release@v1
with:
tag_name: ${{ github.event.inputs.tagName }}
prerelease: ${{ github.events.inputs.prerelease }}
files: artifacts/*
Publishing on Steam is quite simple. First, you need a developer account with the correct documentation and fees paid.
After that, you’ll need to generate some secret keys as follows:
steamcmd +login <username> <password> +quit
If you don’t have the steamcmd application installed, you’ll need to install it using:
cast install --cask steamcmd
Copy the contents of the authentication file:
cat ~/Library/Application\ Support/Steam/config/config.vdf | base64 | pbcopy
Note: You must have MFA enabled. After logging in, run the command below and copy the output into a GitHub Action variable named STEAM_CONFIG_VDF.
Also, create the variables STEAM_USERNAME with your username and STEAM_APP_ID with your game’s ID.
Additionally, the Action downloads the latest Carimbo release for Windows only (sorry Linux and macOS users, my time is limited). Ideally, I should pin the runtime version (the Carimbo version) using something like a runtime.txt file. Maybe I’ll implement this in the future, but for now, everything runs on the bleeding edge. :-)
on:
push:
tags:
- "v*.*.*"
jobs:
publish:
runs-on: ubuntu-latest
env:
CARIMBO_TAG: "v1.0.65"
permissions:
contents: write
steps:
- name: Clone the repository
uses: actions/checkout@v4
- name: Install 7zip
run: sudo apt install p7zip-full
- name: Create bundle
run: 7z a -xr'!.git/*' -xr'!.git' -xr'!.*' -t7z -m0=lzma -mx=6 -mfb=64 -md=32m -ms=on bundle.7z .
- name: Download Carimbo runtime
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: gh release download ${{ env.CARIMBO_TAG }} --repo willtobyte/carimbo --pattern "Windows.zip"
- name: Extract Carimbo runtime
run: 7z x Windows.zip -o.
- name: Copy files
run: |
mkdir -p output
mv bundle.7z output/
mv carimbo.exe output/
- name: Upload build to Steam
uses: game-ci/steam-deploy@v3
with:
username: ${{ secrets.STEAM_USERNAME }}
configVdf: ${{ secrets.STEAM_CONFIG_VDF }}
appId: ${{ secrets.STEAM_APP_ID }}
rootPath: output
depot1Path: "."
releaseBranch: prerelease
Boom! If everything is correct, your game should appear in your Steam client under the list of owned games.