Remove stress

from deploying your unity game with gitlab CI

"Can you make new build?"

  • Compile
  • Run tests
  • Have testers play it
  • Upload to server
  • Announce maintenance
  • Publish
Filip Loster

Vile Monarch

Senior Developer

Live Service Game

Lead Developer

Is it worth the cost to set it all up?

Choose your tool

(in no particular order)

  • Team City - Great integration with IntelliJ tools
  • Jenkins - Easy setup, clear focus on only CI
  • Unity cloud build - Effortless, hosted CI
  • Gitlab - Great free plan, complete package

But why Gitlab?

  • It's like github, but with better free plan
  • Free, private, git repos
  • Unlimited, self hosted, build agents
  • Complete package
  • Code reviews
  • Merge requests

High level gitlab concepts

YAML file

  • .gitlab-ci.yml (can be changed in settings)
  • Entry point for configuration
  • Can be split into multiple files

Script

  • Command run in the shell
  • Returning anything else than 0 to fail
  • Unity CLI interface: -batchmode -quit -projectPath Path
  • Running static method: -executeMethod FileName.StaticMethodName

Job

  • Basic building block
  • Can run multiple scripts in sequence
  • Fails if any of it's script fails
  • Outputs artefacts

Job artefact

  • Output of the job
  • Marked files/directories in the job
  • Can be passed on to next jobs
  • Are kept for the duration of their expiration date

Stage

  • Collection of jobs
  • Usually build, test, deploy

Pipeline

  • Collection of stages
  • Dynamically assembled from jobs

Exhibit A

Nightly game builds

  • Three jobs: test, build, deploy
  • Run periodically

Test job


nightly-test:
  only: 
    - schedules
  stage: test
  script:     
    - run_tests.sh
						

Build Job


nightly-build:
  stage: build
  only: 
    - schedules
  script:
    - "Unity.exe -projectPath . 
      -quit 
      -nographics 
      -batchmode 
      -buildWindowsPlayer ./.build/windows"
  tags:
    - windows	 
  artifacts:
    expire_in: 1 week
    paths:
      - ./.build/windows
						

Upload job


nightly-upload:
  stage: deploy
  only: 
    - schedules
  script:
    - upload.sh ./.build/windows
  tags:
    - fastnet
  dependencies:
    - nightly-build
						

Full Script


stages:
  - test 
  - build
  - deploy

nightly-test:
  only: 
    - schedules
  stage: test
  script:     
    - run_tests.sh

nightly-build:
  stage: build
  only: 
    - schedules
  script:
    - "Unity.exe -projectPath . 
      -quit 
      -nographics 
      -batchmode 
      -buildWindowsPlayer ./.build/windows"
  tags:
    - windows	 
  artifacts:
    expire_in: 1 week
    paths:
      - ./.build/windows

nightly-upload:
  stage: deploy
  only: 
    - schedules
  script:
    - upload.sh ./.build/windows
  tags:
    - fastnet
  dependencies:
    - nightly-build
						

Different ways of running a pipeline

On branch


job-branch:
  only:    
    - /^release.*$/
  except:
    - tags
						
  • branch: releaseBIG_RELEASE
  • branch: releaseSMALL_RELEASE

On tag


job-tag:
  only:    
    - /^tag.*$/
  except:
    - branches
						

Manual


job-only-manual:
  rules: 
    - if: '$CI_PIPELINE_SOURCE == "web"'
						

Variables


job-on-variable:
  rules: 
    - if: '$CUSTOM_VARIABLE == "foo"'
						

Chat-Ops


hello-world:
  stage: chatops
  only: [chat]
  script:
    - echo "Hello World"

Exhibit B

Regular Updates

  • Release to production every week
  • Handle manual testing
  • Be able to hot-fix releases
  • Maintain sanity - don't slow down development!

What is git flow

Why do we need it?

  • Ensure stability of releases
  • Testing takes time
  • Independent feature development
  • Be able to roll back and hot-fix

How do pipelines come into this?

Manual pipeline


manual-prepare:
  stage: test
  rules: 
    - if: '$CI_PIPELINE_SOURCE == "web"'
  script:     
    - run_tests.sh

manual-build-windows:
  stage: build
  rules: 
    - if: '$CI_PIPELINE_SOURCE == "web"'
  script:
    - "Unity.exe -projectPath . -batchmode 
      -buildWindowsPlayer ./.build/windows"
  tags: windows
  artifacts:
    paths: ./.build/windows

manual-build-android:
  stage: build
  rules: 
    - if: '$CI_PIPELINE_SOURCE == "web"'  
  script:
    - "Unity.exe -projectPath . -batchmode 
      -buildTarget Android
  tags: windows	 
  artifacts:
    paths: ./.build/android

manual-notify:
  stage: notify
  rules: 
    - if: '$CI_PIPELINE_SOURCE == "web"'  
  script:
    - notify.sh
  dependencies:

Release Pipeline


release-build-all:
  stage: build
  only:
    - /^release.*$/i
  except:
    - tags
  script:
    - "Unity.exe -projectPath . -batchmode 
      -buildTarget Android
    - "Unity.exe -projectPath . -batchmode 
      -buildTarget Windows
  tags: windows android
  artifacts:
    paths: ./.build

release-build-bundles:
  stage: build
  only:
    - /^release.*$/i
  except:
    - tags
  script:
    - "Unity.exe -projectPath . -batchmode 
      -buildTarget Android"
  tags: windows	 
  artifacts:
    paths: ./.build/android

release-upload:
  stage: deploy
  only:
    - /^release.*$/i
  except:
    - tags
  script:
    - upload.sh
  dependencies:
    - release-build-all

Live Pipeline


live-build-all:
  stage: build
  only:
    - /^live.*$/i
  except:
    - branches
  script:
    - "Unity.exe -projectPath . -batchmode 
      -buildTarget Android
    - "Unity.exe -projectPath . -batchmode 
      -buildTarget Windows
  tags: windows android
  artifacts:
    paths: ./.build

live-upload:
  stage: deploy
  only:
    - /^live.*$/i
  except:
    - branches
  script:
    - upload.sh
  dependencies:
    - live-build-all
  when: manual
    allow_failure: false

Full script


stages:
  - test
  - build
  - upload

include:
  - local: '/manual.yml'
  - local: '/release.yml'
  - local: '/live.yml'

"But my team uses SVN"

Benefits of switching to git

  • Robust branching model
  • Not network-bound
  • Easier conflict resolution
  • Faster diffing / tree browsing
  • Great at working with code
  • Distributed and decentralised

Benefits of svn

  • Easier to understand and use
  • Handles binary blobs better
  • Allows for granural access to files

Have best of booth worlds?

  • Initialise git repository inside trunk
  • Add .git to ignored files by svn
  • Introduce separate branch to synchronise with svn
  • Use it as a contact point between both repositories

What is gitlab runner

  • Self hosted build machine
  • You can use machines already in your company
  • Machines can run subset of jobsa

Installing a runner

  • Install git, accessible from command line
  • Install client
  • Register runner, using token from website
  • Start runner

Runner configuration

config.toml


concurrent = 1
check_interval = 0

[session_server]
  session_timeout = 1800

[[runners]]
  name = "Filip-personal-pc"
  url = "https://gitlab.com/yourproject"
  token = "ABCDEFGH"
  executor = "shell"
  shell = "powershell"
  output_limit = 12288
  [runners.custom_build_dir]
  [runners.cache]
    [runners.cache.s3]
    [runners.cache.gcs]

Tips for installing runner on Windows

  • Use admin account name (or find out using whoami)
  • Register runner using: install -u "admin_name" -m "admin_password"
  • run: services.msc -> Services -> gitlab-runner properties -> logon -> set credentials again

Tips for running unity CLI on windows

  • UnityBuildRunner

General tips

  • Aim for 100% of the pipeline to be automated
  • Use pipeline number as a base for build version number
  • Most tools have CLI interface
  • Most web forms can be filled out using curl...
  • ...but don't forget to scrap csrf token first
  • Try to paralellise your builds using dag...
  • ...but watch out for nasty bugs
https://gitlab.com/gitlab-org/gitlab/-/issues/31526

What we get

(usually)


www.filiploster.com