├── .gitignore
├── Editor.meta
├── Editor
├── AssetBundleBrowser.meta
├── AssetBundleBrowser
│ ├── AssetBundleBrowserWrapper.cs
│ ├── AssetBundleBrowserWrapper.cs.meta
│ ├── AssetBundleBuilder.cs
│ └── AssetBundleBuilder.cs.meta
├── BuildConfig.cs
├── BuildConfig.cs.meta
├── JenkinsBuilder.cs
├── JenkinsBuilder.cs.meta
├── JenkinsBuilderWindow.cs
├── JenkinsBuilderWindow.cs.meta
├── JenkinsBuilder_Android.cs
├── JenkinsBuilder_Android.cs.meta
├── JenkinsBuilder_IOS.cs
├── JenkinsBuilder_IOS.cs.meta
├── KorStrix.JenkinsBuilder.Editor.asmdef
└── KorStrix.JenkinsBuilder.Editor.asmdef.meta
├── GithubImage.meta
├── GithubImage
├── Jenkins_BuildConfig.png
├── Jenkins_BuildConfig.png.meta
├── Jenkins_BuildConfig_Android.png
├── Jenkins_BuildConfig_Android.png.meta
├── Jenkins_BuildConfig_iOS.png
├── Jenkins_BuildConfig_iOS.png.meta
├── Jenkins_EditorWindow.png
└── Jenkins_EditorWindow.png.meta
├── IOS_Shell.meta
├── IOS_Shell
├── ios_export_ipa.sh
├── ios_export_ipa.sh.meta
├── ipa_send_appstore.sh
└── ipa_send_appstore.sh.meta
├── LICENSE
├── LICENSE.meta
├── README.md
├── README.md.meta
├── Shell.meta
├── Shell
├── UploadFTP.sh
├── UploadFTP.sh.meta
├── VersionHandler.sh
└── VersionHandler.sh.meta
├── package.json
└── package.json.meta
/.gitignore:
--------------------------------------------------------------------------------
1 | # This .gitignore file should be placed at the root of your Unity project directory
2 | #
3 | # Get latest from https://github.com/github/gitignore/blob/master/Unity.gitignore
4 | #
5 | /[Ll]ibrary/
6 | /[Tt]emp/
7 | /[Oo]bj/
8 | /[Bb]uild/
9 | /[Bb]uilds/
10 | /[Ll]ogs/
11 | /[Mm]emoryCaptures/
12 |
13 | # Asset meta data should only be ignored when the corresponding asset is also ignored
14 | !/[Aa]ssets/**/*.meta
15 |
16 | # Uncomment this line if you wish to ignore the asset store tools plugin
17 | # /[Aa]ssets/AssetStoreTools*
18 |
19 | # Autogenerated Jetbrains Rider plugin
20 | [Aa]ssets/Plugins/Editor/JetBrains*
21 |
22 | # Visual Studio cache directory
23 | .vs/
24 |
25 | # Gradle cache directory
26 | .gradle/
27 |
28 | # Autogenerated VS/MD/Consulo solution and project files
29 | ExportedObj/
30 | .consulo/
31 | *.csproj
32 | *.unityproj
33 | *.sln
34 | *.suo
35 | *.tmp
36 | *.user
37 | *.userprefs
38 | *.pidb
39 | *.booproj
40 | *.svd
41 | *.pdb
42 | *.mdb
43 | *.opendb
44 | *.VC.db
45 |
46 | # Unity3D generated meta files
47 | *.pidb.meta
48 | *.pdb.meta
49 | *.mdb.meta
50 |
51 | # Unity3D generated file on crash reports
52 | sysinfo.txt
53 |
54 | # Builds
55 | *.apk
56 | *.unitypackage
57 |
58 | # Crashlytics generated file
59 | crashlytics-build.properties
60 |
61 | .UnityProject/Library/
62 | .UnityProject/Temp/
63 |
--------------------------------------------------------------------------------
/Editor.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 82c4633b1244f764bb2ec85d819cadd1
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Editor/AssetBundleBrowser.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: f3ff2370f04644c43ad192da5b08deb7
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Editor/AssetBundleBrowser/AssetBundleBrowserWrapper.cs:
--------------------------------------------------------------------------------
1 | #region Header
2 | /* ============================================
3 | * Author : Strix
4 | * Initial Creation Date : 2020-04-10
5 | * Summary :
6 | * Template : For Unity Editor V1
7 | ============================================ */
8 | #endregion Header
9 |
10 | using UnityEngine;
11 | using System.Reflection;
12 | using UnityEditor;
13 |
14 | #if ASSET_BUNDLE_BROWSER
15 | using AssetBundleBrowser;
16 | #endif
17 |
18 |
19 | ///
20 | ///
21 | ///
22 | public class AssetBundleBrowserWrapper
23 | {
24 | /* const & readonly declaration */
25 |
26 | /* enum & struct declaration */
27 |
28 | /* public - Field declaration */
29 |
30 |
31 | /* protected & private - Field declaration */
32 |
33 | #if ASSET_BUNDLE_BROWSER
34 | AssetBundleBrowserMain _pBrowser;
35 | #endif
36 |
37 | System.Type _pBrowserType;
38 |
39 | FieldInfo _pField_BuildTab;
40 | FieldInfo _pField_BuildTab_UserData;
41 | FieldInfo _pField_BuildTab_UserData_BuildTarget;
42 |
43 | private object _pInstance_BuildTab;
44 | private object _pInstance_UserData;
45 |
46 | MethodInfo _pMethod_Build;
47 |
48 | // ========================================================================== //
49 |
50 | /* public - [Do~Something] Function */
51 |
52 | public AssetBundleBrowserWrapper()
53 | {
54 | #if ASSET_BUNDLE_BROWSER
55 | _pBrowser = AssetBundleBrowserMain.GetWindow();
56 | _pBrowserType = _pBrowser.GetType();
57 |
58 | _pField_BuildTab = _pBrowserType.GetField("m_BuildTab", BindingFlags.NonPublic | BindingFlags.Instance);
59 | _pInstance_BuildTab = _pField_BuildTab.GetValue(_pBrowser);
60 |
61 | _pField_BuildTab_UserData = _pField_BuildTab.FieldType.GetField("m_UserData", BindingFlags.NonPublic | BindingFlags.Instance);
62 | _pInstance_UserData = _pField_BuildTab_UserData.GetValue(_pInstance_BuildTab);
63 |
64 | _pField_BuildTab_UserData_BuildTarget = _pField_BuildTab_UserData.FieldType.GetField("m_BuildTarget", BindingFlags.NonPublic | BindingFlags.Instance);
65 |
66 | _pMethod_Build = _pField_BuildTab.FieldType.GetMethod("ExecuteBuild", BindingFlags.NonPublic | BindingFlags.Instance);
67 | #endif
68 | }
69 |
70 | public void DoBuildBundle(BuildTarget eBuildTarget)
71 | {
72 | _pField_BuildTab_UserData_BuildTarget.SetValue(_pInstance_UserData, (int)eBuildTarget);
73 |
74 | UnityEngine.Debug.Log($"!@#$ Start Build Bundle \n" +
75 | $"Current Platform : {Application.platform} Target : {_pField_BuildTab_UserData_BuildTarget.GetValue(_pInstance_UserData)} \n" +
76 | $"Symbol : {PlayerSettings.GetScriptingDefineSymbolsForGroup(EditorUserBuildSettings.selectedBuildTargetGroup)} \n");
77 |
78 | #if ASSET_BUNDLE_BROWSER
79 | _pMethod_Build?.Invoke(_pField_BuildTab.GetValue(_pBrowser), null);
80 | _pBrowser.Close();
81 | #else
82 | UnityEngine.Debug.Log("!@#$ Use Define Symbol ASSET_BUNDLE_BROWSER");
83 | #endif
84 | UnityEngine.Debug.Log("!@#$ Finish Build");
85 | }
86 |
87 | // ========================================================================== //
88 |
89 | /* protected - [Override & Unity API] */
90 |
91 |
92 | /* protected - [abstract & virtual] */
93 |
94 |
95 | // ========================================================================== //
96 |
97 | #region Private
98 |
99 | #endregion Private
100 | }
101 |
--------------------------------------------------------------------------------
/Editor/AssetBundleBrowser/AssetBundleBrowserWrapper.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 477ed728cf2cdf847acde74422cfbac1
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Editor/AssetBundleBrowser/AssetBundleBuilder.cs:
--------------------------------------------------------------------------------
1 | #region Header
2 | /* ============================================
3 | * Author : Strix
4 | * Initial Creation Date : 2020-04-10
5 | * Summary :
6 | * Template : For Unity Editor V1
7 | ============================================ */
8 | #endregion Header
9 |
10 |
11 | using UnityEditor;
12 |
13 | namespace Jenkins
14 | {
15 | ///
16 | ///
17 | ///
18 | public class AssetBundleBuilder
19 | {
20 | /* const & readonly declaration */
21 |
22 | const string const_strPrefix_ForDebugLog = "!@#$";
23 |
24 | /* enum & struct declaration */
25 |
26 | /* public - Field declaration */
27 |
28 |
29 | /* protected & private - Field declaration */
30 |
31 |
32 | // ========================================================================== //
33 |
34 | /* public - [Do~Something] Function */
35 |
36 |
37 | [MenuItem("Tools/Build/BundleBuild Test - Android", priority = 10000)]
38 | public static void Build_Android()
39 | {
40 | AssetBundleBrowserWrapper pWrapper = new AssetBundleBrowserWrapper();
41 | pWrapper.DoBuildBundle(BuildTarget.Android);
42 | }
43 |
44 |
45 | [MenuItem("Tools/Build/BundleBuild Test - IOS", priority = 10000)]
46 | public static void Build_IOS()
47 | {
48 | AssetBundleBrowserWrapper pWrapper = new AssetBundleBrowserWrapper();
49 | pWrapper.DoBuildBundle(BuildTarget.iOS);
50 | }
51 |
52 | // ========================================================================== //
53 |
54 | /* protected - [Override & Unity API] */
55 |
56 |
57 | /* protected - [abstract & virtual] */
58 |
59 |
60 | // ========================================================================== //
61 |
62 | #region Private
63 |
64 | #endregion Private
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/Editor/AssetBundleBrowser/AssetBundleBuilder.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: b60429b7bf2e9f74cbb4a7438c29bb18
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Editor/BuildConfig.cs:
--------------------------------------------------------------------------------
1 | #region Header
2 | /* ============================================
3 | * Author : Require PlayerPref Key : "Author"
4 | * Initial Creation Date : 2020-05-08
5 | * Summary :
6 | * Template : New Behaviour For Unity Editor V2
7 | ============================================ */
8 | #endregion Header
9 |
10 | using System;
11 | using UnityEngine;
12 | using UnityEditor;
13 |
14 | namespace Jenkins
15 | {
16 | [Serializable]
17 | public partial class BuildConfig : ScriptableObject
18 | {
19 | ///
20 | /// 출력할 파일 명, 젠킨스에서 -filename (filename:string) 로 설정가능
21 | ///
22 | public string strFileName = "Build";
23 |
24 | public string strDefineSymbol;
25 |
26 | ///
27 | /// 설치한 디바이스에 표기될 이름
28 | ///
29 | public string strProductName;
30 |
31 | ///
32 | /// 빌드에 포함할 씬들, 확장자는 안쓰셔도 됩니다.
33 | /// 예시) ["Assets/SomethingScene_1", "Assets/SomethingScene_1"]
34 | ///
35 | public string[] arrBuildSceneNames;
36 |
37 |
38 | // 출력할 폴더 및 파일은 Jenkins에서 처리할 예정이였으나,
39 | // IL2CPP의 경우 같은 장소에 빌드해놓으면 더 빠르다는 메뉴얼로 인해 일단 보류
40 | // https://docs.unity3d.com/kr/2020.2/Manual/IL2CPP-OptimizingBuildTimes.html
41 | public string strAbsolute_BuildOutputFolderPath;
42 |
43 | ///
44 | /// 빌드파일 끝에 DateTime을 붙일지
45 | ///
46 | public bool bUse_DateTime_Suffix;
47 |
48 | ///
49 | ///
50 | /// ScriptableObject.CreateInstance
51 | ///
52 | /// Wrapper
53 | /// ScriptableObject 생성시 생성자에 PlayerSettings에서 Get할경우 Unity Exception이 남
54 | ///
55 | public static BuildConfig CreateConfig()
56 | {
57 | BuildConfig pConfig = ScriptableObject.CreateInstance();
58 |
59 | pConfig.strProductName = PlayerSettings.productName;
60 | pConfig.arrBuildSceneNames = Builder.GetEnabled_EditorScenes();
61 |
62 | pConfig.strAbsolute_BuildOutputFolderPath = Application.dataPath.Replace("/Assets", "") + "/Build";
63 | pConfig.bUse_DateTime_Suffix = true;
64 |
65 | pConfig.pAndroidSetting = AndroidSetting.CreateSetting();
66 | pConfig.pIOSSetting = IOSSetting.CreateSetting();
67 |
68 | return pConfig;
69 | }
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/Editor/BuildConfig.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 83dc1534323151445a0f8c8be8326bb1
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Editor/JenkinsBuilder.cs:
--------------------------------------------------------------------------------
1 | #region Header
2 |
3 | /* ============================================
4 | * 작성자 : Strix
5 | * 작성일 : 2019-10-21 오후 6:42:02
6 | * 개요 :
7 | *
8 | * 에디터 폴더에 있어야 정상 동작합니다.
9 | *
10 | * 참고한 원본 코드 링크
11 | * https://slway000.tistory.com/74
12 | * https://smilejsu.tistory.com/1528
13 | ============================================ */
14 |
15 | #endregion Header
16 |
17 | using UnityEngine;
18 | using System;
19 | using System.IO;
20 | using System.Linq;
21 |
22 | #if UNITY_EDITOR
23 | using System.Collections.Generic;
24 | using UnityEditor;
25 | using UnityEditor.Build.Reporting;
26 |
27 | namespace Jenkins
28 | {
29 | ///
30 | /// 에디터 플레이어 빌드 전 세팅 (빌드 후 되돌리기용)
31 | ///
32 | public class PlayerSetting_Backup
33 | {
34 | public string strDefineSymbol { get; private set; }
35 | public string strProductName { get; private set; }
36 |
37 | public BuildTargetGroup eBuildTargetGroup { get; private set; }
38 |
39 | public PlayerSetting_Backup(BuildTargetGroup eBuildTargetGroup, string strDefineSymbol, string strProductName)
40 | {
41 | this.eBuildTargetGroup = eBuildTargetGroup;
42 | this.strDefineSymbol = strDefineSymbol;
43 | this.strProductName = strProductName;
44 | }
45 |
46 | public void Back_To_Origin()
47 | {
48 | PlayerSettings.SetScriptingDefineSymbolsForGroup(eBuildTargetGroup, strDefineSymbol);
49 | PlayerSettings.productName = strProductName;
50 | }
51 | }
52 |
53 | ///
54 | /// 젠킨스 빌드를 위한 스크립트입니다.
55 | ///
56 | public partial class Builder
57 | {
58 | public const string const_strPrefix_EditorContextMenu = "Tools/Strix/Jenkins Build/";
59 | const string const_strPrefix_ForDebugLog = "!@#$";
60 |
61 | public enum ECommandLineList
62 | {
63 | ///
64 | /// 결과물이 나오는 파일 명
65 | ///
66 | filename,
67 |
68 | ///
69 | /// 컨피그 파일이 있는 절대 경로
70 | ///
71 | config_path,
72 |
73 | ///
74 | /// 결과물이 나오는 절대 경로
75 | ///
76 | output_path,
77 |
78 | ///
79 | /// PlayerSetting.android.BundleVersionCode
80 | ///
81 | android_bundle_versioncode,
82 |
83 | ///
84 | /// PlayerSetting.android.Version
85 | ///
86 | android_version,
87 |
88 | ///
89 | /// 스토어에 올라가는 빌드 번호
90 | ///
91 | ios_buildnumber,
92 |
93 | ///
94 | /// 스토어에 올라가는 버전
95 | ///
96 | ios_version,
97 | }
98 |
99 | static readonly IReadOnlyDictionary mapCommandLine =
100 | new Dictionary()
101 | {
102 | {ECommandLineList.filename, "-filename"},
103 | {ECommandLineList.config_path, "-config_path"},
104 | {ECommandLineList.output_path, "-output_path"},
105 | {ECommandLineList.android_bundle_versioncode, "-android_versioncode"},
106 | {ECommandLineList.android_version, "-android_version"},
107 | {ECommandLineList.ios_buildnumber, "-ios_buildnumber"},
108 | {ECommandLineList.ios_version, "-ios_version"}
109 | };
110 |
111 | public static string GetCommandLineString(ECommandLineList eCommandLine) => mapCommandLine[eCommandLine];
112 |
113 | private static BuildConfig g_pLastConfig;
114 |
115 |
116 | [MenuItem(const_strPrefix_EditorContextMenu + "Create BuildConfig Example Json File")]
117 | public static void Create_BuildConfig_Dummy_Json()
118 | {
119 | string strContent = JsonUtility.ToJson(BuildConfig.CreateConfig(), true);
120 | string strFilePath = nameof(BuildConfig) + "_Example.json";
121 | File.WriteAllText(Application.dataPath + "/" + strFilePath, strContent);
122 |
123 | AssetDatabase.Refresh();
124 |
125 | UnityEngine.Object pJsonFile = AssetDatabase.LoadMainAssetAtPath($"Assets/{strFilePath}");
126 |
127 | Selection.activeObject = pJsonFile;
128 | Debug.Log("Create BuildConfig Done", pJsonFile);
129 | }
130 |
131 | // SO는 아직 고려중
132 | //[MenuItem(const_strPrefix_EditorContextMenu + "Create BuildConfig Example SO File")]
133 | //public static void Create_BuildConfig_Dummy_SO()
134 | //{
135 | // BuildConfig pConfig = BuildConfig.CreateConfig();
136 | // AssetDatabase.CreateAsset(pConfig, $"Assets/{nameof(BuildConfig)} _Example.asset");
137 | // AssetDatabase.SaveAssets();
138 | // AssetDatabase.Refresh();
139 |
140 | // Selection.activeObject = pConfig;
141 | // Debug.Log("Create BuildConfig Done", pConfig);
142 | //}
143 |
144 | #region public
145 |
146 | public static string GetCommandLineArg(string strName)
147 | {
148 | string[] arrArgument = Environment.GetCommandLineArgs();
149 | for (int i = 0; i < arrArgument.Length; ++i)
150 | {
151 | if (arrArgument[i] == strName && arrArgument.Length > i + 1)
152 | {
153 | return arrArgument[i + 1];
154 | }
155 | }
156 |
157 | return null;
158 | }
159 |
160 | public static bool GetFile_From_CommandLine(string strCommandLine, out T pOutFile)
161 | where T : new()
162 | {
163 | string strPath = GetCommandLineArg(strCommandLine);
164 | Exception pException = DoTryParsing_JsonFile(strPath, out pOutFile);
165 | if (pException != null)
166 | {
167 | Debug.LogErrorFormat(const_strPrefix_ForDebugLog + " Error - FilePath : {0}, FilePath : {1}\n" +
168 | " Error : {2}", strCommandLine, strPath, pException);
169 | return false;
170 | }
171 |
172 | return true;
173 | }
174 |
175 | public static bool GetFile_From_CommandLine_SO(string strCommandLine, out T pOutFile)
176 | where T : ScriptableObject
177 | {
178 | string strPath = GetCommandLineArg(strCommandLine);
179 | Exception pException = DoTryParsing_JsonFile_SO(strPath, out pOutFile);
180 | if (pException != null)
181 | {
182 | Debug.LogErrorFormat(const_strPrefix_ForDebugLog + " Error - FilePath : {0}, FilePath : {1}\n" +
183 | " Error : {2}", strCommandLine, strPath, pException);
184 | return false;
185 | }
186 |
187 | return true;
188 | }
189 |
190 | public static void GetAppFilePath_FromConfig(BuildConfig pConfig, out string strBuildOutputFolderPath,
191 | out string strFileName)
192 | {
193 | string strBuildOutputFolderPath_CommandLine = GetCommandLineArg(mapCommandLine[ECommandLineList.output_path]);
194 | string strFileName_CommandLine = GetCommandLineArg(mapCommandLine[ECommandLineList.filename]);
195 |
196 | strBuildOutputFolderPath = string.IsNullOrEmpty(strBuildOutputFolderPath_CommandLine)
197 | ? pConfig.strAbsolute_BuildOutputFolderPath
198 | : strBuildOutputFolderPath_CommandLine;
199 |
200 | if (string.IsNullOrEmpty(strFileName_CommandLine))
201 | {
202 | strFileName = pConfig.strFileName;
203 | }
204 | else
205 | {
206 | strFileName = strFileName_CommandLine;
207 | pConfig.bUse_DateTime_Suffix = false;
208 | }
209 | }
210 |
211 |
212 | public static Exception DoTryParsing_JsonFile(string strJsonFilePath, out T pOutFile)
213 | where T : new()
214 | {
215 | pOutFile = default(T);
216 |
217 | try
218 | {
219 | string strConfigJson = File.ReadAllText(strJsonFilePath);
220 | pOutFile = JsonUtility.FromJson(strConfigJson);
221 | }
222 | catch (Exception pException)
223 | {
224 | return pException;
225 | }
226 |
227 | return null;
228 | }
229 |
230 | public static Exception DoTryParsing_JsonFile_SO(string strJsonFilePath, out T pOutFile)
231 | where T : ScriptableObject
232 | {
233 | pOutFile = ScriptableObject.CreateInstance();
234 |
235 | try
236 | {
237 | string strConfigJson = File.ReadAllText(strJsonFilePath);
238 | JsonUtility.FromJsonOverwrite(strConfigJson, pOutFile);
239 | }
240 | catch (Exception pException)
241 | {
242 | pOutFile = null;
243 | return pException;
244 | }
245 |
246 | return null;
247 | }
248 |
249 | public static string[] GetEnabled_EditorScenes()
250 | {
251 | return EditorBuildSettings.scenes.
252 | Where(p => p.enabled).
253 | Select(p => p.path.Replace(".unity", "")).
254 | ToArray();
255 | }
256 |
257 |
258 | public static void DoBuild(BuildConfig pBuildConfig, string strAbsolute_BuildOutputFolderPath,
259 | string strFileName, BuildTarget eBuildTarget)
260 | {
261 | g_pLastConfig = pBuildConfig;
262 |
263 | Process_PreBuild(pBuildConfig, strAbsolute_BuildOutputFolderPath, strFileName, eBuildTarget, out var eBuildTargetGroup, out var strBuildPath);
264 |
265 | BuildPlayerOptions sBuildPlayerOptions = Generate_BuildPlayerOption(pBuildConfig, eBuildTarget, strBuildPath);
266 | PlayerSetting_Backup pEditorSetting_Backup = SettingBuildConfig_To_EditorSetting(pBuildConfig, eBuildTargetGroup);
267 |
268 | Debug.LogFormat(const_strPrefix_ForDebugLog + " Before Build DefineSymbol TargetGroup : {0}\n" +
269 | "Origin Symbol : {1}\n " +
270 | "Config : {2} \n" +
271 | "Current : {3} \n" +
272 | "strBuildPath : {4}",
273 | eBuildTargetGroup,
274 | pEditorSetting_Backup.strDefineSymbol,
275 | pBuildConfig.strDefineSymbol,
276 | PlayerSettings.GetScriptingDefineSymbolsForGroup(eBuildTargetGroup),
277 | strBuildPath);
278 |
279 | try
280 | {
281 | BuildReport pReport = BuildPipeline.BuildPlayer(sBuildPlayerOptions);
282 | PrintBuildResult(strBuildPath, pReport, pReport.summary);
283 | }
284 | catch (Exception e)
285 | {
286 | Debug.Log(const_strPrefix_ForDebugLog + " Error - " + e);
287 | throw;
288 | }
289 |
290 | pEditorSetting_Backup.Back_To_Origin();
291 | Process_PostBuild(eBuildTarget, strAbsolute_BuildOutputFolderPath);
292 |
293 | Debug.LogFormat(const_strPrefix_ForDebugLog + " After Build DefineSymbol Current {0}",
294 | PlayerSettings.GetScriptingDefineSymbolsForGroup(eBuildTargetGroup));
295 |
296 | // 2018.4 에서 프로젝트 전체 리임포팅 하는 이슈 대응
297 | // https://issuetracker.unity3d.com/issues/osx-batchmode-build-hangs-at-refresh-detecting-if-any-assets-need-to-be-imported-or-removed
298 | #if UNITY_EDITOR
299 | AssetDatabase.Refresh();
300 | #endif
301 | }
302 |
303 | ///
304 | /// Android를 빌드합니다. CommandLine - ConfigPath 필요
305 | /// Command Line으로 실행할 때 partial class file에 있으면 못찾음..
306 | ///
307 | public static void Build_Android()
308 | {
309 | if (GetFile_From_CommandLine_SO(mapCommandLine[ECommandLineList.config_path], out BuildConfig pConfig))
310 | {
311 | GetAppFilePath_FromConfig(pConfig, out string strBuildOutputFolderPath, out string strFileName);
312 | DoBuild(pConfig, strBuildOutputFolderPath, strFileName, BuildTarget.Android);
313 | }
314 | }
315 |
316 | ///
317 | /// IOS를 빌드합니다. CommandLine - ConfigPath 필요
318 | /// Command Line으로 실행할 때 partial class file에 있으면 못찾음..
319 | ///
320 | public static void Build_IOS()
321 | {
322 | if (GetFile_From_CommandLine_SO(mapCommandLine[ECommandLineList.config_path], out BuildConfig pConfig))
323 | {
324 | GetAppFilePath_FromConfig(pConfig, out string strBuildOutputFolderPath, out string strFileName);
325 | DoBuild(pConfig, strBuildOutputFolderPath, strFileName, BuildTarget.iOS);
326 | }
327 | }
328 |
329 | #endregion public
330 |
331 | // ==============================================================================================
332 |
333 |
334 | #region private
335 | private static BuildPlayerOptions Generate_BuildPlayerOption(BuildConfig pBuildConfig, BuildTarget eBuildTarget,
336 | string strBuildPath)
337 | {
338 | BuildPlayerOptions sBuildPlayerOptions = new BuildPlayerOptions
339 | {
340 | scenes = pBuildConfig.arrBuildSceneNames.Select(p => p += ".unity").ToArray(),
341 | locationPathName = strBuildPath,
342 | target = eBuildTarget,
343 | options = BuildOptions.None
344 | };
345 |
346 | return sBuildPlayerOptions;
347 | }
348 |
349 |
350 | private static PlayerSetting_Backup SettingBuildConfig_To_EditorSetting(BuildConfig pBuildConfig,
351 | BuildTargetGroup eBuildTargetGroup)
352 | {
353 | string strDefineSymbol_Backup = PlayerSettings.GetScriptingDefineSymbolsForGroup(eBuildTargetGroup);
354 | PlayerSettings.SetScriptingDefineSymbolsForGroup(eBuildTargetGroup, pBuildConfig.strDefineSymbol);
355 |
356 | string strProductName_Backup = PlayerSettings.productName;
357 | PlayerSettings.productName = pBuildConfig.strProductName;
358 |
359 | return new PlayerSetting_Backup(eBuildTargetGroup, strDefineSymbol_Backup, strProductName_Backup);
360 | }
361 |
362 | private static void Process_PreBuild(BuildConfig pBuildConfig, string strAbsolute_BuildOutputFolderPath,
363 | string strFileName, BuildTarget eBuildTarget, out BuildTargetGroup eBuildTargetGroup,
364 | out string strBuildPath)
365 | {
366 | eBuildTargetGroup = GetBuildTargetGroup(eBuildTarget);
367 | strBuildPath = Create_BuildPath(pBuildConfig.bUse_DateTime_Suffix, strAbsolute_BuildOutputFolderPath,
368 | strFileName);
369 |
370 | switch (eBuildTarget)
371 | {
372 | case BuildTarget.Android:
373 | BuildSetting_Android(pBuildConfig.pAndroidSetting);
374 | strBuildPath += ".apk";
375 | break;
376 |
377 | case BuildTarget.iOS:
378 | BuildSetting_IOS(pBuildConfig.pIOSSetting);
379 | break;
380 | }
381 | }
382 |
383 | private static string Create_BuildPath(bool bUse_DateTime_Suffix, string strFolderName, string strFileName)
384 | {
385 | Debug.LogFormat(const_strPrefix_ForDebugLog + " FolderName : {0}, FileName : {1}", strFolderName,
386 | strFileName);
387 |
388 | try
389 | {
390 | if (Directory.Exists(strFolderName) == false)
391 | Directory.CreateDirectory(strFolderName);
392 | }
393 | catch (Exception e)
394 | {
395 | Debug.Log(const_strPrefix_ForDebugLog + " Error - Create Directory - " + e);
396 | }
397 |
398 | string strBuildPath = strFolderName + "/" + strFileName;
399 | if (bUse_DateTime_Suffix)
400 | {
401 | string strDateTime = DateTime.Now.ToString("MMdd_HHmm");
402 | strBuildPath = strBuildPath + "_" + strDateTime;
403 | }
404 |
405 | return strBuildPath;
406 | }
407 |
408 |
409 | private static void Process_PostBuild(BuildTarget eBuildTarget,
410 | string strAbsolute_BuildOutputFolderPath)
411 | {
412 | switch (eBuildTarget)
413 | {
414 | case BuildTarget.Android:
415 |
416 | try
417 | {
418 | // Mac OS에서 구동 시 Directory.GetFiles함수는 Error가 나기 때문에
419 | // DirectoryInfo.GetFiles를 통해 체크
420 | DirectoryInfo pDirectory = new DirectoryInfo(strAbsolute_BuildOutputFolderPath);
421 | foreach (var pFile in pDirectory.GetFiles())
422 | {
423 | // IL2CPP 파일로 빌드 시 자동으로 생inf기는 파일, 삭제해도 무방
424 | if (pFile.Extension == ".zip" && pFile.Name.Contains("symbols"))
425 | {
426 | Debug.Log(const_strPrefix_ForDebugLog + " Delete : " + pFile.Name);
427 | pFile.Delete();
428 | }
429 | }
430 | }
431 | catch (Exception e)
432 | {
433 | Debug.Log(const_strPrefix_ForDebugLog + " Error - " + e);
434 | }
435 |
436 | break;
437 | }
438 | }
439 |
440 |
441 | private static void PrintBuildResult(string strPath, BuildReport pReport, BuildSummary pSummary)
442 | {
443 | Debug.LogFormat(const_strPrefix_ForDebugLog + " Path : {0}, Build Result : {1}", strPath, pSummary.result);
444 |
445 | if (pSummary.result == BuildResult.Succeeded)
446 | {
447 | Debug.Log(const_strPrefix_ForDebugLog + " Build Succeeded!");
448 | }
449 | else if (pSummary.result == BuildResult.Failed)
450 | {
451 | int iErrorIndex = 1;
452 | foreach (var pStep in pReport.steps)
453 | {
454 | foreach (var pMessage in pStep.messages)
455 | {
456 | if (pMessage.type == LogType.Error || pMessage.type == LogType.Exception)
457 | {
458 | Debug.LogFormat(const_strPrefix_ForDebugLog + " Build Fail Log[{0}] : type : {1}\n" +
459 | " content : {2}", ++iErrorIndex, pMessage.type, pMessage.content);
460 | }
461 | }
462 | }
463 | }
464 | }
465 |
466 | private static BuildTargetGroup GetBuildTargetGroup(BuildTarget eBuildTarget)
467 | {
468 | switch (eBuildTarget)
469 | {
470 | case BuildTarget.Android: return BuildTargetGroup.Android;
471 | case BuildTarget.iOS: return BuildTargetGroup.iOS;
472 | }
473 |
474 | return BuildTargetGroup.Standalone;
475 | }
476 |
477 | #endregion private
478 | }
479 | }
480 |
481 | #endif
482 |
--------------------------------------------------------------------------------
/Editor/JenkinsBuilder.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 524e7afbd5eb4070a54244e149dc5149
3 | timeCreated: 1588752966
--------------------------------------------------------------------------------
/Editor/JenkinsBuilderWindow.cs:
--------------------------------------------------------------------------------
1 | #region Header
2 |
3 | /* ============================================
4 | * 작성자 : Strix
5 | * 작성일 : 2019-10-21 오후 6:42:02
6 | * 개요 :
7 | *
8 | * 에디터 폴더에 있어야 정상 동작합니다.
9 | *
10 | * 참고한 원본 코드 링크
11 | * https://slway000.tistory.com/74
12 | * https://smilejsu.tistory.com/1528
13 | ============================================ */
14 |
15 | #endregion Header
16 |
17 | using UnityEngine;
18 | using System;
19 | using System.IO;
20 | using System.Linq;
21 | using UnityEditor.Callbacks;
22 |
23 | #if UNITY_EDITOR
24 | using UnityEditor;
25 |
26 | namespace Jenkins
27 | {
28 | ///
29 | /// 젠킨스 빌더를 유니티 에디터에서 제어하하는 스크립트입니다.
30 | ///
31 | public class JenkinsBuilderWindow : EditorWindow
32 | {
33 | BuildConfig _pBuildConfig;
34 |
35 | string _strConfigPath;
36 | string _strBuildPath;
37 |
38 | [MenuItem(Builder.const_strPrefix_EditorContextMenu + "Show Builder Window", priority = -10000)]
39 | public static void DoShow_Jenkins_Builder_Window()
40 | {
41 | JenkinsBuilderWindow pWindow = (JenkinsBuilderWindow) GetWindow(typeof(JenkinsBuilderWindow), false);
42 |
43 | pWindow.minSize = new Vector2(600, 200);
44 | pWindow.Show();
45 | }
46 |
47 | private void OnEnable()
48 | {
49 | _strConfigPath = EditorPrefs.GetString($"{nameof(JenkinsBuilderWindow)}_{nameof(_strConfigPath)}");
50 | _strBuildPath = EditorPrefs.GetString($"{nameof(JenkinsBuilderWindow)}_{nameof(_strBuildPath)}");
51 |
52 | CheckConfigPath();
53 | }
54 |
55 | private void OnGUI()
56 | {
57 | GUILayout.Space(10f);
58 |
59 | EditorGUILayout.HelpBox("이 툴은 BuildConfig를 통해 빌드하는 툴입니다.\n\n" +
60 | "사용방법\n" +
61 | "1. Edit Config Json File을 클릭하여 세팅합니다.\n" +
62 | "2. Edit Build Output Path를 눌러 빌드파일 출력 경로를 세팅합니다.\n" +
63 | "3. 플랫폼(Android or iOS) 빌드를 누릅니다.\n" +
64 | "4. 빌드가 되는지 확인 후, 빌드가 완료되면 Open BuildFolder를 눌러 빌드 파일을 확인합니다."
65 | ,MessageType.Info);
66 |
67 |
68 | if (GUILayout.Button("Github"))
69 | {
70 | System.Diagnostics.Process.Start("https://github.com/KorStrix/Unity_JenkinsBuilder");
71 | }
72 | GUILayout.Space(30f);
73 |
74 |
75 | EditorGUI.BeginChangeCheck();
76 | DrawPath_File("Config Json File", ref _strConfigPath,
77 | (strPath) => EditorPrefs.SetString($"{nameof(JenkinsBuilderWindow)}_{nameof(_strConfigPath)}", strPath));
78 | if (EditorGUI.EndChangeCheck())
79 | {
80 | CheckConfigPath();
81 | }
82 |
83 | DrawPath_Folder("Build", ref _strBuildPath,
84 | (strPath) => EditorPrefs.SetString($"{nameof(JenkinsBuilderWindow)}_{nameof(_strBuildPath)}", strPath));
85 | GUILayout.Space(10f);
86 |
87 | bool bConfigIsNotNull = _pBuildConfig != null;
88 |
89 | GUI.enabled = bConfigIsNotNull;
90 | GUILayout.BeginHorizontal();
91 | {
92 | if (GUILayout.Button("Android Build !", GUILayout.Height(40f)))
93 | {
94 | Builder.DoBuild(_pBuildConfig, _strBuildPath, _pBuildConfig.strFileName, BuildTarget.Android);
95 | }
96 |
97 | if (GUILayout.Button("iOS Build !", GUILayout.Height(40f)))
98 | {
99 | Builder.DoBuild(_pBuildConfig, _strBuildPath, _pBuildConfig.strFileName, BuildTarget.iOS);
100 | }
101 | }
102 | GUILayout.EndHorizontal();
103 | GUI.enabled = true;
104 |
105 | if (GUILayout.Button("Open BuildFolder Path !"))
106 | {
107 | System.Diagnostics.Process.Start(_strBuildPath);
108 | }
109 | }
110 |
111 | private string DrawPath_Folder(string strExplainName, ref string strFolderPath, Action OnChangePath)
112 | {
113 | return DrawPath(strExplainName, ref strFolderPath, OnChangePath, true);
114 | }
115 |
116 | private string DrawPath_File(string strExplainName, ref string strFilePath, Action OnChangePath)
117 | {
118 | return DrawPath(strExplainName, ref strFilePath, OnChangePath, false);
119 | }
120 |
121 | private string DrawPath(string strExplainName, ref string strEditPath, Action OnChangePath, bool bIsFolder)
122 | {
123 | GUILayout.BeginHorizontal();
124 |
125 | if (bIsFolder)
126 | GUILayout.Label($"{strExplainName} Path : ", GUILayout.Width(150f));
127 | else
128 | GUILayout.Label($"{strExplainName} Path : ", GUILayout.Width(150f));
129 |
130 | GUI.enabled = false;
131 | GUILayout.TextArea(strEditPath, GUILayout.ExpandWidth(true), GUILayout.Height(40f));
132 | GUI.enabled = true;
133 |
134 | if (GUILayout.Button($"Edit {strExplainName}", GUILayout.Width(150f)))
135 | {
136 | string strPath = "";
137 | if (bIsFolder)
138 | strPath = EditorUtility.OpenFolderPanel("Root Folder", "", "");
139 | else
140 | strPath = EditorUtility.OpenFilePanel("File Path", "", "");
141 |
142 | strEditPath = strPath;
143 | OnChangePath?.Invoke(strPath);
144 | }
145 |
146 | GUILayout.EndHorizontal();
147 |
148 | return strEditPath;
149 | }
150 |
151 | private void CheckConfigPath()
152 | {
153 | if (string.IsNullOrEmpty(_strConfigPath))
154 | return;
155 |
156 | Exception pException = Builder.DoTryParsing_JsonFile_SO(_strConfigPath, out _pBuildConfig);
157 | if (pException != null)
158 | {
159 | _strConfigPath = "!! Error !!" + _strConfigPath;
160 | Debug.LogError($"Json Parsing Fail Path : {_strConfigPath}\n {pException}", this);
161 | }
162 | }
163 |
164 | }
165 | }
166 |
167 | #endif
--------------------------------------------------------------------------------
/Editor/JenkinsBuilderWindow.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 62ce867b31e61764a84f95b91b51a7d8
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Editor/JenkinsBuilder_Android.cs:
--------------------------------------------------------------------------------
1 | #region Header
2 |
3 | /* ============================================
4 | * 작성자 : Strix
5 | * 작성일 : 2019-10-21 오후 6:42:02
6 | * 개요 :
7 | *
8 | * 에디터 폴더에 있어야 정상 동작합니다.
9 | *
10 | * 참고한 원본 코드 링크
11 | * https://slway000.tistory.com/74
12 | * https://smilejsu.tistory.com/1528
13 | ============================================ */
14 |
15 | #endregion Header
16 |
17 | using UnityEngine;
18 | using System;
19 |
20 | #if UNITY_EDITOR
21 | using UnityEditor;
22 |
23 | namespace Jenkins
24 | {
25 | public partial class BuildConfig
26 | {
27 | [Serializable]
28 | public class AndroidSetting
29 | {
30 | ///
31 | /// 예시) com.CompanyName.ProductName
32 | ///
33 | public string strFullPackageName;
34 |
35 | public string strKeyalias_Name;
36 | public string strKeyalias_Password;
37 |
38 | ///
39 | /// Keystore 파일의 경로입니다. `파일경로/파일명.keystore` 까지 쓰셔야 합니다.
40 | /// UnityProject/Asset/ 기준의 상대 경로입니다.
41 | /// 예를들어 UnityProject/Asset 폴더 밑에 example.keystore를 넣으셨으면 "/example.keystore" 입니다.
42 | ///
43 | public string strKeystore_RelativePath;
44 | public string strKeystore_Password;
45 |
46 | ///
47 | /// CPP 빌드를 할지 체크, CPP빌드는 오래 걸리므로 Test빌드가 아닌 Alpha 빌드부터 하는걸 권장
48 | /// 아직 미지원
49 | ///
50 | public bool bUse_IL_TO_CPP_Build;
51 |
52 | public int iBundleVersionCode;
53 |
54 | public string strVersion;
55 |
56 |
57 | ///
58 | /// ScriptableObject 생성시 생성자에 PlayerSettings에서 Get할경우 Unity Exception이 남
59 | ///
60 | ///
61 | public static AndroidSetting CreateSetting()
62 | {
63 | AndroidSetting pNewSetting = new AndroidSetting();
64 |
65 | pNewSetting.strFullPackageName = PlayerSettings.applicationIdentifier;
66 | pNewSetting.iBundleVersionCode = PlayerSettings.Android.bundleVersionCode;
67 | pNewSetting.strVersion = PlayerSettings.bundleVersion;
68 |
69 | return pNewSetting;
70 | }
71 | }
72 |
73 | public AndroidSetting pAndroidSetting;
74 | }
75 |
76 | public partial class Builder
77 | {
78 | [MenuItem(const_strPrefix_EditorContextMenu + "Build Test - Android")]
79 | public static void Build_Test_Android()
80 | {
81 | BuildConfig pConfig = BuildConfig.CreateConfig();
82 | BuildTargetGroup eBuildTargetGroup = GetBuildTargetGroup(BuildTarget.Android);
83 | pConfig.strDefineSymbol = PlayerSettings.GetScriptingDefineSymbolsForGroup(eBuildTargetGroup);
84 |
85 | DoBuild(pConfig, pConfig.strAbsolute_BuildOutputFolderPath, pConfig.strFileName, BuildTarget.Android);
86 | }
87 |
88 | // ==============================================================================================
89 |
90 |
91 | ///
92 | /// 안드로이드 세팅
93 | ///
94 | private static void BuildSetting_Android(BuildConfig.AndroidSetting pSetting)
95 | {
96 | if (string.IsNullOrEmpty(pSetting.strFullPackageName) == false)
97 | PlayerSettings.applicationIdentifier = pSetting.strFullPackageName;
98 |
99 | PlayerSettings.Android.keyaliasName = pSetting.strKeyalias_Name;
100 | PlayerSettings.Android.keyaliasPass = pSetting.strKeyalias_Password;
101 |
102 | PlayerSettings.Android.keystoreName = Application.dataPath + pSetting.strKeystore_RelativePath;
103 | PlayerSettings.Android.keystorePass = pSetting.strKeystore_Password;
104 |
105 | string strBundleVersionCode_FromCommandLine = GetCommandLineArg(mapCommandLine[ECommandLineList.android_bundle_versioncode]);
106 | if(int.TryParse(strBundleVersionCode_FromCommandLine, out int iBundleVersionCode))
107 | PlayerSettings.Android.bundleVersionCode = iBundleVersionCode;
108 | else
109 | PlayerSettings.Android.bundleVersionCode = pSetting.iBundleVersionCode;
110 |
111 | string strVersionCode_FromCommandLine = GetCommandLineArg(mapCommandLine[ECommandLineList.android_version]);
112 | if (string.IsNullOrEmpty(strVersionCode_FromCommandLine) == false)
113 | PlayerSettings.bundleVersion = strVersionCode_FromCommandLine;
114 | else
115 | PlayerSettings.bundleVersion = pSetting.strVersion;
116 |
117 | // if (pAndroidSetting.bUse_IL_TO_CPP_Build)
118 | // PlayerSettings.SetScriptingBackend(BuildTargetGroup.Android, ScriptingImplementation.IL2CPP);
119 | // else
120 | // PlayerSettings.SetScriptingBackend(BuildTargetGroup.Android, ScriptingImplementation.Mono2x);
121 |
122 | Debug.LogFormat(const_strPrefix_ForDebugLog + " Build Setting [Android]\n" +
123 | "strPackageName : {0}\n" +
124 | "keyaliasName : {1}, keyaliasPass : {2}\n" +
125 | "keystoreName : {3}, keystorePass : {4}\n" +
126 | "bUse_IL_TO_CPP_Build : {5}",
127 | PlayerSettings.applicationIdentifier,
128 | PlayerSettings.Android.keyaliasName, PlayerSettings.Android.keyaliasPass,
129 | PlayerSettings.Android.keystoreName, PlayerSettings.Android.keystorePass,
130 | pSetting.bUse_IL_TO_CPP_Build);
131 | ;
132 | }
133 | }
134 | }
135 |
136 | #endif
137 |
--------------------------------------------------------------------------------
/Editor/JenkinsBuilder_Android.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: cba2fab4324b48a1879d081f12cfd2ff
3 | timeCreated: 1588752631
--------------------------------------------------------------------------------
/Editor/JenkinsBuilder_IOS.cs:
--------------------------------------------------------------------------------
1 | #region Header
2 |
3 | /* ============================================
4 | * 작성자 : Strix
5 | * 작성일 : 2019-10-21 오후 6:42:02
6 | * 개요 :
7 | *
8 | * 에디터 폴더에 있어야 정상 동작합니다.
9 | *
10 | * 참고한 원본 코드 링크
11 | * https://slway000.tistory.com/74
12 | * https://smilejsu.tistory.com/1528
13 | ============================================ */
14 |
15 | #endregion Header
16 |
17 | // #define UNITY_IOS // IOS Code Compile Test
18 |
19 | using UnityEngine;
20 | using System;
21 |
22 | #if UNITY_EDITOR
23 | using UnityEditor;
24 | using UnityEditor.Callbacks;
25 |
26 |
27 |
28 | #if UNITY_IOS
29 | using System.Collections.Generic;
30 | using System.IO;
31 | using UnityEditor.iOS.Xcode;
32 | #endif
33 |
34 | namespace Jenkins
35 | {
36 | public partial class BuildConfig
37 | {
38 | ///
39 | /// 유니티 -> XCode Export -> XCode ArchiveBuildConfig -> .ipa 에 필요한 모든 설정
40 | ///
41 | [Serializable]
42 | public class IOSSetting
43 | {
44 | ///
45 | /// 애플 개발자 사이트에서 조회 가능, 숫자랑 영어로 된거
46 | ///
47 | public string strAppleTeamID;
48 |
49 | ///
50 | /// Apple에서 세팅된 net.Company.Product 형식의 string
51 | ///
52 | public string strBundle_Identifier;
53 | public string strEntitlementsFileName_Without_ExtensionName;
54 |
55 | ///
56 | /// 유니티 Asset 경로에서 XCode Project로 카피할 파일 목록, 확장자까지 작성해야 합니다
57 | /// UnityProject/Assets/ 기준
58 | ///
59 | public string[] arrCopy_AssetFilePath_To_XCodeProjectPath;
60 |
61 | ///
62 | /// XCode 프로젝트에 추가할 Framework, 확장자까지 작성해야 합니다
63 | ///
64 | public string[] arrXCode_Framework_Add;
65 |
66 | ///
67 | /// XCode 프로젝트에 제거할 Framework, 확장자까지 작성해야 합니다
68 | ///
69 | public string[] arrXCode_Framework_Remove;
70 |
71 | public string[] arrXCode_OTHER_LDFLAGS_Add;
72 | public string[] arrXCode_OTHER_LDFLAGS_Remove;
73 |
74 | ///
75 | /// HTTP 주소 IOS는 기본적으로 HTTP를 허용 안하기 때문에 예외에 추가해야 합니다. http://는 제외할것
76 | /// 예시) http://www.naver.com = www.naver.com
77 | ///
78 | public string[] arrHTTPAddress;
79 |
80 | ///
81 | /// 출시할 빌드 버전
82 | /// 이미 앱스토어에 올렸으면 그 다음 항상 숫자를 올려야 합니다. 안그럼 앱스토어에서 안받음
83 | ///
84 | public string strBuildVersion;
85 |
86 | ///
87 | /// 빌드 번호
88 | /// 이미 앱스토어에 올렸으면 그 다음 항상 1씩 올려야 합니다. 안그럼 앱스토어에서 안받음
89 | ///
90 | public string strBuildNumber;
91 |
92 | [Serializable]
93 | public class PLIST_ADD
94 | {
95 | public string strKey;
96 | public string strValue;
97 |
98 | public PLIST_ADD(string strKey, string strValue)
99 | {
100 | this.strKey = strKey;
101 | this.strValue = strValue;
102 | }
103 | }
104 |
105 | public PLIST_ADD[] arrAddPlist = new PLIST_ADD[] {new PLIST_ADD("ExampleKey", "ExampleValue")};
106 | public string[] arrRemovePlistKey = new string[] { "ExampleKey", "ExampleValue" };
107 |
108 | ///
109 | /// ScriptableObject 생성시 생성자에 PlayerSettings에서 Get할경우 Unity Exception이 남
110 | ///
111 | ///
112 | public static IOSSetting CreateSetting()
113 | {
114 | IOSSetting pNewSetting = new IOSSetting();
115 |
116 | return pNewSetting;
117 | }
118 | }
119 |
120 | public IOSSetting pIOSSetting;
121 | }
122 |
123 | public partial class Builder
124 | {
125 | public const int const_iPostBuildCallbackOrder = 777;
126 |
127 | [MenuItem(const_strPrefix_EditorContextMenu + "Build Test - IOS")]
128 | // ReSharper disable once UnusedMember.Global
129 | public static void Build_Test_IOS()
130 | {
131 | BuildConfig pConfig = new BuildConfig();
132 | BuildTargetGroup eBuildTargetGroup = GetBuildTargetGroup(BuildTarget.iOS);
133 | pConfig.strDefineSymbol = PlayerSettings.GetScriptingDefineSymbolsForGroup(eBuildTargetGroup);
134 |
135 | DoBuild(pConfig, pConfig.strAbsolute_BuildOutputFolderPath, pConfig.strFileName, BuildTarget.iOS);
136 | }
137 |
138 | [PostProcessBuild(const_iPostBuildCallbackOrder)]
139 | public static void OnPostProcessBuild(BuildTarget eBuildTarget, string strPath)
140 | {
141 | Debug.Log($"{const_strPrefix_ForDebugLog} {nameof(OnPostProcessBuild)} - BuildTarget : {eBuildTarget} strPath : {strPath}");
142 | if (eBuildTarget != BuildTarget.iOS)
143 | return;
144 |
145 | Init_XCodeProject(strPath);
146 | Setup_XCodePlist(strPath);
147 | }
148 |
149 | // ==============================================================================================
150 |
151 | ///
152 | /// IOS용 XCode Initialize
153 | ///
154 | // ReSharper disable once UnusedParameter.Local
155 | private static void Init_XCodeProject(string strXCodeProjectPath)
156 | {
157 | #if UNITY_IOS
158 | BuildConfig.IOSSetting pIOSSetting = g_pLastConfig.pIOSSetting;
159 | var projectPath = strXCodeProjectPath + "/Unity-iPhone.xcodeproj/project.pbxproj";
160 |
161 | Debug.Log($"{const_strPrefix_ForDebugLog} {nameof(Init_XCodeProject)} Start - {nameof(strXCodeProjectPath)} : {strXCodeProjectPath}\n" +
162 | $"projectPath : {projectPath}");
163 |
164 | PBXProject pPBXProject = new PBXProject();
165 | pPBXProject.ReadFromFile(projectPath);
166 |
167 | string strTargetGuid = pPBXProject.TargetGuidByName("Unity-iPhone");
168 |
169 |
170 | // Set Apple Team ID
171 | pPBXProject.SetTeamId(strTargetGuid, pIOSSetting.strAppleTeamID);
172 |
173 | // Copy File Asset To XCode Project
174 | foreach(var strFilePath in pIOSSetting.arrCopy_AssetFilePath_To_XCodeProjectPath)
175 | CopyFile_Asset_To_XCode(strXCodeProjectPath, strFilePath);
176 |
177 |
178 | // Add XCode Framework
179 | foreach (string strFramework in pIOSSetting.arrXCode_Framework_Add)
180 | {
181 | pPBXProject.AddFrameworkToProject(strTargetGuid, strFramework, false);
182 | Debug.Log($"{const_strPrefix_ForDebugLog} Add Framework \"{strFramework}\" to XCode Project");
183 | }
184 |
185 |
186 | // Remove XCode Framework
187 | foreach (string strFramework in pIOSSetting.arrXCode_Framework_Remove)
188 | {
189 | pPBXProject.RemoveFrameworkFromProject(strTargetGuid, strFramework);
190 | Debug.Log($"{const_strPrefix_ForDebugLog} Remove Framework \"{strFramework}\" to XCode Project");
191 | }
192 |
193 |
194 | // Set XCode OTHER_LDFLAGS
195 | pPBXProject.UpdateBuildProperty(strTargetGuid, "OTHER_LDFLAGS", pIOSSetting.arrXCode_OTHER_LDFLAGS_Add, pIOSSetting.arrXCode_OTHER_LDFLAGS_Remove);
196 |
197 | #region Sample
198 | // // Sample of setting build property
199 | // project.SetBuildProperty(targetGuid, "ENABLE_BITCODE", "NO");
200 |
201 | // Sample of setting compile flags
202 | // var guid = pbxProject.FindFileGuidByProjectPath("Classes/UI/Keyboard.mm");
203 | // var flags = pbxProject.GetCompileFlagsForFile(targetGuid, guid);
204 | // flags.Add("-fno-objc-arc");
205 | // pbxProject.SetCompileFlagsForFile(targetGuid, guid, flags);
206 | #endregion Sample
207 |
208 | string strTargetEntitlementsFilePath = strXCodeProjectPath + "/" + pIOSSetting.strEntitlementsFileName_Without_ExtensionName + ".entitlements";
209 | pPBXProject.AddCapability(strTargetGuid, PBXCapabilityType.PushNotifications, strTargetEntitlementsFilePath, true);
210 | pPBXProject.AddCapability(strTargetGuid, PBXCapabilityType.InAppPurchase, null, true);
211 | pPBXProject.AddCapability(strTargetGuid, PBXCapabilityType.GameCenter, null, true);
212 |
213 | pPBXProject.AddBuildProperty(strTargetGuid, "FRAMEWORK_SEARCH_PATHS", "$(PROJECT_DIR)");
214 |
215 | SetIOS_AuthToken(pPBXProject, strTargetGuid);
216 |
217 | // Apply settings
218 | File.WriteAllText(projectPath, pPBXProject.WriteToString());
219 | #else
220 | Debug.Log($"{const_strPrefix_ForDebugLog} {nameof(Init_XCodeProject)} - Define Symbol is Not IOS");
221 | #endif
222 | }
223 |
224 | #if UNITY_IOS
225 | private static void SetIOS_AuthToken(PBXProject project, string strTargetGuid)
226 | {
227 | var token = project.GetBuildPropertyForAnyConfig(strTargetGuid, "USYM_UPLOAD_AUTH_TOKEN");
228 | if (string.IsNullOrEmpty(token))
229 | {
230 | token = "FakeToken";
231 | }
232 |
233 | project.SetBuildProperty(strTargetGuid, "USYM_UPLOAD_AUTH_TOKEN", token);
234 | }
235 | #endif
236 |
237 | private static void CopyFile_Asset_To_XCode(string strXCodeProjectPath, string strFilePath)
238 | {
239 | string strFileName = strFilePath;
240 | int iLastIndex = strFilePath.LastIndexOf("/");
241 | if(iLastIndex != -1)
242 | strFileName = strFilePath.Substring(iLastIndex + 1);
243 |
244 | string strFilePath_Origin = Application.dataPath + "/" + strFilePath;
245 | string strFilePath_Dest = strXCodeProjectPath + "/" + strFileName;
246 |
247 | try
248 | {
249 | FileUtil.DeleteFileOrDirectory(strFilePath_Dest);
250 | FileUtil.CopyFileOrDirectory(strFilePath_Origin, strFilePath_Dest);
251 | }
252 | catch (Exception e)
253 | {
254 | Debug.Log($"{const_strPrefix_ForDebugLog} Copy File Error FileName : \"{strFileName}\" // \"{strFilePath_Origin}\" to \"{strFilePath_Dest}\"" + e);
255 | }
256 |
257 | Debug.Log($"{const_strPrefix_ForDebugLog} Copy File FileName : \"{strFileName}\" // \"{strFilePath_Origin}\" to \"{strFilePath_Dest}\"");
258 | }
259 |
260 | // ReSharper disable once UnusedParameter.Local
261 | private static void Setup_XCodePlist(string strXCodeProjectPath)
262 | {
263 | #if UNITY_IOS
264 | Debug.Log($"{const_strPrefix_ForDebugLog} {nameof(Setup_XCodePlist)} Start - {nameof(strXCodeProjectPath)} : {strXCodeProjectPath}");
265 | BuildConfig.IOSSetting pIOSSetting = g_pLastConfig.pIOSSetting;
266 |
267 | // Property List(.plist) Default Name
268 | const string strInfoPlistName = "Info.plist";
269 |
270 | var str_plistPath = Path.Combine(strXCodeProjectPath, strInfoPlistName);
271 | var p_plistDocument = new PlistDocument();
272 | p_plistDocument.ReadFromFile(str_plistPath);
273 |
274 |
275 |
276 | // 해당 키는 IOS 업로드 시 해당 키는 지원하지 않는다는 에러 발생으로 인해 제거
277 | const string strExitsOnSuspendKey = "UIApplicationExitsOnSuspend";
278 | var arrRootValues = p_plistDocument.root.values;
279 | if(arrRootValues.ContainsKey(strExitsOnSuspendKey))
280 | arrRootValues.Remove(strExitsOnSuspendKey);
281 |
282 | foreach (var pProperty in pIOSSetting.arrAddPlist)
283 | {
284 | Debug.Log($"{const_strPrefix_ForDebugLog} Add Property - Key : \"{pProperty.strKey}\" Value : {pProperty.strValue}");
285 |
286 | if (arrRootValues.ContainsKey(pProperty.strKey))
287 | arrRootValues[pProperty.strKey] = new PlistElementString(pProperty.strValue);
288 | else
289 | arrRootValues.Add(pProperty.strKey, new PlistElementString(pProperty.strValue));
290 | }
291 |
292 | foreach (string strRemovePropertyKey in pIOSSetting.arrRemovePlistKey)
293 | {
294 | if (arrRootValues.ContainsKey(strRemovePropertyKey))
295 | {
296 | arrRootValues.Remove(strRemovePropertyKey);
297 | Debug.Log($"{const_strPrefix_ForDebugLog} Contains & Removed Key.Length : {strRemovePropertyKey}");
298 | }
299 | }
300 |
301 | Debug.Log($"{const_strPrefix_ForDebugLog} pIOSSetting.arrHTTPAddress.Length : \"{pIOSSetting.arrHTTPAddress.Length}\"");
302 |
303 | // HTTP 주소는 Plist에 추가해야 접근 가능..
304 | if (pIOSSetting.arrHTTPAddress.Length != 0)
305 | {
306 | PlistElementDict pTransportDict = Get_Or_Add_PlistDict(arrRootValues, "NSAppTransportSecurity");
307 | PlistElementDict pExceptionDomainsDict = Get_Or_Add_PlistDict(pTransportDict.values, "NSExceptionDomains");
308 |
309 | foreach (string strAddress in pIOSSetting.arrHTTPAddress)
310 | {
311 | Debug.Log($"{const_strPrefix_ForDebugLog} Add HTTPAddress : \"{strAddress}\"");
312 |
313 | PlistElementDict pTransportDomain = Get_Or_Add_PlistDict(pExceptionDomainsDict.values, strAddress);
314 | const string strNSAllowInsecureHTTPLoadsKey = "NSExceptionAllowsInsecureHTTPLoads";
315 | const string strNSIncludesSubdomains = "NSIncludesSubdomains";
316 |
317 |
318 | if (pTransportDomain.values.ContainsKey(strNSAllowInsecureHTTPLoadsKey) == false)
319 | pTransportDomain.values.Add(strNSAllowInsecureHTTPLoadsKey, new PlistElementBoolean(true));
320 |
321 | if (pTransportDomain.values.ContainsKey(strNSIncludesSubdomains) == false)
322 | pTransportDomain.values.Add(strNSIncludesSubdomains, new PlistElementBoolean(true));
323 | }
324 | }
325 |
326 | // Apply editing settings to Info.plist
327 | p_plistDocument.WriteToFile(str_plistPath);
328 | Debug.Log($"{const_strPrefix_ForDebugLog} {nameof(Setup_XCodePlist)} - WriteToFile {str_plistPath}");
329 | #else
330 | Debug.Log($"{const_strPrefix_ForDebugLog} {nameof(Setup_XCodePlist)} - Not Define Symbol is Not IOS");
331 | #endif
332 | }
333 |
334 | #if UNITY_IOS
335 | private static PlistElementDict Get_Or_Add_PlistDict(IDictionary arrRootValues, string strKey)
336 | {
337 | if (arrRootValues.ContainsKey(strKey) == false)
338 | arrRootValues.Add(strKey, new PlistElementDict());
339 |
340 | return arrRootValues[strKey].AsDict();
341 | }
342 | #endif
343 |
344 | private static void BuildSetting_IOS(BuildConfig.IOSSetting pSetting)
345 | {
346 | if (string.IsNullOrEmpty(pSetting.strBundle_Identifier) == false)
347 | PlayerSettings.applicationIdentifier = pSetting.strBundle_Identifier;
348 |
349 | string strVersion_FromCommandLine = GetCommandLineArg(mapCommandLine[ECommandLineList.ios_version]);
350 | if (string.IsNullOrEmpty(strVersion_FromCommandLine) == false)
351 | PlayerSettings.bundleVersion = strVersion_FromCommandLine;
352 | else if(string.IsNullOrEmpty(pSetting.strBuildVersion) == false)
353 | PlayerSettings.bundleVersion = pSetting.strBuildVersion;
354 |
355 |
356 | string strBuildNumber_FromCommandLine = GetCommandLineArg(mapCommandLine[ECommandLineList.ios_buildnumber]);
357 | if(string.IsNullOrEmpty(strBuildNumber_FromCommandLine) == false)
358 | PlayerSettings.iOS.buildNumber = strBuildNumber_FromCommandLine;
359 | else if(string.IsNullOrEmpty(pSetting.strBuildNumber) == false)
360 | PlayerSettings.iOS.buildNumber = pSetting.strBuildNumber;
361 |
362 |
363 | Debug.Log(const_strPrefix_ForDebugLog +
364 | $" Build Setting [IOS]\n" +
365 | $"applicationIdentifier : {PlayerSettings.applicationIdentifier}\n" +
366 | $"PlayerSettings.bundleVersion : {PlayerSettings.bundleVersion}\n" +
367 | $"buildNumber : {PlayerSettings.iOS.buildNumber}"
368 | );
369 | }
370 |
371 | }
372 | }
373 |
374 | #endif
375 |
--------------------------------------------------------------------------------
/Editor/JenkinsBuilder_IOS.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 867ccb99b3bd4074a13329d4fffcd1d8
3 | timeCreated: 1588752768
--------------------------------------------------------------------------------
/Editor/KorStrix.JenkinsBuilder.Editor.asmdef:
--------------------------------------------------------------------------------
1 | {
2 | "name": "KorStrix.JenkinsBuilder.Editor",
3 | "references": [],
4 | "optionalUnityReferences": [],
5 | "includePlatforms": [
6 | "Editor"
7 | ],
8 | "excludePlatforms": [],
9 | "allowUnsafeCode": false,
10 | "overrideReferences": false,
11 | "precompiledReferences": [],
12 | "autoReferenced": true,
13 | "defineConstraints": []
14 | }
--------------------------------------------------------------------------------
/Editor/KorStrix.JenkinsBuilder.Editor.asmdef.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 4bc58e642c93a1646a608a8ddedd04be
3 | AssemblyDefinitionImporter:
4 | externalObjects: {}
5 | userData:
6 | assetBundleName:
7 | assetBundleVariant:
8 |
--------------------------------------------------------------------------------
/GithubImage.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 73ae918af23bcd7428bd2297cba057e6
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/GithubImage/Jenkins_BuildConfig.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KorStrix/Unity_JenkinsBuilder/6a4782ae6f952e73d32477adc18d18d5ca8d5d19/GithubImage/Jenkins_BuildConfig.png
--------------------------------------------------------------------------------
/GithubImage/Jenkins_BuildConfig.png.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 502efca67ed2cc543a589a61ca19a528
3 | TextureImporter:
4 | fileIDToRecycleName: {}
5 | externalObjects: {}
6 | serializedVersion: 9
7 | mipmaps:
8 | mipMapMode: 0
9 | enableMipMap: 1
10 | sRGBTexture: 1
11 | linearTexture: 0
12 | fadeOut: 0
13 | borderMipMap: 0
14 | mipMapsPreserveCoverage: 0
15 | alphaTestReferenceValue: 0.5
16 | mipMapFadeDistanceStart: 1
17 | mipMapFadeDistanceEnd: 3
18 | bumpmap:
19 | convertToNormalMap: 0
20 | externalNormalMap: 0
21 | heightScale: 0.25
22 | normalMapFilter: 0
23 | isReadable: 0
24 | streamingMipmaps: 0
25 | streamingMipmapsPriority: 0
26 | grayScaleToAlpha: 0
27 | generateCubemap: 6
28 | cubemapConvolution: 0
29 | seamlessCubemap: 0
30 | textureFormat: 1
31 | maxTextureSize: 2048
32 | textureSettings:
33 | serializedVersion: 2
34 | filterMode: -1
35 | aniso: -1
36 | mipBias: -100
37 | wrapU: -1
38 | wrapV: -1
39 | wrapW: -1
40 | nPOTScale: 1
41 | lightmap: 0
42 | compressionQuality: 50
43 | spriteMode: 0
44 | spriteExtrude: 1
45 | spriteMeshType: 1
46 | alignment: 0
47 | spritePivot: {x: 0.5, y: 0.5}
48 | spritePixelsToUnits: 100
49 | spriteBorder: {x: 0, y: 0, z: 0, w: 0}
50 | spriteGenerateFallbackPhysicsShape: 1
51 | alphaUsage: 1
52 | alphaIsTransparency: 0
53 | spriteTessellationDetail: -1
54 | textureType: 0
55 | textureShape: 1
56 | singleChannelComponent: 0
57 | maxTextureSizeSet: 0
58 | compressionQualitySet: 0
59 | textureFormatSet: 0
60 | platformSettings:
61 | - serializedVersion: 2
62 | buildTarget: DefaultTexturePlatform
63 | maxTextureSize: 2048
64 | resizeAlgorithm: 0
65 | textureFormat: -1
66 | textureCompression: 1
67 | compressionQuality: 50
68 | crunchedCompression: 0
69 | allowsAlphaSplitting: 0
70 | overridden: 0
71 | androidETC2FallbackOverride: 0
72 | spriteSheet:
73 | serializedVersion: 2
74 | sprites: []
75 | outline: []
76 | physicsShape: []
77 | bones: []
78 | spriteID:
79 | vertices: []
80 | indices:
81 | edges: []
82 | weights: []
83 | spritePackingTag:
84 | pSDRemoveMatte: 0
85 | pSDShowRemoveMatteOption: 0
86 | userData:
87 | assetBundleName:
88 | assetBundleVariant:
89 |
--------------------------------------------------------------------------------
/GithubImage/Jenkins_BuildConfig_Android.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KorStrix/Unity_JenkinsBuilder/6a4782ae6f952e73d32477adc18d18d5ca8d5d19/GithubImage/Jenkins_BuildConfig_Android.png
--------------------------------------------------------------------------------
/GithubImage/Jenkins_BuildConfig_Android.png.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: a094905a75b45a64c935e963cc4818d7
3 | TextureImporter:
4 | fileIDToRecycleName: {}
5 | externalObjects: {}
6 | serializedVersion: 9
7 | mipmaps:
8 | mipMapMode: 0
9 | enableMipMap: 1
10 | sRGBTexture: 1
11 | linearTexture: 0
12 | fadeOut: 0
13 | borderMipMap: 0
14 | mipMapsPreserveCoverage: 0
15 | alphaTestReferenceValue: 0.5
16 | mipMapFadeDistanceStart: 1
17 | mipMapFadeDistanceEnd: 3
18 | bumpmap:
19 | convertToNormalMap: 0
20 | externalNormalMap: 0
21 | heightScale: 0.25
22 | normalMapFilter: 0
23 | isReadable: 0
24 | streamingMipmaps: 0
25 | streamingMipmapsPriority: 0
26 | grayScaleToAlpha: 0
27 | generateCubemap: 6
28 | cubemapConvolution: 0
29 | seamlessCubemap: 0
30 | textureFormat: 1
31 | maxTextureSize: 2048
32 | textureSettings:
33 | serializedVersion: 2
34 | filterMode: -1
35 | aniso: -1
36 | mipBias: -100
37 | wrapU: -1
38 | wrapV: -1
39 | wrapW: -1
40 | nPOTScale: 1
41 | lightmap: 0
42 | compressionQuality: 50
43 | spriteMode: 0
44 | spriteExtrude: 1
45 | spriteMeshType: 1
46 | alignment: 0
47 | spritePivot: {x: 0.5, y: 0.5}
48 | spritePixelsToUnits: 100
49 | spriteBorder: {x: 0, y: 0, z: 0, w: 0}
50 | spriteGenerateFallbackPhysicsShape: 1
51 | alphaUsage: 1
52 | alphaIsTransparency: 0
53 | spriteTessellationDetail: -1
54 | textureType: 0
55 | textureShape: 1
56 | singleChannelComponent: 0
57 | maxTextureSizeSet: 0
58 | compressionQualitySet: 0
59 | textureFormatSet: 0
60 | platformSettings:
61 | - serializedVersion: 2
62 | buildTarget: DefaultTexturePlatform
63 | maxTextureSize: 2048
64 | resizeAlgorithm: 0
65 | textureFormat: -1
66 | textureCompression: 1
67 | compressionQuality: 50
68 | crunchedCompression: 0
69 | allowsAlphaSplitting: 0
70 | overridden: 0
71 | androidETC2FallbackOverride: 0
72 | spriteSheet:
73 | serializedVersion: 2
74 | sprites: []
75 | outline: []
76 | physicsShape: []
77 | bones: []
78 | spriteID:
79 | vertices: []
80 | indices:
81 | edges: []
82 | weights: []
83 | spritePackingTag:
84 | pSDRemoveMatte: 0
85 | pSDShowRemoveMatteOption: 0
86 | userData:
87 | assetBundleName:
88 | assetBundleVariant:
89 |
--------------------------------------------------------------------------------
/GithubImage/Jenkins_BuildConfig_iOS.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KorStrix/Unity_JenkinsBuilder/6a4782ae6f952e73d32477adc18d18d5ca8d5d19/GithubImage/Jenkins_BuildConfig_iOS.png
--------------------------------------------------------------------------------
/GithubImage/Jenkins_BuildConfig_iOS.png.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: eab92f6b90cda2e4ab5442ac0a7b473b
3 | TextureImporter:
4 | fileIDToRecycleName: {}
5 | externalObjects: {}
6 | serializedVersion: 9
7 | mipmaps:
8 | mipMapMode: 0
9 | enableMipMap: 1
10 | sRGBTexture: 1
11 | linearTexture: 0
12 | fadeOut: 0
13 | borderMipMap: 0
14 | mipMapsPreserveCoverage: 0
15 | alphaTestReferenceValue: 0.5
16 | mipMapFadeDistanceStart: 1
17 | mipMapFadeDistanceEnd: 3
18 | bumpmap:
19 | convertToNormalMap: 0
20 | externalNormalMap: 0
21 | heightScale: 0.25
22 | normalMapFilter: 0
23 | isReadable: 0
24 | streamingMipmaps: 0
25 | streamingMipmapsPriority: 0
26 | grayScaleToAlpha: 0
27 | generateCubemap: 6
28 | cubemapConvolution: 0
29 | seamlessCubemap: 0
30 | textureFormat: 1
31 | maxTextureSize: 2048
32 | textureSettings:
33 | serializedVersion: 2
34 | filterMode: -1
35 | aniso: -1
36 | mipBias: -100
37 | wrapU: -1
38 | wrapV: -1
39 | wrapW: -1
40 | nPOTScale: 1
41 | lightmap: 0
42 | compressionQuality: 50
43 | spriteMode: 0
44 | spriteExtrude: 1
45 | spriteMeshType: 1
46 | alignment: 0
47 | spritePivot: {x: 0.5, y: 0.5}
48 | spritePixelsToUnits: 100
49 | spriteBorder: {x: 0, y: 0, z: 0, w: 0}
50 | spriteGenerateFallbackPhysicsShape: 1
51 | alphaUsage: 1
52 | alphaIsTransparency: 0
53 | spriteTessellationDetail: -1
54 | textureType: 0
55 | textureShape: 1
56 | singleChannelComponent: 0
57 | maxTextureSizeSet: 0
58 | compressionQualitySet: 0
59 | textureFormatSet: 0
60 | platformSettings:
61 | - serializedVersion: 2
62 | buildTarget: DefaultTexturePlatform
63 | maxTextureSize: 2048
64 | resizeAlgorithm: 0
65 | textureFormat: -1
66 | textureCompression: 1
67 | compressionQuality: 50
68 | crunchedCompression: 0
69 | allowsAlphaSplitting: 0
70 | overridden: 0
71 | androidETC2FallbackOverride: 0
72 | spriteSheet:
73 | serializedVersion: 2
74 | sprites: []
75 | outline: []
76 | physicsShape: []
77 | bones: []
78 | spriteID:
79 | vertices: []
80 | indices:
81 | edges: []
82 | weights: []
83 | spritePackingTag:
84 | pSDRemoveMatte: 0
85 | pSDShowRemoveMatteOption: 0
86 | userData:
87 | assetBundleName:
88 | assetBundleVariant:
89 |
--------------------------------------------------------------------------------
/GithubImage/Jenkins_EditorWindow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KorStrix/Unity_JenkinsBuilder/6a4782ae6f952e73d32477adc18d18d5ca8d5d19/GithubImage/Jenkins_EditorWindow.png
--------------------------------------------------------------------------------
/GithubImage/Jenkins_EditorWindow.png.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 4d23144f54d90c044bc5da4dd1fb07a5
3 | TextureImporter:
4 | fileIDToRecycleName: {}
5 | externalObjects: {}
6 | serializedVersion: 9
7 | mipmaps:
8 | mipMapMode: 0
9 | enableMipMap: 1
10 | sRGBTexture: 1
11 | linearTexture: 0
12 | fadeOut: 0
13 | borderMipMap: 0
14 | mipMapsPreserveCoverage: 0
15 | alphaTestReferenceValue: 0.5
16 | mipMapFadeDistanceStart: 1
17 | mipMapFadeDistanceEnd: 3
18 | bumpmap:
19 | convertToNormalMap: 0
20 | externalNormalMap: 0
21 | heightScale: 0.25
22 | normalMapFilter: 0
23 | isReadable: 0
24 | streamingMipmaps: 0
25 | streamingMipmapsPriority: 0
26 | grayScaleToAlpha: 0
27 | generateCubemap: 6
28 | cubemapConvolution: 0
29 | seamlessCubemap: 0
30 | textureFormat: 1
31 | maxTextureSize: 2048
32 | textureSettings:
33 | serializedVersion: 2
34 | filterMode: -1
35 | aniso: -1
36 | mipBias: -100
37 | wrapU: -1
38 | wrapV: -1
39 | wrapW: -1
40 | nPOTScale: 1
41 | lightmap: 0
42 | compressionQuality: 50
43 | spriteMode: 0
44 | spriteExtrude: 1
45 | spriteMeshType: 1
46 | alignment: 0
47 | spritePivot: {x: 0.5, y: 0.5}
48 | spritePixelsToUnits: 100
49 | spriteBorder: {x: 0, y: 0, z: 0, w: 0}
50 | spriteGenerateFallbackPhysicsShape: 1
51 | alphaUsage: 1
52 | alphaIsTransparency: 0
53 | spriteTessellationDetail: -1
54 | textureType: 0
55 | textureShape: 1
56 | singleChannelComponent: 0
57 | maxTextureSizeSet: 0
58 | compressionQualitySet: 0
59 | textureFormatSet: 0
60 | platformSettings:
61 | - serializedVersion: 2
62 | buildTarget: DefaultTexturePlatform
63 | maxTextureSize: 2048
64 | resizeAlgorithm: 0
65 | textureFormat: -1
66 | textureCompression: 1
67 | compressionQuality: 50
68 | crunchedCompression: 0
69 | allowsAlphaSplitting: 0
70 | overridden: 0
71 | androidETC2FallbackOverride: 0
72 | spriteSheet:
73 | serializedVersion: 2
74 | sprites: []
75 | outline: []
76 | physicsShape: []
77 | bones: []
78 | spriteID:
79 | vertices: []
80 | indices:
81 | edges: []
82 | weights: []
83 | spritePackingTag:
84 | pSDRemoveMatte: 0
85 | pSDShowRemoveMatteOption: 0
86 | userData:
87 | assetBundleName:
88 | assetBundleVariant:
89 |
--------------------------------------------------------------------------------
/IOS_Shell.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 5fc10328f2e165743aa0c9dd36080c62
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/IOS_Shell/ios_export_ipa.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | # IOS Uploader Bash입니다.
3 | # 주의사항
4 | # Window에서 파일 수정후 맥에서 실행시 줄바꿈 코드(EOL)를 Unix 형식으로 변경바랍니다. (Window/MAC은 안됨)
5 |
6 | WORKSPACE=$1
7 | AppleTeamID=$2
8 | ProjectName=$3
9 |
10 | cd "$WORKSPACE"
11 |
12 | XCODE_PROJECT_DIR="Build"
13 | IPA_EXPORT_PATH="${XCODE_PROJECT_DIR}/.."
14 |
15 |
16 | echo "XCODE_PROJECT_DIR=${XCODE_PROJECT_DIR}"
17 | cd "$XCODE_PROJECT_DIR"
18 | echo "Archive iOS BUILD"
19 |
20 | if test -d "${XCODE_PROJECT_DIR}/Unity-iPhone.xcworkspace"
21 | then
22 | echo "xcodebuild with xcode workspace"
23 | xcodebuild DEVELOPMENT_TEAM="${AppleTeamID}" \
24 | -allowProvisioningUpdates \
25 | -workspace Unity-iPhone.xcworkspace \
26 | -scheme Unity-iPhone \
27 | -configuration Release archive \
28 | -archivePath "${XCODE_PROJECT_DIR}/../archive/${ProjectName}"
29 | else
30 | echo "xcodebuild with xcode project"
31 | xcodebuild DEVELOPMENT_TEAM="${AppleTeamID}" \
32 | -allowProvisioningUpdates \
33 | -scheme Unity-iPhone \
34 | -configuration Release archive \
35 | -archivePath "${XCODE_PROJECT_DIR}/../archive/${ProjectName}"
36 | fi
37 |
38 | echo "Export from ARCHIVE to IPA"
39 |
40 | xcodebuild -allowProvisioningUpdates \
41 | -exportArchive \
42 | -exportOptionsPlist "exportOptions.plist" \
43 | -exportPath "${IPA_EXPORT_PATH}" \
44 | -archivePath "${XCODE_PROJECT_DIR}/../archive/${ProjectName}.xcarchive"
--------------------------------------------------------------------------------
/IOS_Shell/ios_export_ipa.sh.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 19f601fb8a08f7a46b8462742fd0a6d4
3 | DefaultImporter:
4 | externalObjects: {}
5 | userData:
6 | assetBundleName:
7 | assetBundleVariant:
8 |
--------------------------------------------------------------------------------
/IOS_Shell/ipa_send_appstore.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | # 주의사항
3 | # Window에서 파일 수정후 맥에서 실행시 줄바꿈 코드(EOL)를 Unix 형식으로 변경바랍니다. (Window/MAC은 안됨)
4 |
5 | APP_STORE_USERNAME=$1
6 | APP_STORE_PASSWORD=$2
7 | IPA_PATH=$3
8 |
9 | echo "Validate App IPA_PATH : $IPA_PATH"
10 | xcrun altool --validate-app --file "$IPA_PATH" --username "$APP_STORE_USERNAME" --password "$APP_STORE_PASSWORD"
11 |
12 | echo "Upload App IPA_PATH : $IPA_PATH"
13 | xcrun altool --upload-app --file "$IPA_PATH" --username "$APP_STORE_USERNAME" --password "$APP_STORE_PASSWORD"
--------------------------------------------------------------------------------
/IOS_Shell/ipa_send_appstore.sh.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: d481da08ad8063c4cb860317544be92b
3 | DefaultImporter:
4 | externalObjects: {}
5 | userData:
6 | assetBundleName:
7 | assetBundleVariant:
8 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 Strix
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/LICENSE.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 6eaa6f2dbeb8aa34c85ad13773ace966
3 | DefaultImporter:
4 | externalObjects: {}
5 | userData:
6 | assetBundleName:
7 | assetBundleVariant:
8 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # 이 저장소는 관리되지 않습니다.
2 | https://github.com/unity-korea-community/unity-builder
3 |
4 | # 1. 젠킨스 빌더 프로젝트입니다.
5 | 
6 |
7 | `젠킨스`에서 실행하는 유니티 빌드 스크립트 패키지입니다.
8 |
9 | 기능
10 | - Unity Editor 내부/외부(`커맨드라인`)에서 `ConfigFile`을 통해 `Platform`별로 `빌드`
11 |
12 | # 2. 왜 만들었나요?
13 | `커맨드라인`을 통해 `Unity Build`를 할경우 이것저것 `세팅`할게 많습니다.
14 |
15 | 이 세팅들을 `파일`(=**Config File**)에 담은 후 `경로`만 넘겨주는 식으로 빌드하기 위해서 만들었습니다.
16 |
17 | 
18 |
19 | (Config 파일 [링크](https://github.com/KorStrix/Unity_JenkinsBuilder/blob/master/Editor/BuildConfig.cs))
20 |
21 |
22 | # 3. 어떻게 설치하나요?
23 | [링크](https://github.com/KorStrix/Unity_DevelopmentDocs/blob/master/GitHub/UnityPackage.md)를 참고바랍니다.
24 |
25 | **Unity Editor 상단탭/Tools/Build에 메뉴가 뜨면 설치 성공!**
26 |
27 | ---
28 | # 4. 빌드 테스트
29 |
30 | ## 4-1. Build Config 생성 및 Editor에서 바로 빌드 테스트
31 | 1. 유니티 에디터의 상단 탭 - `Tools/Strix/Jenkins Build/Create Build Config Exmaple File`로 `ConfigFile`을 생성합니다.
32 | 2. `Config File`은 `Json 형식`으로 이루어져 있으며, 각 항목당 설명은 스크립트에 주석[(링크)](https://github.com/KorStrix/Unity_JenkinsBuilder/blob/master/Editor/BuildConfig.cs)으로 달았습니다.
33 | 이를 참고하며 `Config File`을 프로젝트에 맞게 수정합니다.
34 | 3. 수정 완료 후 `Tools/Strix/Jenkins Build/Show Jenkins Builder Window`를 통해 윈도우를 엽니다.
35 | 4. 아까 작성한 `Config File Path`를 설정 후 빌드 파일을 어디에 생성할지 세팅합니다.
36 | 5. Android or IOS `Build`를 합니다.
37 | * 빌드 하기 전 주의사항 ) 프로젝트의 `Platform`이 해당 Platform인지 확인합니다.
38 | * `AOS`는 APK를 `바로 빌드`할 수 있지만, `IOS`의 경우 유니티에선 `Xcode Project`로 Export밖에 못합니다.
39 |
40 | 6. **APK or XCode Project가 세팅한 Output path에 나오면 성공!**
41 |
42 | ---
43 | ## 4-2. 젠킨스 - 안드로이드 빌드 테스트
44 |
45 | 
46 |
47 | 빌드하기 전 `BuildConfig/AndroidSetting`을 세팅하세요.
48 |
49 | 안드로이드는 크게 어렵지 않기 때문에 자세한 설명을 생략합니다.
50 |
51 |
52 |
53 | ### 빌드 방법
54 |
55 | 1. 젠킨스 프로젝트를 생성 합니다.
56 | * 젠킨스 프로젝트 생성 관련 내용은 여기서 다루지 않습니다.
57 | 2. 젠킨스 프로젝트 구성 - `Build` 항목에 `Invoke Unity3D Editor` 항목이 있습니다. 여기서 `Editor command line arguments`를 수정할 예정입니다.
58 | * 이 항목에는 Unity Default CommandLine과 이 프로젝트의 CommandLine을 같이 쓰며 CommandLine을 통해 **"어떻게"** 유니티를 실행시키고, 이 프로젝트의 빌드 스크립트를 **"어떻게"** 실행하는지를 세팅하는 곳입니다.
59 | * 유니티 에디터의 커맨드라인 중 -quit -batchmode -logFile log.txt를 넣습니다. 이에 대한 설명은 유니티 메뉴얼[(링크)](https://docs.unity3d.com/kr/530/Manual/CommandLineArguments.html)를 참고합니다.
60 | * 하단의 라인도 연달아 삽입합니다.
61 | ```
62 | -executeMethod Jenkins.Builder.Build_Android -config_path YOUR_CONFIG_PATH.json -output_path ${JENKINS_HOME}/jobs/${JOB_NAME}/builds/${BUILD_NUMBER}/archive
63 | ```
64 | 여기서 YOUR_CONFIG_PATH에 Build Config 파일의 경로를 세팅합니다.
65 | 다른 커맨드 라인을 보고싶으시면 스크립트[(링크)](https://github.com/KorStrix/Unity_JenkinsBuilder/blob/eb5f4c29fe026abfbbdf7977ca4295948cfb8106/Editor/JenkinsBuilder.cs#L60)를 참고바랍니다.
66 |
67 | - ${JENKINS_HOME}, ${JOB_NAME}, ${BUILD_NUMBER}의 경우 Jenkins 환경변수입니다.
68 |
69 |
70 | 3. **Build를 한 뒤 Archive에 APK파일이 있으면 성공!**
71 |
72 | ---
73 | ## 4-3. 젠킨스 - IOS 빌드 테스트
74 |
75 | 
76 |
77 | 빌드하기 전 `BuildConfig/iOSSetting`을 세팅하세요.
78 |
79 | ### 주의사항
80 | **IOS 빌드를 위해선 MAC OS의 PC와 Apple 개발자 계정이 필요합니다.**
81 |
82 | ### 개요
83 | 안드로이드의 경우 PC -> APK 추출 -> 선택에 따라 -> APK 스토어 업로드까지 크게 어렵지는 않으나,
84 |
85 | IOS의 경우 ipa를 공유하려면
86 | PC -> XCode Project -> ipa 추출 -> Appstore Connect 업로드까지 해아 하며,
87 | PC -> XCode Project 과정에서 ipa -> Appstore Connect 업로드에 필요한 `plist(property list)` 등을 함께 `Xcode Project`에 담아야 합니다. 이것은 `Config File`로 작업할 수 있습니다.
88 |
89 | 젠킨스에 IOS Build 플러그인이 있음에도 불구하고 배치파일로 뺀 이유는 세팅 간소화 및 범용성을 위해서입니다.
90 | (플러그인에 세팅해야 할 변수가 많음, 젠킨스가 아닌 환경에서도 쓸 수 있게끔)
91 |
92 | **여기서 IOS 빌드 테스트 항목은 PC -> XCode Project -> ipa 추출 및 Appstore Connect 업로드까지 테스트합니다.**
93 |
94 | **Appstore Connect 링크**
95 | https://appstoreconnect.apple.com/
96 |
97 | ### 빌드 방법
98 | 1. 젠킨스 프로젝트 생성 후 `프로젝트 구성`으로 갑니다.
99 | 2. `Build`에 Execute Shell 작업을 추가하고 하단의 내용을 적습니다.
100 | ```
101 | # 폴더 내 모든 걸 비우기
102 | rm -r ${WORKSPACE}/Build/
103 | ```
104 | 3. `Build`에 `Invoke Unity3D Editor/Editor command line arguments`에 하단의 내용을 적습니다.
105 | ```
106 | -quit -batchmode -executeMethod Jenkins.Builder.Build_IOS -config_path YOUR_CONFIG_PATH.json -output_path ${WORKSPACE} -filename Build -ios_version 1
107 | ```
108 |
109 | 4. `Build`에 `Execute Shell` 작업을 추가하고 하단의 내용을 적습니다.
110 | ```
111 | # ipa Export
112 | sh "ios_export_ipa.sh이 들어있는 경로" "${WORKSPACE}" "AppleTeamID"
113 | ```
114 | 여기서 `AppleTeamID`는 애플 계정에 있는 애플 `팀 ID`를 기입합니다. `팀 ID`는 숫자와 대문자 영어로 이루어진 10개의 단어입니다. (2020.08 기준)
115 |
116 | 5. Mac OS가 설치된 PC에서 XCode를 설치 후 `Preference - AppleTeamID`를 등록한 뒤 **빌드**를 합니다.
117 | 6. **Build를 한 뒤 AppleStore Connect 사이트에 세팅한 빌드번호의 빌드가 있으면 성공**
118 |
--------------------------------------------------------------------------------
/README.md.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 939cf69029667ec40a8df6b2207f283b
3 | TextScriptImporter:
4 | externalObjects: {}
5 | userData:
6 | assetBundleName:
7 | assetBundleVariant:
8 |
--------------------------------------------------------------------------------
/Shell.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: ed20f3a8f790e4c4a9e72fd58850073e
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Shell/UploadFTP.sh:
--------------------------------------------------------------------------------
1 | # ============================================
2 | # 작성자 : Strix
3 | # 개요 : LFTP를 통해 FTP에 업로드하는 스크립트입니다.
4 | # LFTP는 병렬 전송 및 실패 시 어느정도 자동화를(경로가 없으면 경로생성 등) 지원하기 때문에 채택하였습니다.
5 | #
6 | # 설치 : LFTP를 설치해야 합니다.
7 | # - 공식 홈페이지 : https://lftp.yar.ru/
8 | #
9 | # 주의사항 : Window에서 파일 수정후 맥에서 실행시 줄바꿈 코드(EOL)를 Unix 형식으로 변경바랍니다. (Window/MAC은 안됨)
10 | # ============================================
11 |
12 |
13 | # 데이터 세팅 - FTP
14 | HOST=$1
15 | USER=$2
16 | PASS=$3
17 |
18 | CLEAR_TARGET_DIR_IF_EXIST=$4
19 | SOURCE_DIR=$5
20 | TARGET_DIR=$6
21 |
22 |
23 | # TARGETDIR이 이미 있으면 비우기 유무
24 | if [ $CLEAR_TARGET_DIR_IF_EXIST == "true" ]
25 | then
26 | echo "Clear Start // Target Dir : $TARGET_DIR"
27 |
28 | lftp -f "
29 | open $HOST
30 | user $USER $PASS
31 | set ftp:ssl-allow no;
32 | rm -r -f "$TARGET_DIR";
33 | bye
34 | "
35 | fi
36 |
37 |
38 | echo "Upload Start // SourceDir : $SOURCE_DIR TargetDir : $TARGET_DIR"
39 |
40 | lftp -f "
41 | open $HOST
42 | user $USER $PASS
43 | set ftp:ssl-allow no;
44 | mirror -R --parallel=50 $SOURCE_DIR $TARGET_DIR
45 | bye
46 | "
47 |
--------------------------------------------------------------------------------
/Shell/UploadFTP.sh.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: f4c79528136decc4d993b788841c9e6a
3 | DefaultImporter:
4 | externalObjects: {}
5 | userData:
6 | assetBundleName:
7 | assetBundleVariant:
8 |
--------------------------------------------------------------------------------
/Shell/VersionHandler.sh:
--------------------------------------------------------------------------------
1 | # ============================================
2 | # 작성자 : Strix
3 | # 개요 : 버전 파일(Json 형식만 지원)을 핸들링하는 Shell입니다.
4 | # 설치 : JJ(Json CLI Editor,https://github.com/tidwall/jj)를 설치해야 합니다.
5 | #
6 | # 주의사항 : Window에서 파일 수정후 맥에서 실행시 줄바꿈 코드(EOL)를 Unix 형식으로 변경바랍니다. (Window/MAC은 안됨)
7 | # ============================================
8 |
9 |
10 | # 데이터 세팅
11 | FILE_NAME=$1
12 | EDIT_NAME=$2
13 | METHOD_NAME=$3
14 | ZERO_PADDING_COUNT=$4
15 |
16 | # JJ 플러그인을 통해 변수 추출
17 | VERSION=$(cat "$FILE_NAME" | jj "$EDIT_NAME")
18 |
19 | if [ "$METHOD_NAME" == "GET" ] || [ "$METHOD_NAME" == "get" ]
20 | then
21 | echo $VERSION
22 |
23 | else
24 | NEW_VERSION=$VERSION;
25 |
26 | echo "Current File : $(cat "$FILE_NAME") METHOD_NAME : $METHOD_NAME \nNEW_VERSION : $NEW_VERSION"
27 |
28 | if [ "$METHOD_NAME" == "ADD" ] || [ "$METHOD_NAME" == "add" ]
29 | then
30 | # 변수에 1을 더합니다. `10#`을 안붙일 경우 에러가 뜹니다. (shell은 기본적으로 8진수 계산이므로 9 이상 숫자가 나올 시 에러)
31 | NEW_VERSION=$((10#${VERSION} + 1))
32 | elif [ "$METHOD_NAME" == "SUB" ] || [ "$METHOD_NAME" == "sub" ]
33 | then
34 | # 변수에 1을 더합니다.
35 | NEW_VERSION=$((10#${VERSION} - 1))
36 | fi
37 |
38 | if [ "$ZERO_PADDING_COUNT" != "0" ]
39 | then
40 | OPERATOR="%0${ZERO_PADDING_COUNT}d"
41 | NEW_VERSION=$(printf \""$OPERATOR\"" $NEW_VERSION)
42 |
43 | echo "Zero Fill $ADD_PREFIX // $NEW_VERSION"
44 | fi
45 |
46 | echo "$EDIT_NAME : Current : $VERSION // New : $NEW_VERSION"
47 |
48 | # 1을 더한 값을 변수에 저장후 덮어쓰기
49 | # -v = 덮어쓰기 / -p = 보기좋은 출력
50 | FILE_TEXT=$(cat "$FILE_NAME" | jj -r -v "$NEW_VERSION" "$EDIT_NAME" | jj -p)
51 |
52 | # 변수를 파일에 덮어쓰며 확인합니다.
53 | echo "$FILE_TEXT" > "$FILE_NAME"
54 | echo "New File : $(cat "$FILE_NAME")"
55 | fi
--------------------------------------------------------------------------------
/Shell/VersionHandler.sh.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 8d6b16f68de22284895a5ed6038cb3d8
3 | DefaultImporter:
4 | externalObjects: {}
5 | userData:
6 | assetBundleName:
7 | assetBundleVariant:
8 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "com.korstrix.jenkinsbuilder",
3 | "version": "1.0.0",
4 | "displayName": "ZZ.Jenkins Builder",
5 | "description": "\uc820\ud0a8\uc2a4\uc5d0\uc11c \uc2e4\ud589\ud558\ub294 \uc720\ub2c8\ud2f0 \ube4c\ub4dc \uc2a4\ud06c\ub9bd\ud2b8\uc785\ub2c8\ub2e4.",
6 | "unity": "2018.1",
7 | "keywords": [
8 | "utility"
9 | ],
10 | "author": {
11 | "name": "KorStrix",
12 | "email": "korstrix@gmail.com",
13 | "url": "https://github.com/KorStrix/Unity_JenkinsBuilder"
14 | }
15 | }
--------------------------------------------------------------------------------
/package.json.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: a415ffceec2ef544eb9fa3302910749c
3 | PackageManifestImporter:
4 | externalObjects: {}
5 | userData:
6 | assetBundleName:
7 | assetBundleVariant:
8 |
--------------------------------------------------------------------------------