Unity 基于Jenkins自动化打包流程

什么是Jenkins?

        Jenkins是一款开源 CI&CD 软件,用于自动化各种任务,包括构建、测试和部署软件。Jenkins 支持各种运行方式,可通过系统包、Docker 或者通过一个独立的 Java 程序。

Jenkins的下载与安卓

直接搜索jenkins进入官网下在LTS(稳定版本)下载地址:https://www.jenkins.io/download/

下载完成打开执行文件,点击下一步,修改安装目录,

Unity 基于Jenkins自动化打包流程_第1张图片

 下载JavaJDK,选中目录然后一直点击next完成安装

Unity 基于Jenkins自动化打包流程_第2张图片

安装完成后 在网页打开 http://localhost:8080 端口号是安装时所选的端口号

 Unity 基于Jenkins自动化打包流程_第3张图片

按提示找到密码输入,然后直接安装推荐插件,安装完成设置账号密码

 Unity 基于Jenkins自动化打包流程_第4张图片

 Unity 基于Jenkins自动化打包流程_第5张图片

配置本地的jenkins路径用于访问

Unity 基于Jenkins自动化打包流程_第6张图片

 然后访问配置路径 http://localhost:8080/  输入账号密码进入

Unity 基于Jenkins自动化打包流程_第7张图片

unity 相关配置 

找到插件配置,添加Unity3d插件

Unity 基于Jenkins自动化打包流程_第8张图片

Unity 基于Jenkins自动化打包流程_第9张图片

Unity 基于Jenkins自动化打包流程_第10张图片

 找到全局配置 配置unity 安装路径

Unity 基于Jenkins自动化打包流程_第11张图片

 Unity 基于Jenkins自动化打包流程_第12张图片

 新建项目

输入项目名称,选着项目类型,创建

Unity 基于Jenkins自动化打包流程_第13张图片

 配置项目

  1. 项目描述
  2. 项目显示名称
  3. 丢弃旧的构建(Discard old builds)
  4. 参数化构建过程(This project is parameterized)
  5. 使用自定义的工作空间(unity项目根目录)
  6. 定时构建(Build periodically)
  7. 添加window命令行(Build Steps/Execute Windows batch command)
  8. 添加unity版本(Build Steps/Invoke Unity3d Editor)
  9. 项目归档(Archive the artifacts)将打包出来的东西进行储存

一下会使用到window 命令行,对于命令行不熟悉的可以看下这篇文章:Window 命令行与bat批处理文件总结

使用到的命令在里面都能找到

Unity 基于Jenkins自动化打包流程_第14张图片

 SVN Server 下载与安装

Downloads | VisualSVN

Unity 基于Jenkins自动化打包流程_第15张图片

 创建SVN目录  右键Repositories->Create New Repository

Unity 基于Jenkins自动化打包流程_第16张图片

Unity 基于Jenkins自动化打包流程_第17张图片

 右键 Uers 创建用户

Unity 基于Jenkins自动化打包流程_第18张图片

 本地SVN下载:Downloads · TortoiseSVN

Unity 基于Jenkins自动化打包流程_第19张图片

 下载后安装,文件夹下右键 SVN ->CheckOut,填入的路基是SVNServer项目路径

Unity 基于Jenkins自动化打包流程_第20张图片

SVN 命令行

  • svn commit -m * 上传全部文件
  • svn add * 添加全部文件
  • svn update 更新目录所有文件及文件更新
  • svn cleanup 解锁
  • svn revert * 还原文件

Jenkins SVN更新配置

添加构建化参数,项目地址:

Unity 基于Jenkins自动化打包流程_第21张图片

添加命令行构建步骤:

  •  svn 更新命令
  • 执行unity编辑器函数   

Unity 基于Jenkins自动化打包流程_第22张图片

-projectpath %WorkPath% -quit -batchmode -executeMethod BuildApp.Build -logFile "D:\log.txt"
  • -projectpath %WorkPath% 工程路径

  • -quit 执行完后退出编辑器

  • -batchmode 执行unity的时候不会弹出Unity编辑器框

  • -executeMethod BuildApp.Build 编辑器方法

  • -logFile "D:\log.txt"    执行jenkins log输出位置

添加参数并将Jenkins参数传递给Unity

Unity 基于Jenkins自动化打包流程_第23张图片

 将参数传递给Unity:

使用定义的变量名加入到命令行中 Name=$Name 

-projectpath %WorkPath% -quit -batchmode -executeMethod BuildApp.BuildAndroid Name=$Name Version=$Version  HotCount=$HotCount ChanelType=$ChanelType -logFile "D:\log.txt"

Unity接收命令行参数并解析:

主要还是这段代码:

string[] parameters = Environment.GetCommandLineArgs();

public class BuildSettingCfg
{
    public string Name = "Res";
    public string Version = "1.0.1";
    public int HotCount = 1;
    public ChannelType ChannelType = ChannelType.OVERSEAS_SDK;    // 渠道宏定义
}

public enum ChannelType
{
    BAIBAO,
    OVERSEAS_SDK
}
public static BuildSettingCfg GetBuildSettingCfg()
        {
            // 获取命令行参数
            string[] parameters = Environment.GetCommandLineArgs();
            BuildSettingCfg buildSettingCfg = new BuildSettingCfg();
            for (int i = 0; i < parameters.Length; i++)
            {
                string str = parameters[i];
                string[] paramArr = str.Split('=');
                if (paramArr.Length <= 1)
                {
                    Debug.Log(paramArr.Length+":" +  paramArr[0]);
                    continue;
                }
                string param = paramArr[1];
                if(str.StartsWith("Name"))
                {
                    buildSettingCfg.Name = param;
                }
                else if(str.StartsWith("Version"))
                {
                    buildSettingCfg.Version = param;
                }
                else if(str.StartsWith("HotCount"))
                {
                    buildSettingCfg.HotCount = Convert.ToInt32(param);
                }
                else if (str.StartsWith("ChannelType"))
                {
                    buildSettingCfg.ChannelType = (ChannelType)Enum.Parse(typeof(ChannelType), param);
                }
            }

            return buildSettingCfg;
        }

设置解析后的对象,并设置Unity

        public static void SetAndroidSetting(BuildSettingCfg cfg)
        {
            PlayerSettings.productName = cfg.Name;
            PlayerSettings.bundleVersion = cfg.Version;
            PlayerSettings.Android.bundleVersionCode = cfg.HotCount;
            
            // 原有宏定义
            string symbol = PlayerSettings.GetScriptingDefineSymbolsForGroup(BuildTargetGroup.Android);
            // 移除原来的渠道宏定义
            symbol = symbol.Replace(ChannelType.BAIBAO.ToString(), string.Empty)
                     .Replace(ChannelType.OVERSEAS_SDK.ToString(), string.Empty);
            
            PlayerSettings.SetScriptingDefineSymbolsForGroup(BuildTargetGroup.Android,symbol + ";" + cfg.ChannelType.ToString());
        }

打包完成,压缩安装包 

添加压缩命令行:

Unity 基于Jenkins自动化打包流程_第24张图片

 打包需要时将apk文件路径保存到BuildName.txt文件中

@echo off
cd /d E:
cd E:\RAR解压软件
for /F "delims=;" %%i in (%WorkPath%\Build\BuildName.txt) do set name=%%i
WinRAR.exe a -r -ep1 %name%.rar %name%.apk
echo %name%.apk压缩完成
pause
  • 进入压缩软件安装的盘符
  • 进入压缩软件根目录
  • 读取文件路径
  • 对读取的文件进行压缩

贴一下buildApp代码吧

public class BuildApp
    {
        public static string VERSION_File_PATH = Application.dataPath + "/Resources/Version.xml";
        public static string AppName = "MyApp";
        public static string VERSION = "1.0.1";
        public static string PackageName = "DefaultCompany.ResourceManager";
        public static string ABMD5RootPath = Application.dataPath + "/../ABMD5/";
        public static string BuildPath = Directory.GetParent(Application.dataPath) + "/Build/";

        [MenuItem("Tools/一键打包PC")]
        public static void BuildPC()
        {
            // SaveVersion(VERSION,PackageName);
            BuildPipeline.BuildPlayer(EditorBuildSettings.scenes, BuildPath + AppName, BuildTarget.StandaloneWindows64,
                BuildOptions.None);
        }

        public static string GetABMD5FilePath()
        {
            return string.Format("%s%s/%s", ABMD5RootPath, EditorUserBuildSettings.activeBuildTarget.ToString(), VERSION);
        }
    
        public static void SaveVersion(string version, string packageName)
        {
            VersionInfo info = XmlSerializerOpt.DeserializeFile(VERSION_File_PATH);
            info.Version = version;
            info.PackageName = packageName;
            XmlSerializerOpt.SaveSerializerFile(VERSION_File_PATH,info);
            AssetDatabase.Refresh();
        }

        [MenuItem("Tools/一键打包Android")]
        public static void BuildAndroid()
        {
            // 获取命令行配置
            BuildSettingCfg buildSettingCfg = GetBuildSettingCfg();
            // 设置命令行
            SetAndroidSetting(buildSettingCfg);
            
            string appName = buildSettingCfg.Name + "_" + DateTime.Now.ToString("yyyy_MM_dd_hh_mm") + ".apk";
            string appFullName = BuildPath + "Android/" + appName;
            SaveAppName(appFullName.Replace(".apk",string.Empty));
            BuildPipeline.BuildPlayer(EditorBuildSettings.scenes, appName, BuildTarget.Android,
                BuildOptions.None);
        }

        public static void SaveAppName(string appFullName)
        {
            StreamWriter sr = File.CreateText(BuildPath + "BuildName.txt");
            sr.Write(appFullName);
            sr.Close();
        }

        public static BuildSettingCfg GetBuildSettingCfg()
        {
            // 获取命令行参数
            string[] parameters = Environment.GetCommandLineArgs();
            BuildSettingCfg buildSettingCfg = new BuildSettingCfg();
            for (int i = 0; i < parameters.Length; i++)
            {
                string str = parameters[i];
                string[] paramArr = str.Split('=');
                if (paramArr.Length <= 1)
                {
                    Debug.Log(paramArr.Length+":" +  paramArr[0]);
                    continue;
                }
                string param = paramArr[1];
                if(str.StartsWith("Name"))
                {
                    buildSettingCfg.Name = param;
                }
                else if(str.StartsWith("Version"))
                {
                    buildSettingCfg.Version = param;
                }
                else if(str.StartsWith("HotCount"))
                {
                    buildSettingCfg.HotCount = Convert.ToInt32(param);
                }
                else if (str.StartsWith("ChannelType"))
                {
                    buildSettingCfg.ChannelType = (ChannelType)Enum.Parse(typeof(ChannelType), param);
                }
            }

            return buildSettingCfg;
        }

        public static void SetAndroidSetting(BuildSettingCfg cfg)
        {
            PlayerSettings.productName = cfg.Name;
            PlayerSettings.bundleVersion = cfg.Version;
            PlayerSettings.Android.bundleVersionCode = cfg.HotCount;
            
            // 原有宏定义
            string symbol = PlayerSettings.GetScriptingDefineSymbolsForGroup(BuildTargetGroup.Android);
            // 移除原来的渠道宏定义
            symbol = symbol.Replace(ChannelType.BAIBAO.ToString(), string.Empty)
                     .Replace(ChannelType.OVERSEAS_SDK.ToString(), string.Empty);
            
            PlayerSettings.SetScriptingDefineSymbolsForGroup(BuildTargetGroup.Android,symbol + ";" + cfg.ChannelType.ToString());
        }
    }

你可能感兴趣的:(Unity,jenkins,自动化,运维,unity)