LoginSignup
14
18

More than 3 years have passed since last update.

Jenkins+Unity+Windows 久しぶりなのでメモ(バッチモードしんどい)

Last updated at Posted at 2019-04-10

インストールの仕方

 参考URL:https://itsakura.com/tool-jenkins-install

 ※Widnowsの場合、注意が必要。
  ProgamFilesフォルダに馬鹿正直にインストールしたところ、
  workspaceがその中に作られてcloneするまではよかったが
  内部のUnityプロジェクトが読み書き不可能エリアらしくて開けなかった。
  

Global Tool Configuration

◆◆ Git ◆◆

 ●Gitのexeパス設定(Git実行形式へのパス)
  私はSourceTree入れてるので、下記パスを入力
 
  C:\Users\XXXXX\AppData\Local\Atlassian\SourceTree\git_local\bin\git.exe

◆◆ Unity ◆◆

 ●Jenkins-->プラグインの管理-->利用可能タブ-->Unity3d を入れる(再起動せずにインストール)

 ●インストールディレクトリの設定(ディレクトリ名なので、そこまでのパスを設定)
  C:\Program Files\Unity\Hub\Editor\2018.3.8f1\Editor

GitHubのリポジトリをクローン

セキュリティ的にはよくないが確認するだけなら、
まずはこれで@以降を自分のリポジトリにして
ユーザー名とパスワードを設定すればクローンできるっぽい

書式:https://username:password@bitbucket.org/username/repo-name.git

参考URL:https://gist.github.com/n-shinya/5675834

これでもエラーが出る場合、
例えば returned status code 128

リポジトリURLの下にある認証情報をセットしてCloneする。

認証情報を設定するためには、
Jenkinsの認証情報->System->グローバルドメインを選択
グローバルドメイン.png

追加する。

Cloneが成功すると、なぜか他のジョブでは認証情報を設定しなくても
https://username:password@********.git 

でクローンできた謎ですね。(一旦、Jenkinsの認証を通す必要があるのかな?)

ビルド手順の追加

 「Widnowsバッチコマンドの実行」を追加して下記を記述

Unityのexeパス -batchmode -quit -projectPath プロジェクトパス -executeMethod クラス名.メソッド名

(注)何回やってもエラーになるので、コマンドプロンプトから実行、でもエラー。
「このアプリはお使いのPCでは実行できませんと表示される」
同じ職場の方にも、調べてもらったら実行はできて、・・・あれってなりました。
インストールしたunityのエグゼファイルのプロパティを見ると、私の方にはデジタル署名のタブがありませんでした。
とりあえずインストールし直しました。

(注1)クラス名とメソッド名はpublic staticじゃないと呼べないかも
(注2)名前空間も関係していて、usingに移動する必要あり
    名前空間ありクラスだとエラーがでる、
    コマンドプロンプトからバッチモード起動をでエラーが確認できました(Editor.log参照)。

(注3)

バッチモードで呼び出し成功例

◆呼び出し側
"C:\Program Files\Unity2018_3_8_f1\Editor\Unity.exe" -batchmode -quit -buildTarget プラットフォーム -projectPath C:\Users\XXXXX\Documents\プロジェクトフォルダ -executeMethod BatchTest.OutPutLog

◆呼び出される側

using UnityEditor;
using UnityEngine;

public class BatchTest
{
    public static void OutPutLog()
    {
        Debug.Log("123456790");
    }
}

◆Editor.log内の内容

123456790
UnityEngine.DebugLogHandler:Internal_Log()
UnityEngine.DebugLogHandler:LogFormat(LogType, Object, String, Object[])
UnityEngine.Logger:Log(LogType, Object)
UnityEngine.Debug:Log(Object)

バッチモードで呼び出しエラー例1(staticではない)

◆呼び出し側
"C:\Program Files\Unity2018_3_8_f1\Editor\Unity.exe" -batchmode -quit -projectPath C:\Users\XXXXX\Documents\プロジェクトフォルダ -executeMethod BatchTest.OutPutLog

◆呼び出される側

using UnityEditor;
using UnityEngine;

public class BatchTest
{
    public void OutPutLog()
    {
        Debug.Log("123456790");
    }
}

◆Editor.log内の内容

executeMethod method 'OutPutLog' in class 'BatchTest' could not be found.
Argument was -executeMethod BatchTest.OutPutLog

バッチモードで呼び出しエラー例2(名前空間あり)

◆呼び出し側
"C:\Program Files\Unity2018_3_8_f1\Editor\Unity.exe" -batchmode -quit -projectPath C:\Users\XXXXX\Documents\プロジェクトフォルダ -executeMethod BatchTest.OutPutLog

◆呼び出される側

using UnityEditor;
using UnityEngine;

namespace test.batch.test
{
    public class BatchTest
    {
        public static void OutPutLog()
        {
            Debug.Log("123456790");
        }
    }
}

◆Editor.log内の内容

executeMethod class 'BatchTest' could not be found.
Argument was -executeMethod BatchTest.OutPutLog

(Filename: C:\buildslave\unity\build\Runtime/Utilities/Argv.cpp Line: 354)


Aborting batchmode due to failure:
executeMethod class 'BatchTest' could not be found.
Argument was -executeMethod BatchTest.OutPutLog

Exiting without the bug reporter. Application will terminate with return code 1

バッチモードで引数あり呼び出し成功例(シーン名を引数にする)

◆呼び出し側
"C:\Program Files\Unity2018_3_8_f1\Editor\Unity.exe" -batchmode -quit -projectPath C:\Users\XXXXX\Documents\プロジェクトフォルダ -executeMethod BatchTest.OutPutLog /scene シーン名

◆呼び出される側

using UnityEditor;
using UnityEngine;

/// <summary>
/// バッチモードビルドのテスト用クラス
/// </summary>
public class BatchTest
{
    public static void OutPutLog()
    {
        Debug.Log("123456790");
        GetSceneNameFromArgs();
    }

    /// <summary>
    /// バッチ処理側の引数を抜き出してシーン名を取得する。
    /// </summary>
    /// <returns></returns>
    private static string GetSceneNameFromArgs()
    {
        Debug.Log("GetSceneNameFromArgs");
        string[] args = System.Environment.GetCommandLineArgs();
        for (int i = 0; i < args.Length; ++i)
        {
            Debug.Log("GetSceneNameFromArgs i=" + i);
            Debug.Log("GetSceneNameFromArgs args[i]=" + args[i]);
            if (args[i] == "/scene")
            {
                Debug.Log("GetSceneNameFromArgs args[i + 1]=" + args[i + 1]);
                return args[i + 1];
            }
        }

        return string.Empty;
    }
}

バッチモードで引数あり呼び出し成功例(クラス名の前に名前空間をつけて、シーン名を引数にする)

◆呼び出し側
"C:\Program Files\Unity2018_3_8_f1\Editor\Unity.exe" -batchmode -quit -projectPath C:\Users\XXXXX\Documents\プロジェクトフォルダ -executeMethod test.batch.test.BatchTest.OutPutLog /scene シーン名

◆呼び出される側

using UnityEditor;
using UnityEngine;

namespace test.batch.test
{
    /// <summary>
    /// バッチモードビルドのテスト用クラス
    /// </summary>
    public class BatchTest
    {
        public static void OutPutLog()
        {
            Debug.Log("123456790");
            GetSceneNameFromArgs();
        }

        /// <summary>
        /// バッチ処理側の引数を抜き出してシーン名を取得する。
        /// </summary>
        /// <returns></returns>
        private static string GetSceneNameFromArgs()
        {
            Debug.Log("GetSceneNameFromArgs");
            string[] args = System.Environment.GetCommandLineArgs();
            for (int i = 0; i < args.Length; ++i)
            {
                Debug.Log("GetSceneNameFromArgs i=" + i);
                Debug.Log("GetSceneNameFromArgs args[i]=" + args[i]);
                if (args[i] == "/scene")
                {
                    Debug.Log("GetSceneNameFromArgs args[i + 1]=" + args[i + 1]);
                    return args[i + 1];
                }
            }

            return string.Empty;
        }
    }
}

Jenkins側のパラメーターをWindowsバッチコマンド経由で渡すには?

Jenkins側のパラメーター設定
Jenkinsパラメータ.png

Jenkins側のWindowsバッチコマンド設定
Windowsバッチコマンド引数パラーメータあり.png

Unity側のソース

渡ってきた引数パラメーターの取得

/// <summary>
/// バッチ処理側の引数を抜き出して開発用ビルドパラメーターを取得する。
/// </summary>
/// <returns></returns>
private static string GetPathFromArgs()
{
    string[] args = System.Environment.GetCommandLineArgs();
    for (int i = 0; i < args.Length; ++i)
    {
        if (args[i] == "/build")
        {
            return args[i + 1];
        }
    }

    return string.Empty;
}

開発用パラメーターを判定して開発用ビルドオプションを設定する

private static BuildOptions _buildOptions = BuildOptions.None;

public static void WindowsBuild()
{
    var isDevelopment  = GetPathFromArgs();

    if(isDevelopment == "true")
    {
        _buildOptions = BuildOptions.Development;
    }

※参照URL:https://fuwafuwac.com/?p=214

「Windowsバッチコマンドの実行」を使用エリア内、curlで取得した値を変数に入れてパラメーターで渡す。

REM コメント
set CMD=curl URL
set GETVERSION=
for /f "usebackq delims=" %%a in (`%CMD%`) do set GETVERSION=%%a
echo %GETVERSION%

REM スペースを空文字に変換
set VersionStr=%GETVERSION: =%

echo %VersionStr%

ログ出力ありバッチビルド

「Windowsバッチコマンドの実行」を使用(development Build等いろいろパラメーター化した場合の例)

"C:\Program Files\Unity2018_3_8_f1\Editor\Unity.exe" -batchmode -quit -logFile .\build.log -projectPath プロジェクトのフォルダパス -executeMethod 名前空間.クラス名.メソッド名
 /DevelopBuild %Jenkinsのパラメータ% /HostType %Jenkinsのパラメータ% /BundleVersionCode %Jenkinsのパラメータ% /Version %Jenkinsのパラメータ% /ServerVersionCode %CURLの結果% /Compiler %Jenkinsのパラメータ% /Signed %Jenkinsのパラメータ%

Windows64ビルドは成功したが、Oculus用のGoビルドはapkが作られなかったので対処法メモ(めっちゃはまった)

エラー内容:unity jenkins unable to locate android sdk

参考URL
https://codingtrabla.blogspot.com/2016/03/jenkins-unity3d-plugin-unable-to-locate.html

システム環境変数にAndroidSDKのパスを通す必要があるみたい・・・Windowsだから?

さらに、Jenkins側にも設定が必要っぽい

Jenkinsの管理⇒システムの設定⇒グローバルプロパティ⇒環境変数にチェックをする。

キー:ANDROID_SDK_ROOT(なんでもいい気がする)
値:AndroidSDKのパス
(フォルダまで、わからなかったらUnityのpreferencesを開いてExternalToolsのSDKのパスをパクってくればOK) 
 C:\Users\ユーザー名\AppData\Local\Android\sdk


APKが作られたことを確認。

Jenkins側のUnity関係の設定メモ

Jenkinsの管理⇒Pluginの管理⇒Unity3d plugin をインストール

Jenkinsの管理⇒Global Tool Configuration⇒Unity3d

名前:わかりやすければなんでもいいはず、UnityExePathとした。
インストールディレクトリ:C:\Program Files\Unity2018_3_8_f1\

※注:Editor\Unity.exe の部分を除外したパスを設定する。

ジョブ側のUnity記述方法

ビルド手順の追加⇒Invoke Unity3d Editor

Unity3d installation name:さっき設定したUnityExePathを選ぶ
Editor command line arguments:-batchmode -quit -logFile C:\Users\ユーザー名\AppData\Local\Unity\Editor\Editor.log -executeMethod 名前空間.クラス名.メソッド名

クローンするブランチのプルダウン選択

Groovyあんまわからんけど結構便利なので入れておきたい。

参考URL:https://qiita.com/fuku2014/items/8f731db20743c33efddf

入れられなかった・・・・・Macの時はいけたのに・・

ワークスペース直下の jenkins.err.log によると

com.cwctravel.hudson.plugins.extended_choice_parameter.ExtendedChoiceParameterDefinition executeGroovyScriptAndProcessGroovyValue
重大: Cannot run program "git": CreateProcess error=2, 指定されたファイルが見つかりません。
java.io.IOException: Cannot run program "git": CreateProcess error=2, 指定されたファイルが見つかりません。

gitコマンドが認識されていない、

Jenkinsのシステムの設定のシェルの「シェル実行ファイル」を下記にしてもダメ・・・
Windowsの環境変数のシステムパスに追加してもダメ・・・・うーんわからん。

C:\Users\ユーザー名\AppData\Local\Atlassian\SourceTree\git_local\bin\sh.exe

色々探した結果
List Git Branches Parameter Plugin を使用すると同じ事ができるようだ
https://wiki.jenkins.io/display/JENKINS/List+Git+Branches+Parameter+Plugin

Jenkinsジョブの表示名を日本語にする。

ジョブを選択⇒設定⇒高度な設定⇒表示用プロジェクト名に任意の文字を入力する。

Jenkins側ジョブの実行コンソール出力される文字の文字化け修正。

◆文字化け対策(参照URL)
https://tokkan.net/web/jenkins5.html

①システム環境変数に下記を追加する。
 変数:JAVA_TOOL_OPTIONS
 値:-Dfile.encoding=UTF-8 -Dsun.jnu.encoding=UTF-8

②PC再起動する(Jenkins側のシステムの再読み込みだけでは反映されず)

Switch Platformをスクリプトで行う。

// Androidにプラットフォームを切り替える。
EditorUserBuildSettings.SwitchActiveBuildTarget(BuildTargetGroup.Android, BuildTarget.Android);

Symbol設定をスクリプトで行う。

PlayerSettings.SetScriptingDefineSymbolsForGroup(BuildTargetGroup.Android, ";"区切りの文字列);

PackageName Or Bundle Identifier の設定をスクリプトで行う。

// パッケージ名の設定(Android)
PlayerSettings.SetApplicationIdentifier(BuildTargetGroup.Android,packageName);

Slack連携時のメッセージカスタマイズ(各パラメーターも含めて通知する)

基本的にパラメーター名の頭に$を付ければ良い

●Jenkins自身が持っているパラメータはこちらを参照
 https://wiki.jenkins.io/display/JA/Building+a+software+project

 ジョブ名が欲しければ $JOB_NAME とすれば良い

●自分たちで作ったパラメーターに関しては名前欄に入っている内容を使う

 選択したブランチ名の名前がBranchであれば$Branch と擦ればいい

「ビルド後の処理」⇒「Custom Message」 の欄に下記のように記述すると、
ジョブ番号・ブランチ名付きでメッセージが通知される。

ビルド開始
 ジョブ番号:$BUILD_NUMBER
 ブランチ名:$Branch

呼び出される側

全アセットを検索
https://qiita.com/T_2/items/bbd03ad320fbc03595af

シーン名検索

var guids = AssetDatabase.FindAssets("t:Scene", null);
foreach (var guid in guids)
{
    string path = AssetDatabase.GUIDToAssetPath(guid);
    Debug.Log("path=" + path);

    if (path.IndexOf("シーン名.unity") >= 0)
    {
        Debug.Log("Matches");
        break;
    }
}

動的パラメータが必要なのでGroovyを頑張って動かす(Windows)

目的:GroovyからUnityのバッチモードを使ってEditor拡張をコマンドで呼び出し、
   作成されたシーン一覧ファイルの中身を表示する。

①cygwinを入れる(Bestが選択されているので、そのままインストール)
https://cygwin.com/install.html

②システム環境変数を修正。(コントロールパネルかWindowsアイコンの右クリックからいける)
 システム⇒システム情報⇒システムの詳細設定⇒環境変数⇒システム環境変数エリアのPathを編集
 ⇒C:\cygwin64\binのようにbinフォルダをパスとして通しておく

 ※念のためPC再起動しておく

③Jenkins側の操作に移って⇒Jenkinsの管理⇒システムの設定⇒シェルの項目のシェル実行ファイルエリアを未入力にする

④Jenkinsの管理⇒プラグインの管理⇒extended choice parameterをインストールする。

⑤任意のジョブを作り、ビルドパラメーターの追加から、extended choice parameter を選択

⑥適当なパラメーター名を入力して、シェルコマンドを実行してみる。
動いた!!

下図、参照
Groovy1.png

(注)シェルの内容確認だけであれば、Jenkinsの管理⇒スクリプトコンソール を開いて入力してみると、実行内容の確認ができる。

下図参照
2019-07-19 (1).png

2019-07-19 (2).png

⑦シーンリストを作るEditor拡張の作成

",;"をいちいちつけてるのは、";"でSplitして配列にし、末尾が,で終わるリストにするため。

sceneNames = sceneNames.Substring(0, sceneNames.Length - 2); は 最終行は","無しにして保存したいため
そうしないとGroovy側のDelimiterを","にして複数行状態にする時、空白の行ができる。

using System.IO;
using System.Text;
using UnityEditor;

namespace aaa.bbb.ccc.EditorExtension
{
    public static class BuildExtension
    {
        private const string SCENE_FILENAME = "scenelist.txt";

        private const string CHECK_SCENE_STRING = "フィルタリングする文字列";

        public static void WriteBuildScene()
        {
            // シーンファイルのみのguidを取得
            var guids = AssetDatabase.FindAssets("t:Scene", null);

            string sceneNames = string.Empty;

            foreach (var guid in guids)
            {
                // アセットパスに変換
                string path = AssetDatabase.GUIDToAssetPath(guid);

                // 拡張子なしのファイル名を抜き出す
                string sceneName = Path.GetFileNameWithoutExtension(path);

                if(sceneName.IndexOf(CHECK_SCENE_STRING) <0)
                {
                    continue;
                }

                sceneNames = sceneNames + sceneName + ",;";
            }

            sceneNames = sceneNames.Substring(0, sceneNames.Length - 2);

            // 文字コードを指定
            Encoding enc = Encoding.GetEncoding("utf-8");

            // ファイルを開く
            StreamWriter writer = new StreamWriter(Path.Combine(Directory.GetCurrentDirectory(), SCENE_FILENAME), false, enc);

            foreach(var scene in sceneNames.Split(';'))
            {
                // テキストに書き込む
                writer.WriteLine(scene);
            }

            // ファイルを閉じる
            writer.Close();
        }
    }
}


⑧Jenkins側のGroovyスクリプトエリアに下記を記述する。

(注)めっちゃはまった
def e=でコマンド文を受け取らないと、Unityが起動しっぱなしになるためわざと変数で受ける。
2重起動のエラーJenkinsのコンソールに表示される。

WORKSPACEの環境変数が使えなかったので、フルパス記述・・・・やり方はあると思うけど時間切れ

ジョブ内の
 extended choice parameterChoose Source for ValueGroovy Script

String a="C:/Program Files/Unity2018_3_8_f1_LiveEdit/Editor/Unity.exe"
String b="C:/Users/XXXXXX/Desktop/Jenkins/workspace/ワークスペースフォルダ"

String d = "C:/Users/XXXXXX/Desktop/Jenkins/workspace/ワークスペースフォルダ" + "/scenelist.txt"

def e = "$a -batchmode -quit -projectPath $b -executeMethod aaa.bbb.ccc.EditorExtension.BuildExtension.WriteBuildScene".execute()

def f = new File("$d")
def h = f.getText()

return h

extended choice parameterのにてパラメーター設定

パラメーター名を任意のものにして、チェックボックスで複数選択できるようにする。

※Delimiterを","にする、スペースでやってみたが変換されないのであえて","にする。
 ここもなんかありそう。

extended_param.png

⑩ジョブ側で複数シーンをパラメーターとして送る。

Windowsバッチコマンドの実行に下記を記述・・・これで動きました。

"C:\Program Files\Unity2018_3_8_f1_LiveEdit\Editor\Unity.exe" -batchmode -quit -logFile ./build.log -buildTarget Android -projectPath %WORKSPACE% -executeMethod aaa.bbb.ccc.EditorExtension.MakeAssetBundleScene.MakeSceneFromBatch /scene %AssetBundleScenes%

◆参考にしたページ
https://codeday.me/jp/qa/20181216/50076.html
https://issues.jenkins-ci.org/browse/JENKINS-33708?focusedCommentId=263259&page=com.atlassian.jira.plugin.system.issuetabpanels%3Acomment-tabpanel#comment-263259

◆プロセス系コマンドメモ

http://hironemu.hatenablog.com/entry/20090408/1239163437
https://www.atmarkit.co.jp/ait/articles/1808/16/news026.html

WMIC PROCESS WHERE "Name LIKE '%Unity%'" GET /FORMAT:LIST
14
18
6

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
14
18