Jenkins - Sizuha/devdog GitHub Wiki

๊ณต์‹ ์‚ฌ์ดํŠธ

Installation

Plugins

ํ”Œ๋Ÿฌ๊ทธ์ธ ๋ฆฌ์ŠคํŠธ: https://wiki.jenkins-ci.org/display/JENKINS/Plugins

์‚ฌ์šฉ๊ฐ€๋Šฅํ•œ ํ”Œ๋Ÿฌ๊ทธ์ธ ํŽ˜์ด์ง€( http://localhost:8080/pluginManager/available )์—์„œ Plugin์„ ์ฐพ์•„์„œ ์ฒดํฌํ•˜๊ณ  ์„ค์น˜ ํ›„ ์  ํ‚จ์Šค๋ฅผ ๋ฆฌ์Šคํƒ€ํŠธ ํ•ด์ค€๋‹ค.

๋ฌธ์ œ ๋ฐ ํ•ด๊ฒฐ

http://localhost:8080 ์— ์ ‘์†์ด ๋˜์ง€ ์•Š๋Š”๋‹ค

์ตœ์‹  ๋ฒ„์ „ JDK๊ฐ€ ์„ค์น˜๋˜์–ด ์žˆ๋Š”์ง€ ํ™•์ธํ•ด ๋ณด๋ผ.

์ •ํ™•ํ•œ ์—๋Ÿฌ๋Š” ๋‹ค์Œ ๋กœ๊ทธ๋ฅผ ํ™•์ธ.

$ nano /var/log/jenkins/jenkins.log

๊ทธ๋ž˜๋„ ํ•ด๊ฒฐ์ด ์•ˆ๋œ๋‹ค๋ฉด, log ํŒŒ์ผ์˜ ๊ถŒํ•œ ๋ฌธ์ œ์ผ ์ˆ˜ ์žˆ๋‹ค.

๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ง„ํ–‰.

$ sudo chown jenkins /var/log/jenkins/jenkins.log
$ sudo nano /etc/newsyslog.d/jenkins.conf

/etc/newsyslog.d/jenkins.conf ํŒŒ์ผ ๋‚ด์šฉ์„ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋ฐ”๊พผ๋‹ค.

/var/log/jenkins/jenkins.log         644  3    *   $D0   J

to

/var/log/jenkins/jenkins.log   jenkins:jenkins    644  3    *   $D0   J

์ด๋Š” ๋‹ค์Œ์— ์ƒ์„ฑ๋˜๋Š” ๋กœ๊ทธํŒŒ์ผ๋“ค๋„ ๊ณ„์†ํ•ด์„œ jenkins ์œ ์ €๊ฐ€ ์†Œ์œ ์ž ๊ถŒํ•œ์„ ๊ฐ€์ง€๋„๋ก ํ•œ๋‹ค.

๊ด€๋ฆฌ

Restart

$ sudo launchctl unload /Library/LaunchDaemons/org.jenkins-ci.plist
$ sudo launchctl load /Library/LaunchDaemons/org.jenkins-ci.plist

SSH

๋นŒ๋“œ ํ”„๋กœ์„ธ์Šค์—์„œ ssh ์—ฐ๊ฒฐ์„ ์‚ฌ์šฉํ•˜๊ณ ์ž ํ•  ๋•Œ, Jenkins ๊ณ„์ •์— ssh ์„ค์ •์ด ํ•„์š”ํ•˜๋‹ค.

$ sudo su - Jenkins
$ mkdir .ssh
$ cd ~/.ssh
$ sudo nano config

Jenkins ๊ณ„์ •์˜ ํ™ˆ ๋””๋ ‰ํ† ๋ฆฌ ๊ฒฝ๋กœ: */Users/Shared/Jenkins/ (macOS)

Unity3D Build

์„ค์น˜ํ•ด์•ผ๋  ํ”Œ๋Ÿฌ๊ทธ์ธ

  • Git ๋“ฑ์˜ ๋ฒ„์ „๊ด€๋ฆฌ ํ”Œ๋Ÿฌ๊ทธ์ธ
    • Git์˜ ๊ฒฝ์šฐ: Git Client, Git Server, Git Parameter
  • Unity3d Build plugin
  • Xcode integration (iOS ๋นŒ๋“œ์šฉ)

Build Settings

Job์— Unity3dBuilder ํ”Œ๋Ÿฌ๊ทธ์ธ์„ ์ถ”๊ฐ€ํ•˜๊ณ , Invoke Unity3d Editor ํ•ญ๋ชฉ์˜ Editor command line arguments์— ๋‹ค์Œ๊ณผ ๊ฐ™์€ ํ˜•์‹์œผ๋กœ ์ถ”๊ฐ€.

-quit -batchMode -executeMethod ProjectBuilder.PerformAndroidBuild

๋นŒ๋“œ ์‹œ์ ์—์„œ DEFINE ์‹ฌ๋ณผ์„ ์„ค์ •ํ•˜๊ณ ์ž ํ•  ๋•Œ๋Š”,

static void Pattern1 {
    PlayerSettings.SetScriptingDefineSymbolsForGroup (BuildTargetGroup.Android, "TEST1;TEST2");
}

static void Pattern2 {
    PlayerSettings.SetScriptingDefineSymbolsForGroup (BuildTargetGroup.Android, "TEST3;TEST4");
}

Unity์—์„œ์˜ ์ž‘์—…

Unityํ”„๋กœ์ ํŠธ์˜ Assets/Editor/ ๊ฒฝ๋กœ์— ๋‹ค์Œ ๋‚ด์šฉ์œผ๋กœ ProjectBuilder.cs ํŒŒ์ผ์„ ์ƒ์„ฑ.

using UnityEngine;
using UnityEditor;
using System;
using System.Collections;
using System.Collections.Generic;
 
 
class ProjectBuilder {
	static string[] SCENES = FindEnabledEditorScenes();
	static string APP_NAME = "YourProject";
	static string TARGET_DIR = "build"; // !! ์ค‘์š”: Standalone ๋นŒ๋“œ ๋“ฑ์˜ ๊ฒฝ์šฐ์—, ํƒ€๊ฒŸ ๊ฒฝ๋กœ๋ฅผ ์ง€์ •ํ•ด ์ฃผ์ง€ ์•Š์œผ๋ฉด ๋นŒ๋“œ์— ์‹คํŒจํ•œ๋‹ค.
 
	[MenuItem ("Custom/CI/Build Android")]
	static void PerformAndroidBuild () {
		string target_filename = TARGET_DIR + "/" + APP_NAME + ".apk";
		GenericBuild(SCENES, target_filename, BuildTarget.Android ,BuildOptions.None);
	}
 
	private static string[] FindEnabledEditorScenes() {
		List<string> EditorScenes = new List<string>();
		foreach(EditorBuildSettingsScene scene in EditorBuildSettings.scenes) {
			if (!scene.enabled) continue;
			EditorScenes.Add(scene.path);
		}
		return EditorScenes.ToArray();
	}
 
	static void GenericBuild(string[] scenes, string target_filename, BuildTarget build_target, BuildOptions build_options) {
		EditorUserBuildSettings.SwitchActiveBuildTarget(build_target);
		string res = BuildPipeline.BuildPlayer(scenes, target_filename, build_target, build_options);
		if (res.Length > 0) {
			throw new Exception("BuildPlayer failure: " + res);
		}
	}
}

๊ฐ ํ”Œ๋žซํผ ๋นŒ๋“œ ์ˆ˜ํ–‰์šฉ Static Method์—๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์†์„ฑ ๋ถ€์—ฌ. (์ด๊ฒƒ์€ ์œ ๋‹ˆํ‹ฐ์˜ ๋ฉ”์ธ๋ฉ”๋‰ด์— ํ•ญ๋ชฉ์„ ํ‘œ์‹œํ•˜๊ธฐ ์œ„ํ•จ.)

[MenuItem ("Custom/CI/Build Android")]
[MenuItem ("Custom/CI/Build IOS")]
[MenuItem ("Custom/CI/Build Mac OS X")]
[MenuItem ("Custom/CI/Build Win32")]

Android Build

์ฃผ์˜ํ•  ์ ์€ keystore์˜ password๋ฅผ ์ง€์ •ํ•ด ์ค˜์•ผ ํ•œ๋‹ค๋Š” ๊ฒƒ.

	[MenuItem ("Custom/CI/Build Android")]
	static void PerformAndroidBuild() {
		string target_filename = APP_NAME + "_" + PlayerSettings.bundleVersion.Replace(".", "_") + ".apk";

		PlayerSettings.Android.keystorePass = "password";
		PlayerSettings.Android.keyaliasPass = "password";

		GenericBuild(FindEnabledEditorScenes(), target_filename, BuildTarget.Android ,BuildOptions.None);
	}

์–ด์…‹์„ ๋ถ„ํ•  ํ•ด์„œ apk + obb ํ˜•์‹์œผ๋กœ ๋นŒ๋“œํ•˜๊ณ ์ž ํ•  ๊ฒฝ์šฐ,

PlayerSettings.Android.useAPKExpansionFiles = true;

๋ฌธ์ œ ๋ฐ ํ•ด๊ฒฐ

์œ ๋‹ˆํ‹ฐ ๋นŒ๋“œ ๋„์ค‘์— WindowsServer์— ์ ‘์†ํ•˜์ง€ ๋ชปํ•œ๋‹ค๋Š” ์˜ค๋ฅ˜๊ฐ€ ๋œฌ๋‹ค. ์ด๋Š” LaunchDeamon ๊ถŒํ•œ์œผ๋กœ Jenkins๊ฐ€ ์‹คํ–‰๋˜๊ธฐ ๋•Œ๋ฌธ.

Jenkins Slave Agent๋ฅผ ์ด์šฉํ•ด์„œ ํ•ด๊ฒฐ

  1. ๋…ธ๋“œ ๊ด€๋ฆฌ์ž์—์„œ Unity ๋นŒ๋“œ์šฉ ๋…ธ๋“œ๋ฅผ ์ƒˆ๋กœ ์ถ”๊ฐ€.
  2. Remote FS Root ๊ฒฝ๋กœ ์„ค์ •: /Users/{user}/Jenkins/slave
  3. JNLP๋ฅผ ๊ฒฝ์œ ํ•ด์„œ ์‹คํ–‰ ์˜ต์…˜ ์„ ํƒ
  4. Job ์„ค์ •์—์„œ ์‹คํ–‰ํ•  ๋…ธ๋“œ ์ œํ•œ(ๅฎŸ่กŒใ™ใ‚‹ใƒŽใƒผใƒ‰ใ‚’ๅˆถ้™) ํ•ญ๋ชฉ์—์„œ ์œ„์—์„œ ์„ค์ •ํ•œ ๋…ธ๋“œ ์ด๋ฆ„์„ ๋„ฃ์Œ.
โš ๏ธ **GitHub.com Fallback** โš ๏ธ