文章目录

  • 一、基本概念介绍
  • 二、为你的Unity项目创建自动化构建
  • 三、Q&A


一、基本概念介绍
  1. 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 系统。

  1. GitLab CI/CD 整体流程
  • GitLab CI/CD 的 pipeline 具体流程和操作在 .gitlab-ci.yml 文件中申明。
  • 触发 pipeline 后,由 GitLab Runner 根据 .gitlab-ci.yml 文件运行。
  • 运行结束后将返回至 GitLab 系统。
  1. .gitlab-ci.yml 文件

.gitlab-ci.yml文件是一个申明式文件,文件中指定了CI的触发条件、工作内容、工作流程,编写和理解此文件是CI实战中最重要的一步,该文件指定的任务内容总体构成了1个pipeline、1个pipeline包含不同的stage执行阶段、每个stage包含不同的具体job脚本任务。

  1. Gitlab Runner
  1. GitLab Runner 是 CI 的执行环境,负责执行 gitlab-ci.yml 文件,并将结果返回给 GitLab 系统。
  2. Runner可以分为两种: Specific RunnerShared Runner
  • Shared Runner是Gitlab平台提供的免费使用的runner程序,它由Google云平台提供支持,每个开发团队有十几个。对于公共开源项目是免费使用的,如果是私人项目则有每月2000分钟的CI时间上限。
  • Specific Runner是我们自定义的,在自己选择的机器上运行的runner程序,gitlab给我们提供了一个叫gitlab-runner的命令行软件,只要在对应机器上下载安装这个软件,并且运行gitlab-runner register命令,然后输入从gitlab-ci交互界面获取的token进行注册, 就可以在自己的机器上远程运行pipeline程序了。
  1. Pipeline & stage & Job

Pipeline: 管道,每次commit或MR都会执行一次pipeline构建任务,包含多个阶段如测试、编译。
stage: 阶段,每个Pipeline有多个Stage,从上向下执行,前一个执行成功才能执行下一个
Job: 任务,CI/CD的最小运行单位,表示在指定Stage下执行的任务工作,可以有多个Job,并行执行。

二、为你的Unity项目创建自动化构建
  1. 如果你在GitLab上没有账户,请创建一个
  2. Gitlab设置
  3. 项目设置
    (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
  1. 参考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 Xcharts使用教程 unity ci_git


在此要特别说明一下,官方的示例中是没有"UNITY_VERSION"属性,它是通过执行get-unity-versionjob访问项目根目录ProjectSettings/ProjectVersion.txt获取Unity的版本,但是经测试,在CI Lint检查时报错get-unity-version在执行get-activation-filejob之前没有定义",因此我这里将get-unity-versionjob删除了,在属性中增加了UNITY_VERSION来设置Unity版本
  1. 提交新增文件到远程仓库

unity Xcharts使用教程 unity ci_git_02


gitlab在检测到yml文件后,自动创建pipeline


unity Xcharts使用教程 unity ci_git_03

  1. 激活
    (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值中
  2. 可用的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.

unity Xcharts使用教程 unity ci_unity_04


输入gitlab status查看状态,gitlab start启动runner,gitlab stop暂停Runner

注册成功后,回到Projects->Settings->CI/CD->Runner->Specific Runner,状态如下注册成功

unity Xcharts使用教程 unity ci_ci_05


8. shared runner

yml文件中,可以设置tags标签选择指定的Runner,若关闭tags属性,并Projects->Settings->CI/CD->Runner->Shared Runner没有禁用,任务执行时会自动选择可用的Shared Runner

unity Xcharts使用教程 unity ci_git_06


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
  1. Build and Test
    (1)Projects->CI/CD->Pipelines->Run Pipeline,执行Pipeline



    (2)运行时或运行成功后,可以点击任务查看状态,执行成功后,可查看任务状态并点击右侧Download下载安装包或WebGL
三、Q&A
  1. 问题: 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]
  1. 问题: 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版本