Post List

[JENKINS] 로컬 MAC 머신에 Unity CI/CD 구축하기


이번에 사이드 프로젝트를 하며, 관심이 있었던 CI/CD 환경을 구축해 볼 수 있는 기회를 가지게 되었다.

지금까지 알기로, CI/CD 환경에 필요한 기능은 아래와 같다.

  • 웹 훅을 이용하여, 슬랙 같은 메신저에 빌드 유발/ 성공/ 실패 등의 메시지 푸시
  • git이나 소스 커밋시, 설정된 빌드 자동 유발
  • 빌드 스크립트를 숨기고, GUI를 통해 빌드 생성
앞으로 위 기능들을 추가해 볼 예정이다.

우선, 로컬 머신에 젠킨스 설치를 해보았다.
관련하여 찾은 문서는 https://shkim0811.tistory.com/20 블로그에 잘 설명 되어 있는데, 사이드 프로젝트의 개발 환경과 약간 다른점이 있다.
이번 프로젝트의 환경은 PC 플랫폼을 타겟으로 하며, 버전 관리 툴은 Plastic SCM을 쓰고, 협업도구로 discord를 사용한다.

Plugin manager에서 설치한 플러그인은 아래와 같다:
  • Unity 3D
  • Discord Notifier
  • Plastic SCM
  • post build task
추가로 조사해 보았을 때, Plastic SCM은 새로운 커밋(checkin)이 있을 때 감지해서 빌드를 trigger하는 기능은 없어 보였다. 그래서, 시간마다 주기적으로 빌드를 유발하고, 이 때 저장소의 최신 버전을 받고, 빌드 진행 후에 빌드 결과를 저장소에 다시 checkin하도록 하는 방안으로 가닥을 잡았다. 
이런 기능만 필요하다면, 따로 로컬호스트로 띄워져 있는 젠킨스를 외부 IP에서 접근할 수 있도록 공개하는 것은 필요하지 않았다.

시간마다 주기적으로 빌드 유발

간단히 젠킨스 구성 > 빌드 유발 > Build periodically 항목에서 시간을 설정해주면 된다.

저장소의 최신 버전 받기

빌드 시점에 저장소의 최신 버전을 받기 위해서는, 젠킨스에게 어떤 Plastic SCM 의 cloud repository, branch는 어떤것인지 알려주어야 한다.
공식 문서 를 확인해 보면, 아래와 같은 명령어로 확인할 수 있다.
(현재 plastic scm이 연결된 프로젝트 디렉토리로 이동 후 터미널에서: )

cm ss

이 명령어를 입력해주면, 아래 로그를 얻을 수 있다.


이제 이 로그를 복사해서, 젠킨스 구성 > 소스코드 관리 > Plastic SCM 에 넣어주면 빌드 시작시 자동으로 최신 저장소 버전으로 업데이트 된다 
물론 이 과정이 수행되려면 plastic scm 저장소에 접근할 수 있는 id/pw가 필요한데, 젠킨스 구성 > 소스코드 관리 > Plastic SCM > Credentials 에서 간단히 지정해줄 수 있다.
 

Unity cli 빌드

젠킨스는 기본적으로 .jenkins라는 숨겨져 있는 디렉토리에 관련 설정이 저장된다.
이전에 저장소의 최신 소스로 .jenkins/젠킨스 프로젝트 경로의 파일들이 업데이트 되었을 것이다.
이번 프로젝트의 빌드 타겟은 windows exe실행 파일로, 아래와 같이 간단하게 구성이 가능하다.
젠킨스 구성 > Build > invoke Unity3d Editor 이동
Unity3d installation name 에는 자신의 프로젝트에서 사용하는 유니티 버전을, (ex 2021.2.8.f1)
Editor command line arguments 에는 아래와 같은 명령어를 입력해주었다. 이 명령어는 공식 문서에 다양한 종류가 설명되어 있다. (https://docs.unity3d.com/Manual/EditorCommandLineArguments.html)

-quit -batchmode -logFile "$WORKSPACE/JenkinsBuild.log" -projectPath "/Users/.jenkins/유니티 프로젝트 위치" -executeMethod JenkinsBuildScript.Build_Win64

여기서, executeMethod 옵션에는 JenkinsBuildScript 라는 것을 주었는데, 이는 자신의 프로젝트에 필요로 하는, 직접 작성한 빌드 스크립트를 의미한다. 이 파일은 /유니티 프로젝트 위치/Editor/ 경로 하위에 위치해야 한다.
예를들면, 현재 프로젝트의 JenkinsBuildScript.cs 구성은 아래와 같다.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
using UnityEditor;
using UnityEngine;
using UnityEditor.Build.Reporting;
using System;
using System.IO;

public class JenkinsBuildScript : MonoBehaviour
{
    public static void Build_Win64()
    {
        string currentDate = string.Format("{0:yyyy}_{0:MM}_{0:dd}_{0:HH}_{0:mm}_{0:ss}", System.DateTime.Now);
        string buildPath = string.Format("../builds/temp/{0}/", currentDate);
        string exeFileName = currentDate += ".exe";

        BuildPlayerOptions buildPlayerOptions = new BuildPlayerOptions();
        buildPlayerOptions.scenes = new[] {
            "Assets/Scenes/Enter.unity",
            "Assets/Scenes/Lobby.unity",
            "Assets/Scenes/Login.unity",
            "Assets/Scenes/Module.unity",
            "Assets/Scenes/Stage/Forest.unity"
            };
        buildPlayerOptions.locationPathName = buildPath + exeFileName;
        buildPlayerOptions.target = BuildTarget.StandaloneWindows64;
        buildPlayerOptions.options = BuildOptions.None;

        BuildReport report = BuildPipeline.BuildPlayer(buildPlayerOptions);
        BuildSummary summary = report.summary;

        if (summary.result == BuildResult.Succeeded)
        {
            Debug.Log("Build succeeded: " + summary.totalSize + " bytes");
        }

        if (summary.result == BuildResult.Failed)
        {
            Debug.Log("Build failed");
        }
    }
}

이번 프로젝트에서는, 위 cs파일에서도 볼 수 있듯 빌드 실행 시점의 시각을 폴더 이름으로 구성했고, 이 폴더를 빌드가 완료되면 Plastic SCM에 체크인해줘야 한다.
이를 위해 postBuild.sh라는 쉘 스크립트를 직접 작성해주었고, Jenkins 에 post build task라는 플러그인을 설치해 주었다.
post build task에서 아래 쉘 파일을 실행하도록 해주었다.

#!/bin/bash

echo "[postbuild] Copy build outputs from temp dir to Builds dir" 

# Used for jenkins
cd /Users/.jenkins/workspace/BuildUnityProject/builds

cd temp

# current build output 
dirs=(*)
echo "[postbuild] Current build output dir name: ${dirs[0]}"

echo "[postbuild] Copying build output to builds dir..."
cp -r ${dirs[0]} ../
cd ..

echo "[postbuild] Start checkin build output process to main branch"
echo "[postbuild] Add local build dir under the source control..."
echo ${dirs[0]}
/usr/local/bin/cm add ${dirs[0]}/*
echo "[postbuild] checkin build dir..."
/usr/local/bin/cm ci ${dirs[0]}/* -c "[JENKINS] Build output submit, ${dirs[0]}"
echo "[postbuild] Finished checkin"

echo "[postbuild] remove temp dir"
rm -r temp

echo "[postbuild] Everything is ok..."


빌드 완료 후 discord 에 노티 주기

post build task에 Discord notifier 를 추가해준다.
그 후 원하는 디스코드 채널의 웹 훅 url를 https://discordbot.tistory.com/35 문서 참고해서 얻어내고, 등록만 해주면 된다.


결과

아래 이미지와 같이, 시간이 되면 빌드가 실행되며, 완료시 Plastic SCM에 빌드 결과 서밋, discord에 알림이 정상 실행되는것을 볼 수 있다.



댓글