/unity3d-ci-example

🍴Additional remote of unity3d CI example project for Travis and CircleCI on Github

Primary LanguageC#MIT LicenseMIT

unity3d ci example

pipeline status Build Status

This project is a PoC to run unity3d tests and builds inside a CI using gableroux/unity3d docker image. It currently creates builds for Windows, Linux, MacOS and webgl. The webgl build is published by the CI to gitlab-pages and github-pages! You can try the built project on the published gitlab-pages.

github-pages integration will be done in GabLeRoux/unity3d-ci-example#4.

Git remotes

This repository is hosted on multiple remotes to provide examples for Gitlab-CI, Travis and CircleCI

Table of Contents generated with DocToc

Getting started

If you don't have a Unity project yet:

  1. Fork this project from github or gitlab
  2. Update the readme and remove undesired CI configurations
  3. Follow How to activate instructions
  4. Configure your CI environment variables (once everything is set, you should only need UNITY_LICENSE_CONTENT in your project variables)

If you already have your own project:

  1. Copy desired ci file (.gitlab-ci.yml, or .travis.yml, etc.)
  2. Copy BuildScript.cs (make sure you use the same path as original project, it must be in an Editor folder)
  3. Copy ci folder
  4. Update the Unity version according to your project version in the CI file. All versions are available at gableroux/unity3d docker image
  5. Follow How to activate instructions
  6. Configure your CI environment variables (once everything is set, you should only need UNITY_LICENSE_CONTENT in your project variables)

Points of interest

This is probably what you're looking for.

Build script

Script passed to the unity3d command line as argument to create builds

You need to have this file in your project in order to build your project in the CI.

CI Configuration

Pick one, if you're on gitlab, use gitlab-ci as Travis and CircleCI don't support Gitlab as of september 2018, if you're on github, Travis is more popular but CircleCI and gitlab-ci will also work. If you can't decide, see CircleCI vs. GitLab CI/CD and Travis CI vs GitLab.

You need to have one of these files in your project in order to build your project to actually use your CI.

gitlab-ci

Note: you can add BuildOptions per target by adding environment variable BuildOptions.

build-ios:
  <<: *build
  image: gableroux/unity3d:2019.3.7f1-android
  variables:
    BUILD_TARGET: iOS
	BuildOptions: AcceptExternalModificationsToPlayer

If you would like to use several BuildOptions, you have to separate all values by , :

	BuildOptions: AcceptExternalModificationsToPlayer,CompressTextures,ConnectToHost

See HERE for BuildOptions values.

WIP: CircleCI

TODO

Travis

Test files

How to activate

There are a few methods available, if you're using gitlab-ci, the easiest method in the current documentation is using gitlab-ci.

Unity Personal

a. Using gitlab-ci

Once you've added all required files to your project (mainly .gitlab-ci.yml), there should be a manual step that can be triggered for activation.

  1. Visit your project's settings > CI/CD > Variables and add UNITY_USERNAME and UNITY_PASSWORD with your credentials
  2. Push your first commit to your project and visit CI/CD Pipelines.
  3. Locate your latest job, there should be a play button, click on it and click get-activation-file
  4. Wait for the job to run and follow instructions in the console

b. Locally

All you need is docker installed on your machine.

  1. Clone this project

  2. Pull the docker image and run bash inside, passing unity username and password to env

    hint: you should write this to a shell script and execute the shell script so you don't have your credentials stored in your bash history. Also make sure you use your Unity3d email address for UNITY_USERNAME env var.

    UNITY_VERSION=2019.3.7f1
    docker run -it --rm \
    -e "UNITY_USERNAME=username@example.com" \
    -e "UNITY_PASSWORD=example_password" \
    -e "TEST_PLATFORM=linux" \
    -e "WORKDIR=/root/project" \
    -v "$(pwd):/root/project" \
    gableroux/unity3d:$UNITY_VERSION \
    bash

    If your password contains a !, you can escape it like this (example_pass!word):

    ...
    -e "UNITY_PASSWORD=example_pass"'!'"word" \
    ...
  3. In Unity docker container's bash, run once like this, it will try to activate

    xvfb-run --auto-servernum --server-args='-screen 0 640x480x24' \
    /opt/Unity/Editor/Unity \
    -logFile /dev/stdout \
    -batchmode \
    -username "$UNITY_USERNAME" -password "$UNITY_PASSWORD"
  4. Wait for output that looks like this:

    LICENSE SYSTEM [2017723 8:6:38] Posting <?xml version="1.0" encoding="UTF-8"?><root><SystemInfo><IsoCode>en</IsoCode><UserName>[...]
    

    If you get the following error:

    Can't activate unity: No sufficient permissions while processing request HTTP error code 401

    Make sure your credentials are valid. You may try to disable 2FA in your account and try again. Once done, you should enable 2FA again for security reasons. See #11 for more details.

  5. Copy xml content and save as unity3d.alf

  6. Open https://license.unity3d.com/manual and answer questions

  7. Upload unity3d.alf for manual activation

  8. Download Unity_v2018.x.ulf (Unity_v2019.x.ulf for 2019 versions)

  9. Copy the content of Unity_v2018.x.ulf license file to your CI's environment variable UNITY_LICENSE_CONTENT. Note: if you are doing this on windows, chances are the line endings will be wrong as explained here. Luckily for you, .gitlab-ci.yml solves this by removing \r character from the env variable so you'll be alright .gitlab-ci.yml will then place the UNITY_LICENSE_CONTENT to the right place before running tests or creating the builds.

Unity Plus/Pro

  1. Clone this project

  2. Pull the docker image and run bash inside, passing unity username and password to env

    hint: you should write this to a shell script and execute the shell script so you don't have your credentials stored in your bash history. Also make sure you use your Unity3d email address for UNITY_USERNAME env var.

    UNITY_VERSION=2019.3.7f1
    docker run -it --rm \
    -e "UNITY_USERNAME=username@example.com" \
    -e "UNITY_PASSWORD=example_password" \
    -e "UNITY_SERIAL=AN-EXAM-PLE-SERIA-LKEY-1234" \
    -e "TEST_PLATFORM=linux" \
    -e "WORKDIR=/root/project" \
    -v "$(pwd):/root/project" \
    gableroux/unity3d:$UNITY_VERSION \
    bash
  3. In Unity docker container's bash, run once like this, it will try to activate

    xvfb-run --auto-servernum --server-args='-screen 0 640x480x24' \
    /opt/Unity/Editor/Unity \
    -logFile /dev/stdout \
    -batchmode \
    -username "$UNITY_USERNAME" -password "$UNITY_PASSWORD" -serial "$UNITY_SERIAL"
  4. Wait for the command to finish without errors

  5. Obtain the contents of the license file by running cat /root/.local/share/unity3d/Unity/Unity_lic.ulf

  6. Copy the content to your CI's environment variable UNITY_LICENSE_CONTENT. Note: if you are doing this on windows, chances are the line endings will be wrong as explained here. Luckily for you, .gitlab-ci.yml solves this by removing \r character from the env variable so you'll be alright .gitlab-ci.yml will then place the UNITY_LICENSE_CONTENT to the right place before running tests or creating the builds.

Unity license per target

Before 2018.4.8f1 for 2018 versions and before 2019.2.4f1 for 2019 versions, if you need a specific Unity license for a build target, you can add environment var UNITY_LICENSE_CONTENT_{BUILD_TARGET}. (UNITY_LICENSE_CONTENT_ANDROID, UNITY_LICENSE_CONTENT_IOS, ...). _This is not required anymore now that images share a base image See related change**

Note about components in recent images

Starting from these versions, base image doesn't include windows, mac and webgl components anymore. This means you must use -mac, -windows or -webgl images. See related change

Travis

Travis doesn't support multiple-lines env variable out of the box and I had troubles with escaping so I recommend encrypting the license file. .travis.yml will decrypt the file and add its content to UNITY_LICENSE_CONTENT env var itself afterward.

travis encrypt-file --pro -r YOUR_TRAVIS_USERNAME/YOUR_TRAVIS_REPO_NAME ./Unity_v2018.x.ulf # TODO confirm new file name for 2019

For the record, the message I was getting:

The previous command failed, possibly due to a malformed secure environment variable. Please be sure to escape special characters such as ' ' and '$'. For more information, see https://docs.travis-ci.com/user/encryption-keys.

How to add build targets

Supported build targets can be found here

gitlab-ci

Update .gitlab-ci.yml by adding a build section like this:

build-StandaloneWindows64:
  <<: *build
  variables:
    BUILD_TARGET: StandaloneWindows64

iOS support

Setup (only one time per mac)

Install the latest Xcode command line tools :

xcode-select --install

Install fastlane using:

# Using RubyGems
sudo gem install fastlane -NV

# Alternatively using Homebrew
brew install fastlane

Unity Settings

  1. Switch target to iOS
  2. In PlayerSettings -> Other Settings
    1. Fill the field Signing Team ID
    2. Ensure Automatically Sign is unchecked
    3. iOS Provisioning Profile
      1. ProfileID: match AppStore your_bundle_identifier Replace your_bundle_identifier by yours
      2. ProfileType: Distribution

XCode project

Make a first iOS build using your mac from Unity, that will create an xcode project.
Ensure your target the same path than the ci.
Ex: if you let BUILD_NAME: ExampleProjectName in .gitlab-ci.yml, your xcode project must be at the root of the following path: .\Builds\iOS\ExampleProjectName\

App on portail

Make sure that you have setup your app on the Apple Developer Portal and the App Store Connect or use fastlane produce to create it.

Fastlane initialization

Open the terminal at the same path then run fastlane init, follow instructions to generate Appfile and default Fastfile.

Provisioning profile

Run fastlane match init, follow instructions, select appstore provisioning profile type. (Documentation)

Make lane

Copy the following instructions on your fastlane/Fastfile:

default_platform(:ios)

platform :ios do
  desc "Push a new beta build to TestFlight"
  lane :beta do
    sync_code_signing(type:"appstore", readonly: is_ci)
    increment_build_number({
        build_number: latest_testflight_build_number + 1
    })
    build_app(scheme:"Unity-iPhone")
    upload_to_testflight(groups:["Team"]) 
  end
end

Note about upload_to_testflight: Change "Team" to your internal tester or remove (groups:["Team"]) if you want set manually who can test the build

Related documentation

Run tests locally

Run the following command to test the build and the deployement localy:

fastlane ios beta

If the build and upload are ok, you have to force add some file to your git using command below

git add -f pathToTheFileToAdd

you have to add the following files:

  • Gemfile
  • Gemfile.lock (if here)
  • fastlane/Appfile
  • fastlane/Fastfile
  • fastlane/Matchfile

Gitlab-runner - register your mac

To automate your build with gitlab, you need to setup your mac as a gitlab runner.
Installation:

sudo curl --output /usr/local/bin/gitlab-runner https://gitlab-runner-downloads.s3.amazonaws.com/latest/binaries/gitlab-runner-darwin-amd64

Give permission to execute :

sudo chmod +x /usr/local/bin/gitlab-runner

Go to your project gitlab page, then go to settings -> CI/CD -> Runners -> Specitic Runners -> Set up a specific Runner manually -> take note of the token

Follow these instructions to register your mac as a gitlab-runner for your specific project.
Follow macOS instructions without sudo command for registration.

  • Tags: set mac,ios
  • Executor: set shell

Then, to install/launch the runner:

cd ~ 
gitlab-runner install
gitlab-runner start

Runner is installed and will be run after a system reboot.

Now, you can uncomment the job build-and-deploy-ios in .gitlab-ci.yml to make the app build and deployement work.

Android support

To make build working with Android, you will need a specific Unity license (because that is not the same docker image).
Add the content of your specific Unity license in your CI's environment variable : UNITY_LICENSE_CONTENT_ANDROID

By default the apk is not signed and the build will use the Unity's default debug key.
For security reason, you must not add your keystore to git.
Encode your keystore file as base64 using openssl:
openssl base64 -A -in yourKeystore.keystore

Copy the result to your CI's environment variable ANDROID_KEYSTORE_BASE64

Add following environment variables:

  • KEYSTORE_PASS: Keystore pass
  • KEY_ALIAS_NAME: Keystore alias name to use (if not set, the program will use the alias name set in Project's PlayerSettings)
  • KEY_ALIAS_PASS: Keystore alias pass to use

Note about keystore security, if you would like to use another solution for storage, see HERE.

Android app bundle

BUILD_APP_BUNDLE env var is defined in gitlab-ci.yml. Set it to true to build an .aab file.
Note: to build an android app bundle, you need an image with Android NDK. See related issue gableroux/unity3d#61

Bundle version code

The bundle version code must be increment for each deployed build.
To simplify the process, the BUNDLE_VERSION_CODE env var is used and set as bundle version code.
Currently, for gitlab, BUNDLE_VERSION_CODE = $CI_PIPELINE_IID. Documentation
If you use another CI solution, set a CI env var incrementing for each pipeline.

Fastlane supply (deployement)

Follow setup instructions to get a google play console token, then, add the content to env var GPC_TOKEN.
Uncomment the #deploy-android job in gitlab-ci.yml and replace com.youcompany.yourgame by your package name.
You can change the track internal to alpha, beta or production.

That is the simplest way with command line but you can also make fastlane/Fastfile and fastlane/Appfile, with the following command after building a temporary gradle project (export gradle project option in Unity build settings):

fastlane init

Then run the following command:

fastlane supply init

and update all metadata, images, changelogs, etc... These will be uploaded to the store everytime. Refer to fastlane supply documentation for more details.

How to run scripts manually

You can execute the local scripts and specify the path of your Unity executable using UNITY_EXECUTABLE. You may try this in your project before you setup the whole CI so you confirm it works with your current unity version 👍

Test

UNITY_EXECUTABLE="/Applications/Unity/Hub/Editor/2019.3.7f1/Unity.app/Contents/MacOS/Unity" \
  ./local_test.sh

Build

UNITY_EXECUTABLE="/Applications/Unity/Hub/Editor/2019.3.7f1/Unity.app/Contents/MacOS/Unity" \
  ./local_build.sh

About the example project

This is an updated version of the Unity's Creator Kit: RPG free asset which is not affiliated with this project at all. Feel free to explore it, dialogs are updated ;)

Get involved

There is a discord #technical-english channel at totema.studio/discord. Feel free to join in! I will be looking for maintainers as this project is getting more and more attention 🎉.

Shameless plug

I made this for free as a gift to the video game community so if this tool helped you and you would like to support me, send your love to Totema Studio on Patreon: 🍻

Totema Studio Logo

Become a Patron

License

MIT © Gabriel Le Breton