文章目录
- 一、基本概念介绍
- 二、为你的Unity项目创建自动化构建
- 三、Q&A
一、基本概念介绍
- Gitlab CI/CD
GitLab CI/CD(后简称 GitLab CI)是一套基于 GitLab 的 CI/CD 系统,可以让开发人员通过 .gitlab-ci.yml 在项目中配置 CI/CD 流程,在提交后,系统可以自动/手动地执行任务,完成 CI/CD 操作。而且,它的配置非常简单,CI Runner 由 Go 语言编写,最终打包成单文件,所以只需要一个 Runner 程序、以及一个用于运行 jobs 的执行平台(如裸机+SSH,Docker 或 Kubernetes 等,我推荐用 Docker,因为搭建相当容易)即可运行一套完整的 CI/CD 系统。
- GitLab CI/CD 整体流程
- GitLab CI/CD 的 pipeline 具体流程和操作在 .gitlab-ci.yml 文件中申明。
- 触发 pipeline 后,由 GitLab Runner 根据 .gitlab-ci.yml 文件运行。
- 运行结束后将返回至 GitLab 系统。
- .gitlab-ci.yml 文件
.gitlab-ci.yml文件是一个申明式文件,文件中指定了CI的触发条件、工作内容、工作流程,编写和理解此文件是CI实战中最重要的一步,该文件指定的任务内容总体构成了1个pipeline、1个pipeline包含不同的stage执行阶段、每个stage包含不同的具体job脚本任务。
- Gitlab Runner
- GitLab Runner 是 CI 的执行环境,负责执行 gitlab-ci.yml 文件,并将结果返回给 GitLab 系统。
- Runner可以分为两种: Specific Runner 和 Shared Runner
- Shared Runner是Gitlab平台提供的免费使用的runner程序,它由Google云平台提供支持,每个开发团队有十几个。对于公共开源项目是免费使用的,如果是私人项目则有每月2000分钟的CI时间上限。
- Specific Runner是我们自定义的,在自己选择的机器上运行的runner程序,gitlab给我们提供了一个叫gitlab-runner的命令行软件,只要在对应机器上下载安装这个软件,并且运行gitlab-runner register命令,然后输入从gitlab-ci交互界面获取的token进行注册, 就可以在自己的机器上远程运行pipeline程序了。
- Pipeline & stage & Job
Pipeline: 管道,每次commit或MR都会执行一次pipeline构建任务,包含多个阶段如测试、编译。
stage: 阶段,每个Pipeline有多个Stage,从上向下执行,前一个执行成功才能执行下一个
Job: 任务,CI/CD的最小运行单位,表示在指定Stage下执行的任务工作,可以有多个Job,并行执行。
二、为你的Unity项目创建自动化构建
- 如果你在GitLab上没有账户,请创建一个
- Gitlab设置
- 项目设置
(1). 使用Unity在本地创建的你的项目
(2).访问Gitignore,搜索"Unity"并创建。随后在项目的根目录创建一个.gitignore文件并将上一步创建的内容粘贴到文件中,以避免上传不必要的文件
(3). 项目根目录下,打开Git bash here窗口,执行以下命令,提交本地项目到远端仓库
git init
git remote add origin 远端仓库地址/unity3d-gitlab-ci-example.git
git add .
git commit -m "initial commit"
git push -u origin master
- 参考Game CI为你的项目启动Gitlab-CI
(1) 文档:https://game.ci/docs/gitlab/getting-started(2)项目示例:https://gitlab.com/game-ci/unity3d-gitlab-ci-example/(3)克隆示例项目到本地拷贝示例项目根目录下的".gitlab-ci.yml"文件和"ci"文件夹到你的存储库的根目录。拷贝示例项目根目录下的"/Assets/Scripts/Editor/BuildCommand.cs"脚本到你的存储库的根目录"/Assets/Scripts/Editor/“文件夹下(4)打开并编辑你项目下的”.gitlab-ci.yml"文件,修改BUILD_NAME属性为你的项目名称,UNITY_VERSION属性设置Unity版本。在此要特别说明一下,官方的示例中是没有"UNITY_VERSION"属性,它是通过执行get-unity-versionjob访问项目根目录ProjectSettings/ProjectVersion.txt获取Unity的版本,但是经测试,在CI Lint检查时报错get-unity-version在执行get-activation-filejob之前没有定义",因此我这里将get-unity-versionjob删除了,在属性中增加了UNITY_VERSION来设置Unity版本
- 提交新增文件到远程仓库
gitlab在检测到yml文件后,自动创建pipeline
- 激活
(1)访问Projects->Settings->CI/CD->Variables,添加UNITY_USERNAME和UNITY_PASSWORD属性,Value分别为你注册Unity的邮箱和密码
(2)回到projects->CI/CD->Pipelines,查看任务并点击get-acticvation-file右边的play按钮(需要要等待一会),job作业执行成功后,点击get-acticvation-file按钮,查看执行任务流程,左边的Download下载Unity3d.alf文件
(3) 访问 https://license.unity3d.com/manual,上传unity3d.al,生成Unity证书并下载Unity2020.x.ulf文件(注:ulf问价的年份应与Unity版本年份保持一致)
(4) 访问Projects->Settings->CI/CD->Variables,添加"UNITY_LICENSE"属性,并将ulf文件的内容复制到Value值中 - 可用的Runner
Gitlab Runner主要分为Specific Runner、Group Runner和Share Runner。在此仅介绍使用Specific Runner和Share Runner构建你的项目
- Specific Runner(指定),我们可以在本地下载gitlab-runner命令行软件,来服务Gitlab CI
(1)在系统的某处创建一个文件夹,例如:D:Gitlab-Runner
(2)GitLab-Runner下载Windows系统下载64位二进制文件并将其放入你创建的文件夹,重命名为gitlab-runner
(3)务必以管理员运行cmd,切换到你创建的文件夹下,输入"gitlab-runner register"注册Runner(注册Runner是要与你Gitlab项目建立联系,需要提供项目的URL和令牌,Projects->Settings->CI/CD->Runner->Specific Runner)
(4)注册
Enter the GitLab instance URL (for example, https://gitlab.com/):
输入URL
Enter the registration token:
输入令牌
Enter a description for the runner:
输入Runner描述
Enter tags for the runner (comma-separated):
输入Runner的标签,(yml文件,job通过设置tags标签选用指定的Runner)
Enter optional maintenance note for the runner:
输入可选维护说明
Enter an executor: docker+machine, docker-ssh+machine, custom, docker-windows, docker-ssh, ssh, kubernetes, docker, parallels, shell, virtualbox:
输入shell
回车结束,安装gitlab-runner文件夹下会自动生成config.
输入gitlab status查看状态,gitlab start启动runner,gitlab stop暂停Runner
注册成功后,回到Projects->Settings->CI/CD->Runner->Specific Runner,状态如下注册成功
8. shared runner
yml文件中,可以设置tags标签选择指定的Runner,若关闭tags属性,并Projects->Settings->CI/CD->Runner->Shared Runner没有禁用,任务执行时会自动选择可用的Shared Runner
9.编辑yml文件
Unity 版本修改
(1)yml文件修改UNITY_VERSION属性为"2020.3.6f1"
(2)项目根目录下->ProjectSettings->ProjectVersion.txt修改Unity版本"2020.3.6f1"
yml文件可以注销build job,自由选择需要打包的平台
如下提供的是使用Shared Runner,若想测试Specific runner,请get-activation-file、.test-with-junit-reports: &test-with-junit-reports、.build: &build任务job添加tags并指定runner标签
stages:
- prepare
- build_and_test
- deploy
variables:
BUILD_NAME: unity3d-gitlab-ci-example
UNITY_ACTIVATION_FILE: ./unity3d.alf
UNITY_VERSION: "2020.3.6f1"
IMAGE: unityci/editor
IMAGE_VERSION: "0.17"
UNITY_DIR: $CI_PROJECT_DIR
VERSION_NUMBER_VAR: $CI_COMMIT_REF_SLUG-$CI_PIPELINE_ID-$CI_JOB_ID
VERSION_BUILD_VAR: $CI_PIPELINE_IID
KUBERNETES_CPU_REQUEST: 2000m
KUBERNETES_CPU_LIMIT: 3000m
KUBERNETES_MEMORY_REQUEST: 8Gi
KUBERNETES_MEMORY_LIMIT: 10Gi
image: $IMAGE:$UNITY_VERSION-base-$IMAGE_VERSION
.unity_before_script: &unity_before_script
before_script:
- chmod +x ./ci/before_script.sh && ./ci/before_script.sh
.cache: &cache
cache:
key: "$CI_PROJECT_NAMESPACE-$CI_PROJECT_NAME-$CI_COMMIT_REF_SLUG-$TEST_PLATFORM"
paths:
- $UNITY_DIR/Library/
.license: &license
rules:
- if: '$UNITY_LICENSE != null'
when: always
.unity_defaults: &unity_defaults
<<:
- *unity_before_script
- *cache
- *license
get-activation-file:
<<: *unity_before_script
rules:
- if: '$UNITY_LICENSE == null'
when: manual
stage: prepare
script:
- chmod +x ./ci/get_activation_file.sh && ./ci/get_activation_file.sh
artifacts:
paths:
- $UNITY_ACTIVATION_FILE
expire_in: 10 min
.test: &test
stage: build_and_test
<<: *unity_defaults
script:
- chmod +x ./ci/test.sh && ./ci/test.sh
artifacts:
when: always
expire_in: 2 weeks
# tags:
# - gitlab-org
coverage: /<Linecoverage>(.*?)</Linecoverage>/
# Tests without junit reporting results in GitLab
# test-playmode:
# <<: *test
# variables:
# TEST_PLATFORM: playmode
# TESTING_TYPE: NUNIT
# test-editmode:
# <<: *test
# variables:
# TEST_PLATFORM: editmode
# TESTING_TYPE: NUNIT
.test-with-junit-reports: &test-with-junit-reports
stage: build_and_test
<<: *unity_defaults
script:
- apt-get update && apt-get install -y default-jre libsaxonb-java
- chmod +x ./ci/test.sh && ./ci/test.sh
- saxonb-xslt -s $UNITY_DIR/$TEST_PLATFORM-results.xml -xsl $CI_PROJECT_DIR/ci/nunit-transforms/nunit3-junit.xslt >$UNITY_DIR/$TEST_PLATFORM-junit-results.xml
artifacts:
when: always
paths:
- $UNITY_DIR/$TEST_PLATFORM-coverage/
reports:
junit:
- $UNITY_DIR/$TEST_PLATFORM-junit-results.xml
- "$UNITY_DIR/$TEST_PLATFORM-coverage/coverage.xml"
expire_in: 2 weeks
# tags:
# - gitlab-org
coverage: /<Linecoverage>(.*?)</Linecoverage>/
test-playmode-with-junit-reports:
<<: *test-with-junit-reports
variables:
TEST_PLATFORM: playmode
TESTING_TYPE: JUNIT
test-editmode-with-junit-reports:
<<: *test-with-junit-reports
variables:
TEST_PLATFORM: editmode
TESTING_TYPE: JUNIT
.build: &build
stage: build_and_test
<<: *unity_defaults
script:
- chmod +x ./ci/build.sh && ./ci/build.sh
artifacts:
paths:
- $UNITY_DIR/Builds/
# tags:
# - gitlab-org
#build-StandaloneLinux64:
# <<: *build
# variables:
# BUILD_TARGET: StandaloneLinux64
#build-StandaloneLinux64-il2cpp:
# <<: *build
# image: $IMAGE:$UNITY_VERSION-linux-il2cpp-$IMAGE_VERSION
# variables:
# BUILD_TARGET: StandaloneLinux64
# SCRIPTING_BACKEND: IL2CPP
#build-StandaloneOSX:
# <<: *build
# image: $IMAGE:$UNITY_VERSION-mac-mono-$IMAGE_VERSION
# variables:
# BUILD_TARGET: StandaloneOSX
#Note: build target names changed in recent versions, use this for versions < 2017.2:
# build-StandaloneOSXUniversal:
# <<: *build
# variables:
# BUILD_TARGET: StandaloneOSXUniversal
#build-StandaloneWindows64:
# <<: *build
# image: $IMAGE:$UNITY_VERSION-windows-mono-$IMAGE_VERSION
# variables:
# BUILD_TARGET: StandaloneWindows64
build-WebGL:
<<: *build
image: $IMAGE:$UNITY_VERSION-webgl-$IMAGE_VERSION
before_script:
- chmod +x ./ci/before_script.sh && ./ci/before_script.sh
- apt-get update && apt-get install ffmpeg -y
variables:
BUILD_TARGET: WebGL
build-android:
<<: *build
image: $IMAGE:$UNITY_VERSION-android-$IMAGE_VERSION
variables:
BUILD_TARGET: Android
BUILD_APP_BUNDLE: "false"
#build-android-il2cpp:
# <<: *build
# image: $IMAGE:$UNITY_VERSION-android-$IMAGE_VERSION
# variables:
# BUILD_TARGET: Android
# BUILD_APP_BUNDLE: "false"
# SCRIPTING_BACKEND: IL2CPP
#deploy-android:
# stage: deploy
# image: ruby
# script:
# - cd $UNITY_DIR/Builds/Android
# - echo $GPC_TOKEN > gpc_token.json
# - gem install bundler
# - bundle install
# - fastlane supply --aab "${BUILD_NAME}.aab" --track internal --package_name com.youcompany.yourgame --json_key ./gpc_token.json
# needs: ["build-android"]
#build-ios-xcode:
# <<: *build
# image: $IMAGE:$UNITY_VERSION-ios-$IMAGE_VERSION
# variables:
# BUILD_TARGET: iOS
#build-and-deploy-ios:
# stage: deploy
# script:
# - cd $UNITY_DIR/Builds/iOS/$BUILD_NAME
# - pod install
# - fastlane ios beta
# tags:
# - ios
# - mac
# needs: ["build-ios-xcode"]
pages:
image: alpine:latest
stage: deploy
script:
- mv "$UNITY_DIR/Builds/WebGL/${BUILD_NAME}" public
artifacts:
paths:
- public
only:
- main
workflow:
rules:
- if: $CI_MERGE_REQUEST_ID
when: never
- if: $CI_COMMIT_TAG
when: never
- when: always
- Build and Test
(1)Projects->CI/CD->Pipelines->Run Pipeline,执行Pipeline
(2)运行时或运行成功后,可以点击任务查看状态,执行成功后,可查看任务状态并点击右侧Download下载安装包或WebGL
三、Q&A
- 问题: ERROR: Job failed (system failure): prepare environment: failed to start process: exec: “pwsh”: executable file not found in %PATH%.
原因: pwsh 不是有效的 Windows 命令
解决: 转到Gitlab Runner安装目录找到config.toml文件,并用powershell替换pwsh(在注册runner时,会自动生成config.toml配置文件)
concurrent = 1
check_interval = 0
[session_server]
session_timeout = 1800
[[runners]]
name = "unity3d"
url = "https://git.n.xiaomi.com/"
token = "yDKTtGwAfmZxwcE2ekBe"
executor = "shell"
shell = "powershell"
[runners.custom_build_dir]
[runners.cache]
[runners.cache.s3]
[runners.cache.gcs]
[runners.cache.azure]
- 问题: ERROR: Job failed (system failure): prepare environment: pulling image “unityci/editor:2020.1.14f1c1-base-0.17”: image pull failed: Back-off pulling image “unityci/editor:2020.1.14f1c1-base-0.17”.
原因: Game CI并不支持Unity所有版本,但它支持绝大多数版本
解决:
(1)yml文件修改UNITY_VERSION属性为"2020.3.6f1"
(2)项目根目录下->ProjectSettings->ProjectVersion.txt修改Unity版本