Release and CI

On this page

Every game repo from the studio template has two GitHub Actions workflows. hygiene.yml runs on every push with no Unity licence. unity.yml runs tests and builds with GameCI (opens in a new tab), gated on the repository variable UNITY_CI=true.

#The Unity workflow

Job Action What
Test game-ci/unity-test-runner (v4.4.0) EditMode and PlayMode tests from Assets/Tests/
Build gully-labs/unity-builder (fork of game-ci/unity-builder v6.0.0) one build per target, in a matrix

Build targets:

Target Used for
StandaloneWindows64 desktop players, playtests
StandaloneLinux64 dedicated servers (headless)
Android mobile; signed when the keystore secrets exist
WebGL browser builds

Each build is uploaded as a workflow artifact. The Library/ folder is cached per target with actions/cache, which cuts repeat build times a lot.

#Pinned actions

Every action is pinned to a full commit SHA, with the version tag in a comment:

YAML
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: game-ci/unity-test-runner@32e57712352b500e17974b245a6dce9e11a73213 # v4.4.0
- uses: gully-labs/unity-builder@eb1b9fba120c6e62c9fb7a7a81d6c107ce004c45 # v6.0.0

Bump an action by pull request with the new SHA and tag. Never switch to a moving tag like @v6.

#Licence

Unity is proprietary: CI builds need a licence. The workflow reads it from secrets only.

Secret Licence type
UNITY_EMAIL, UNITY_PASSWORD always
UNITY_SERIAL Unity Pro or Unity Industry (required above the Personal revenue threshold)
UNITY_LICENSE contents of a Personal .ulf, for prototyping

Heads up

Never commit a .ulf file, a serial or a keystore. The hygiene workflow fails the build if a .ulf or .unitypackage file is committed.

Android signing uses ANDROID_KEYSTORE_BASE64, ANDROID_KEYSTORE_PASS, ANDROID_KEYALIAS_NAME and ANDROID_KEYALIAS_PASS. Without them the Android build is unsigned (fine for CI, not for a store).

#Hygiene workflow

Runs without a licence on every push and fails when:

  • the repository is public;
  • Force Text serialization or Visible Meta Files has drifted;
  • a binary that belongs in LFS was committed as a normal blob;
  • a .unitypackage or .ulf file is in the tree.

#Runners

The hosted ubuntu-latest runner is enough for the empty template. Real games need more disk, memory and time than hosted runners give, so they build on a larger runner or a self-hosted runner on Gully infrastructure. Self-hosted runners follow the same rules as other Gully services: Gully boxes only, no public ports, secrets in the runner environment.

#Never committed

Library/, Temp/, Obj/, Build/, Logs/, UserSettings/ are in Unity's .gitignore and stay out of git. Builds go to artifacts or releases, never into the repo.

#Versioning and releases

  • Version the game with tags: v<major>.<minor>.<patch>. Set the same version in Player Settings before tagging.
  • Android needs an increasing bundleVersionCode for every store upload.
  • Build release candidates from tags, not from branch heads, so a build can be reproduced.
  • Keep the editor version in ProjectSettings/ProjectVersion.txt unchanged during a release; upgrade it in its own pull request.

#A release checklist

  1. All tests green on main.
  2. Asset Store licence audit up to date (Assets/ThirdParty/README, see Asset Store licence).
  3. Version bumped and tagged.
  4. Store policy re-checked for any crypto, reward or payment change (see Store policy).
  5. Server build deployed before clients that need it.
  6. Release notes written for players.