Jenkins的具体代码
系列文章
- Jenkins使用
- Jenkins插件使用
- Jenkins具体代码
简介
- 本人是使用cocoscreator进行打包的,以下是我个人的设置,在此做个记录
使用插件 | 作用 |
---|---|
Publish Over SSH | 上传 |
Active Choices Plug-in | 构建参数的选项变更 |
File Operations Plugin | 压缩移动文件 |
Persistent Parameter Plugin | 保存版本信息 |
CocosCreator Jenkins所在目录
在Jenkin中已经设置了Shell环境变量,所以在Window和Mac都可以使用shell命令
项目根目录
|
|--- assets
|
|--- Jenkins
| |
| |--- Jenkinsfile
| |
| |--- CocosCreatorBuild.sh
| |
| |--- ASbuild.sh
| |
| |--- XCodeBuild.sh
|
|--- ...
主体Jenkins
Orientation =
[
//横屏
Landscape:"landscape",
//竖屏
Portrait:"portrait",
//自动
Auto:"auto"
]
JSBTemplate =
[
//JSB模板,直接链接Cocos引擎的库,单人开发好用
Link:"link",
//JSB模板,将Cocos引擎的库复制到当前项目中,多人开发好用
Default:"default"
]
Agent =
[
//代理的Key
Window:"Window",
Mac:"Mac",
//代理的系统类型
Type:
[
Win:"win",
Mac:"mac"
]
]
ServerUrl =
[
//Web公司内网地址
WebCompanyInterior:"[NEED]xxx.xxx.xxx",
//Web公司外网地址
WebCompanyWithout:"[NEED]xxx.xxx.xxx",
//apk公司内网地址
APKCompanyInterior:"[NEED]xxx.xxx.xxx",
]
GameProject =
[
//项目名字,即项目文件夹名字
Name:"[NEED]项目名字",
//Excel导表文件夹
ExcelToolDir:"[NEED]Excel导表文件夹",
//Excel导表工具,不用添加后缀
ExcelToolName:"[NEED]Excel导表工具",
//设备方向
Orientation:Orientation.Portrait,
BuildSetting:
[
Web:
[
//构建命令,必要
BuildCmd:"platform=web-mobile",
//代理的Key,必要
AgentKey:Agent.Window,
//默认平台
Default: [],
],
Mini:
[
//构建命令,必要
BuildCmd:"platform=&buildPlatform",
//代理的Key,必要
AgentKey:Agent.Window,
//默认平台
Default: [ BuildPlatform:"wechatgame" ],
//微信平台
Wx: [ BuildPlatform:"wechatgame" ],
//头条平台
Tt: [ BuildPlatform:"wechatgame" ]
],
Android:
[
//构建命令,必要
BuildCmd:"platform=android",
//代理的Key,必要
AgentKey:Agent.Window,
//安卓cpu构建选项:['armeabi-v7a','arm64-v8a','x86','x86_64'],通用必要
AppABIs:"['armeabi-v7a','arm64-v8a','x86','x86_64']",
//安卓SDK的版本,通用必要
ApiLevel:30,
//JSB模板,通用必要
Template:JSBTemplate.Default,
//包名,通用必要
PackageName:"org.cocos2d.demo",
//默认平台, 可以重写上述通用必要的值
Default: [],
//字节平台, 可以重写上述通用必要的值
ByteDance: [ PackageName:"[NEED]xxx.xxx.xxxxx" ]
],
Ios:
[
//构建命令,必要
BuildCmd:"platform=ios",
//代理的Key,必要
AgentKey:Agent.Mac,
//JSB模板,通用必要
Template:JSBTemplate.Link,
//包名,通用必要
PackageName:"org.cocos2d.demo",
//默认平台, 可以重写上述通用必要的值
Default: [],
//字节平台, 可以重写上述通用必要的值
ByteDance: [ PackageName:"[NEED]xxx.xxx.xxxxx" ]
]
],
]
Const =
[
Mode:
[
Key:"MODE",
Des:"开发模式:带有打印信息,单纯测试才能选择改模式;\n线上模式:不带有打印信息,带有混淆代码,发布正式选择此模式",
Value: [ Develop:"开发模式", Release:"线上模式" ]
],
AppVersion:
[
Key:"APP_VERSION",
Des:"主版本号,构建的版本号会自动保存,需要修改在进行修改",
Value:"0.0.1"
],
IsUpload:
[
Key:"IS_UPLOAD",
Des:"是否上传\nweb环境:不勾选只上传内网;勾选即上传内网和外网服务器\n原生苹果环境:勾选即上传AppStore\n原生安卓环境:勾选即上传内网",
Value: false
],
Enviroment:
[
Key:"ENVIROMENT",
Des:"游戏打包环境",
Value:
[
//Value 对于代码中环境的枚举值
Web: [ Code:"Web", Key:"Web环境", Value:0 ],
Mini: [ Code:"Mini", Key:"小游戏环境", Value:1 ],
Android: [ Code:"Android", Key:"原生安卓环境", Value:2 ],
Ios: [ Code:"Ios", Key:"原生苹果环境", Value:3 ],
]
],
Platform:
[
Key:"PLATFORM",
Des:"游戏打包平台",
Value:
[
//Value 对于代码中平台的枚举值
Web:
[
Default: [ Code:"Default", Key:"默认", Value:1 ]
],
Mini:
[
Default: [ Code:"Default", Key:"默认", Value:0 ],
Wx: [ Code:"Wx", Key:"微信", Value:1 ],
Tt: [ Code:"Tt", Key:"头条", Value:2 ]
],
Android:
[
Default: [ Code:"Default", Key:"默认", Value:0 ],
ByteDance: [ Code:"ByteDance", Key:"字节跳动", Value:1 ]
],
Ios:
[
Default: [ Code:"Default", Key:"默认", Value:0 ],
ByteDance: [ Code:"ByteDance", Key:"字节跳动", Value:1 ]
]
]
],
//代理节点
Agent:
[
//Window代理标签
Window:
[
//类型
Type:Agent.Type.Win,
//CocosCreator软件所在地址
CocosCreator:"[NEED]CocosCreatorExe所在地址,例如 D:/Engine/CocosCreator/CocosDashboard/resources/.editors/Creator/2.4.6/CocosCreator.exe",
//项目所在地址
ProjectPath:"[NEED]项目所在地址,例如 D:/Projects/CocosCreator/${GameProject.Name}",
//构建目标地址
BuildPath:"[NEED]项目构建地址,例如 D:/Builds/CocosCreator/${GameProject.Name}",
//Android的密钥
AndroidKeystore:
[
Path:"[NEED]Android的密钥存放地址,例如 D:/XXX/xxx.jks",
Password:"[NEED]Android的密钥密码",
Alias:"[NEED]Android的密钥别名",
AliasPassword:"[NEED]Android的密钥别名密码"
]
],
//Mac代理标签
Mac:
[
//类型
Type:Agent.Type.Mac,
//用户目录
UserDir:"[NEED]用户目录,例如 /Users/xxx",
//CocosCreator软件所在地址
CocosCreator:"[NEED]项目所在地址,例如 /Applications/CocosCreator/Creator/2.4.6/CocosCreator.app/Contents/MacOS/CocosCreator",
//项目所在地址
ProjectPath:"[NEED]项目所在地址,例如 /Users/xxx/Projects/CocosCreator/${GameProject.Name}",
//构建目标地址
BuildPath:"[NEED]项目构建地址,例如 /Users/xxx/Builds/CocosCreator/${GameProject.Name}",
//Android的密钥
AndroidKeystore:
[
Path:"[NEED]Android的密钥存放地址,例如 /XXX/xxx.jks",
Password:"[NEED]Android的密钥密码",
Alias:"[NEED]Android的密钥别名",
AliasPassword:"[NEED]Android的密钥别名密码"
],
//Mac的密钥及登入密码,有这个密钥才能用命令行上传AppStore
MacKeysore:
[
//连接AppStore的密钥,进入https://appstoreconnect.apple.com/->用户和访问->密钥(没有就新增密钥)
//密钥只能下载一次,下载地址在隐藏文件夹/Users/xxx/.private_keys中
//IssuerID 就是 api_issuer, 密钥ID 就是 api_key
ApiKey:"[NEED]密钥ID",
ApiIssuer:"[NEED]IssuerID",
//mac登入密码,解锁钥匙串用的
LoginPassword:"[NEED]mac登入密码"
]
]
]
]
def BuildTimeDayStr()
{
return new Date().format('yyyy.MM.dd');
}
def BuildTimeSecondStr()
{
// 构建时间,输出结果 2019.12.10.17.58.42
return new Date().format('yyyy.MM.dd.HH.mm.ss');
}
//返回环境选项列表[Web, Mini, Android, IOS]
def ReturnEnviromentChoices(isDefault)
{
judgeChoices = "return &evnListStr";
judgeCode = "";
envList = Const.Enviroment.Value.values();
list = isDefault ? [envList[0]] : envList;
evnListStr = GetEvnOrPlatformKeyListStr(list);
judgeCode = judgeChoices.replaceAll("&evnListStr", evnListStr);
return judgeCode;
}
//返回平台选项列表的代码[Default, ....]
def ReturnPlatformChoices(isDefault, envKey)
{
judgeChoices = "if(&env.equals('&needEnv')){return &platformListStr}\n";
judgeCode = "";
evnList = Const.Enviroment.Value.values();
for(int i = 0; i < evnList.size(); i++)
{
evn = evnList[i];
envCode = GetEnvCode(evn.Key);
platformList = Const.Platform.Value[envCode].values();
list = isDefault ? [platformList[0]] : platformList;
platformListStr = GetEvnOrPlatformKeyListStr(list);
code = judgeChoices;
code = code.replaceAll("&env", envKey);
code = code.replaceAll("&needEnv", evn.Key);
code = code.replaceAll("&platformListStr", platformListStr);
judgeCode += code;
}
return judgeCode;
}
//获取环境或平台的Key列表字符串
def GetEvnOrPlatformKeyListStr(envOrPlatformlist)
{
lenth = envOrPlatformlist.size();
envOrPlatformlistStr = "[";
for(int i = 0; i < lenth; i++)
{
if(i > 0) { envOrPlatformlistStr = envOrPlatformlistStr + "," }
envOrPlatformlistStr = envOrPlatformlistStr + "'" + envOrPlatformlist[i].Key + "'";
}
envOrPlatformlistStr = envOrPlatformlistStr + "]";
return envOrPlatformlistStr;
}
//通过环境Key和平台Key获取平台Code
def GetPlatformCode(envKey, platformKey)
{
envCode = GetEnvCode(envKey);
platformList = Const.Platform.Value[envCode].values();
for(int i = 0; i < platformList.size(); i++)
{
if(platformKey == platformList[i].Key)
{
return platformList[i].Code;
}
}
return "";
}
//通过环境Key获取环境Code
def GetEnvCode(envKey)
{
evnList = Const.Enviroment.Value.values();
for(int i = 0; i < evnList.size(); i++)
{
if(envKey == evnList[i].Key)
{
return evnList[i].Code;
}
}
return "";
}
//通过环境Code获取设备方向的命令行参数
def GetOrientation(envCode)
{
orientation = "";
if(envCode == Const.Enviroment.Value.Web.Code
||envCode == Const.Enviroment.Value.Mini.Code)
{
orientation = "webOrientation=" + GameProject.Orientation;
}
else if(envCode == Const.Enviroment.Value.Android.Code
||envCode == Const.Enviroment.Value.Ios.Code)
{
if(GameProject.Orientation == Orientation.Landscape)
{
orientation = "orientation={'landscapeLeft': true, 'landscapeRight': true}";
}
else if(GameProject.Orientation == Orientation.Portrait)
{
orientation = "orientation={'portrait': true}";
}
else
{
orientation = "orientation={'landscapeLeft': true, 'landscapeRight': true, 'portrait': true}";
}
}
return orientation;
}
//通过环境Code和平台Code还有参数获取需要的命令行参数
def GetPlatformBuildParam(envCode, platformCode, paramsKey)
{
if(GameProject.BuildSetting[envCode].containsKey(platformCode)
&& GameProject.BuildSetting[envCode][platformCode].size() > 0
&& GameProject.BuildSetting[envCode][platformCode].containsKey(paramsKey))
{
return GameProject.BuildSetting[envCode][platformCode][paramsKey];
}
else
{
return GameProject.BuildSetting[envCode][paramsKey];
}
}
@NonCPS
def CheckVersion(version)
{
versionReg = /^(?:[1-9]\d*|0)(?:\.(?:[1-9]\d*|0)){2}$/
if(version == "0.0.0")
{
return "版本号不能为0.0.0";
}
else if(version ==~ versionReg)
{
return "版本号错误";
}
else
{
return "";
}
}
properties([
parameters([
choice(
choices: Const.Mode.Value.values(),
description: Const.Mode.Des,
name: Const.Mode.Key
),
persistentString(
defaultValue: Const.AppVersion.Value,
description: Const.AppVersion.Des,
name: Const.AppVersion.Key,
successfulOnly: false,
trim: true
),
choice(
choices: ['master'],
description: '远程项目分支',
name: 'ORIGIN_BRANCK'
),
[
$class: 'ChoiceParameter',
choiceType: 'PT_SINGLE_SELECT',
description: Const.Enviroment.Des,
filterLength: 1,
filterable: false,
name: Const.Enviroment.Key,
randomName: 'choice-parameter-162030434430400',
script: [
$class: 'GroovyScript',
fallbackScript: [
classpath: [],
sandbox: true,
script: ReturnEnviromentChoices(true)
],
script: [
classpath: [],
sandbox: true,
script: ReturnEnviromentChoices(false)
]
]
],
[
$class: 'CascadeChoiceParameter',
choiceType: 'PT_SINGLE_SELECT',
description: Const.Platform.Des,
filterLength: 1,
filterable: false,
name: Const.Platform.Key,
randomName: 'choice-parameter-162030443211600',
referencedParameters: Const.Enviroment.Key,
script: [
$class: 'GroovyScript',
fallbackScript: [
classpath: [],
sandbox: true,
script: ReturnPlatformChoices(true, Const.Enviroment.Key)
],
script: [
classpath: [],
sandbox: true,
script: ReturnPlatformChoices(false, Const.Enviroment.Key)
]
]
],
booleanParam(
description: Const.IsUpload.Des,
name: Const.IsUpload.Key
)
])
])
pipeline
{
//选择全局控制节点
agent { label "GlobalControl" }
stages
{
stage("设置常量")
{
steps
{
script
{
echo "设置常量"
//将所有需要用到的参数设置到环境变量中
EnviromentCode = GetEnvCode("${params.ENVIROMENT}");
PlatformCode = GetPlatformCode("${params.ENVIROMENT}", "${params.PLATFORM}");
AgentKey = GameProject.BuildSetting[EnviromentCode].AgentKey;
if(!Const.Agent.containsKey(AgentKey))
{
error("未能找到代理<${AgentKey}>");
return;
}
AgentConfig = Const.Agent[AgentKey];
BuildPath = AgentConfig.BuildPath + "/" + PlatformCode;
NativePath = BuildPath + "/jsb-" + GetPlatformBuildParam(EnviromentCode, PlatformCode, "Template");
env.Agent = AgentKey;
env.ProjectName = GameProject.Name;
env.ProjectPath = AgentConfig.ProjectPath;
env.ExcelToolDir = AgentConfig.ProjectPath + "/" + GameProject.ExcelToolDir;
env.CocosCreatorPath = AgentConfig.CocosCreator;
env.EnviromentValue = Const.Enviroment.Value[EnviromentCode].Value;
env.PlatformValue = Const.Platform.Value[EnviromentCode][PlatformCode].Value;
env.PlatformCode = PlatformCode;
env.AppVersion = "${params.APP_VERSION}";
env.DevVersion = "${BUILD_NUMBER}";
env.BuildPath = BuildPath;
env.BuildXCodeDir = "${NativePath}/frameworks/runtime-src/proj.ios_mac";
env.BuildASDir = "${NativePath}/frameworks/runtime-src/proj.android-studio";
env.BuildTimeSecond = BuildTimeSecondStr();
env.BuildTimeDay = BuildTimeDayStr();
env.IsDebug = "${params.MODE}" == Const.Mode.Value.Develop;
env.IsOnline = "${params.MODE}" == Const.Mode.Value.Release;
env.IsUpload = "${params.IS_UPLOAD}";
echo "EnviromentValue:${EnviromentValue}"
echo "PlatformValue:${PlatformValue}"
//设置Win和Mac节点下的参数
if(Const.Agent[env.Agent].Type == Agent.Type.Mac)
{
env.MacUserDir = AgentConfig.UserDir;
env.ExcelToolName = GameProject.ExcelToolName;
}
else
{
env.ExcelToolName = GameProject.ExcelToolName + ".exe";
}
//Cocos命令行构建
env.BuildCmd = GameProject.BuildSetting[EnviromentCode].BuildCmd;
env.BuildCmd += ";" + "buildPath=${env.BuildPath}";
env.BuildCmd += ";" + "md5Cache=true";
env.BuildCmd += ";" + "sourceMaps=true";
env.BuildCmd += ";" + "debug=${env.IsDebug}";
env.BuildCmd += ";" + GetOrientation(EnviromentCode);
echo "EnviromentCode:${EnviromentCode}"
echo "PlatformCode:${PlatformCode}"
if(EnviromentCode == Const.Enviroment.Value.Web.Code)
{
}
else if(EnviromentCode == Const.Enviroment.Value.Mini.Code)
{
env.BuildCmd = env.BuildCmd.replaceAll("&buildPlatform", GameProject.BuildSetting.Mini[PlatformCode].BuildPlatform);
}
else
{
template = GetPlatformBuildParam(EnviromentCode, PlatformCode, "Template");
packageName = GetPlatformBuildParam(EnviromentCode, PlatformCode, "PackageName");
env.BuildCmd += ";" + "encryptJs=${params.IsOnline}";
env.BuildCmd += ";" + "template=${template}";
env.BuildCmd += ";" + "packageName=${packageName}";
if(EnviromentCode == Const.Enviroment.Value.Android.Code)
{
apiLevel = GetPlatformBuildParam(EnviromentCode, PlatformCode, "ApiLevel");
appABIs = GetPlatformBuildParam(EnviromentCode, PlatformCode, "AppABIs");
env.AndroidApiLevel = apiLevel;
env.AndroidAppABIs = appABIs;
env.AndroidKeystorePath = AgentConfig.AndroidKeystore.Path;
env.AndroidKeystorePassword = AgentConfig.AndroidKeystore.Password;
env.AndroidKeystoreAlias = AgentConfig.AndroidKeystore.Alias;
env.AndroidKeystoreAliasPassword = AgentConfig.AndroidKeystore.AliasPassword;
}
else if(EnviromentCode == Const.Enviroment.Value.Ios.Code)
{
env.MacApiKey = AgentConfig.MacKeysore.ApiKey;
env.MacApiIssuer = AgentConfig.MacKeysore.ApiIssuer;
env.MacLoginPassword = AgentConfig.MacKeysore.LoginPassword;
}
}
}
}
}
stage("进行构建")
{
agent { label "${env.Agent}" }
stages
{
stage('更新Git')
{
steps
{
echo "更新Git"
sh """
cd ${env.ProjectPath}
# 更新主仓库
git checkout .
git clean -f
git checkout master
git pull origin master
# 更新子仓库
git submodule foreach git checkout .
git submodule foreach git clean -f
git submodule foreach git checkout master
git submodule foreach git pull origin master
"""
}
}
stage('构建')
{
steps
{
echo "CocosCreatorExe地址: ${env.CocosCreatorPath}"
echo "Cocos项目地址: ${env.ProjectPath}"
echo "ExcelTool文件夹地址: ${env.ExcelToolDir}"
echo "ExcelTool名称: ${env.ExcelToolName}"
echo "Build地址: ${env.BuildPath}"
echo "构建环境: ${env.EnviromentValue}(${params.ENVIROMENT})"
echo "构建平台: ${env.PlatformValue}(${params.PLATFORM})"
echo "构建模式: isDebug:${env.IsDebug}, isOnline:${env.IsOnline}(${params.MODE})"
echo "App版本: ${env.AppVersion}, 构建版本:${env.DevVersion}"
echo "构建事件: ${env.BuildTimeSecond}"
echo "构建命令行: ${env.BuildCmd}"
echo "构建"
sh """
chmod 777 ${env.ProjectPath}/Jenkins/CocosCreatorBuild.sh
${env.ProjectPath}/Jenkins/CocosCreatorBuild.sh
"""
}
}
stage("Web压缩")
{
when
{
beforeAgent true
environment name: Const.Enviroment.Key, value: Const.Enviroment.Value.Web.Key
}
steps
{
script
{
WebName = "web-mobile";
echo "Web压缩"
//压缩后放到工作空间文件夹下,方便后面上传
fileOperations([
fileZipOperation(
folderPath: "${env.BuildPath}/${WebName}",
outputFolderPath: "./"
)
])
}
}
}
stage("Web内网测试上传")
{
when
{
beforeAgent true
environment name: Const.Enviroment.Key, value: Const.Enviroment.Value.Web.Key
}
steps
{
script
{
echo "Web内网测试上传"
sshPublisher (
publishers:[
sshPublisherDesc(
configName: '内网服务器',
transfers: [
sshTransfer(
cleanRemote: false,
excludes: '',
execCommand: "cd /www/wwwroot/${ServerUrl.WebCompanyInterior}/${env.ProjectName} && rm -rf web-mobile && unzip web-mobile.zip && rm -rf web-mobile.zip",
execTimeout: 120000,
flatten: false,
makeEmptyDirs: false,
noDefaultExcludes: false,
patternSeparator: '[, ]+',
remoteDirectory: "/${ServerUrl.WebCompanyInterior}/${env.ProjectName}",
remoteDirectorySDF: false,
removePrefix: '',
sourceFiles: "web-mobile.zip"
)
],
usePromotionTimestamp: false,
useWorkspaceInPromotion: false,
verbose: false
),
]
)
}
}
}
stage("Web外网测试上传")
{
when
{
beforeAgent true
allOf
{
environment name: Const.Enviroment.Key, value: Const.Enviroment.Value.Web.Key
environment name: Const.IsUpload.Key, value: "true"
}
}
steps
{
script
{
echo "Web外网测试上传"
sshPublisher (
publishers:[
sshPublisherDesc(
configName: '外网测试服务器',
transfers: [
sshTransfer(
cleanRemote: false,
excludes: '',
execCommand: "cd /www/wwwroot/${ServerUrl.WebCompanyWithout}/${env.ProjectName} && rm -rf web-mobile && unzip web-mobile.zip && rm -rf web-mobile.zip",
execTimeout: 120000,
flatten: false,
makeEmptyDirs: false,
noDefaultExcludes: false,
patternSeparator: '[, ]+',
remoteDirectory: "/${ServerUrl.WebCompanyWithout}/${env.ProjectName}",
remoteDirectorySDF: false,
removePrefix: '',
sourceFiles: "web-mobile.zip"
)
],
usePromotionTimestamp: false,
useWorkspaceInPromotion: false,
verbose: false
)
]
)
}
}
}
stage('安卓编译上传')
{
when
{
beforeAgent true
allOf
{
environment name: Const.Enviroment.Key, value: Const.Enviroment.Value.Android.Key
environment name: Const.IsUpload.Key, value: "true"
}
}
steps
{
echo "安卓编译上传"
echo "AndroidStudio项目地址:${env.BuildASDir}"
echo "AndroidApiLevel:${env.AndroidApiLevel}"
echo "AndroidAppABIs:${env.AndroidAppABIs}"
echo "AndroidKeystorePath:${env.AndroidKeystorePath}";
echo "AndroidKeystorePassword:${env.AndroidKeystorePassword}"
echo "AndroidKeystoreAlias:${env.AndroidKeystoreAlias}"
echo "AndroidKeystoreAliasPassword:${env.AndroidKeystoreAliasPassword}"
sh """
chmod 777 ${env.ProjectPath}/Jenkins/ASbuild.sh
${env.ProjectPath}/Jenkins/ASbuild.sh
"""
script
{
AppMode = env.IsOnline == "true" ? "release" : "debug";
OldAPKName = "${env.ProjectName}-${AppMode}.apk";
NewAPKName = "${env.ProjectName}_v${env.AppVersion}.${env.DevVersion}_${AppMode}.apk";
echo "AppMode:${AppMode}"
echo "OldAPKName:${OldAPKName}"
echo "NewAPKName:${NewAPKName}"
fileOperations([
fileRenameOperation(
source: "${env.BuildASDir}/app/build/outputs/apk/${AppMode}/${OldAPKName}",
destination: "./${NewAPKName}"
)
])
sshPublisher (
publishers:[
sshPublisherDesc(
configName: '内网服务器',
transfers: [
sshTransfer(
cleanRemote: false,
excludes: '',
execCommand: "",
execTimeout: 120000,
flatten: false,
makeEmptyDirs: false,
noDefaultExcludes: false,
patternSeparator: '[, ]+',
remoteDirectory: "/${ServerUrl.APKCompanyInterior}/Android/${env.ProjectName}/${env.PlatformCode}/",
remoteDirectorySDF: false,
removePrefix: '',
sourceFiles: "${NewAPKName}"
)
],
usePromotionTimestamp: false,
useWorkspaceInPromotion: false,
verbose: false
)
]
)
}
}
}
stage('IOS编译上传')
{
when
{
beforeAgent true
allOf
{
environment name: Const.Enviroment.Key, value: Const.Enviroment.Value.Ios.Key
environment name: Const.IsUpload.Key, value: "true"
}
}
steps
{
echo "IOS编译上传"
echo "XCode项目地址:${env.BuildXCodeDir}"
echo "MacApiKey:${env.MacApiKey}"
echo "MacApiIssuer:${env.MacApiIssuer}"
echo "MacLoginPassword:${env.MacLoginPassword}"
sh """
chmod 777 ${env.ProjectPath}/Jenkins/XCodeBuild.sh
${env.ProjectPath}/Jenkins/XCodeBuild.sh
"""
}
}
}
}
}
}
CocosCreatorBuild.sh
- 这是本人打包所使用的配套的Excel打包工具,需要根据自己的项目实际情况配置。
- LaunchSettingPath:是项目启动读取的配置。
echo "执行CocosCreatorBuild.sh"
ExcelToolPath="${ExcelToolDir}/${ExcelToolName}"
ExcelToolIntputExcelPath="${ProjectPath}/Doc/3_数值文档"
ExcelToolOutputJsonPath="${ProjectPath}/assets/jsons"
ExcelToolOutputTsPath="${ProjectPath}/assets/scripts/Datas"
ExcelToolOutputType="1"
PlotInputPath="${ProjectPath}/Doc/7_剧情"
PlotOutputPath="${ProjectPath}/assets/resources/Json/Story"
LaunchSettingPath="${ProjectPath}/assets/libs/launch_setting/LaunchSetting.js"
echo "ExcelToolPath:${ExcelToolPath}"
echo "ExcelToolIntputExcelPath:${ExcelToolIntputExcelPath}"
echo "ExcelToolOutputJsonPath:${ExcelToolOutputJsonPath}"
echo "ExcelToolOutputTsPath:${ExcelToolOutputTsPath}"
echo "ExcelToolOutputType:${ExcelToolOutputType}"
echo "PlotInputPath:${PlotInputPath}"
echo "PlotOutputPath:${PlotOutputPath}"
echo "LaunchSettingPath:${LaunchSettingPath}"
cd ${ProjectPath}
# 构建配置表
cd ${ExcelToolDir}
echo "执行CocosCreatorBuild.sh 构建配置表"
${ExcelToolPath} ${ExcelToolIntputExcelPath} ${ExcelToolOutputJsonPath} ${ExcelToolOutputTsPath} ${ExcelToolOutputType}
cd ${ProjectPath}
# 拷贝剧情内容
echo "执行CocosCreatorBuild.sh 拷贝剧情内容"
cp ${PlotInputPath}/*.json ${PlotOutputPath}
cp ${PlotInputPath}/*/*.json ${PlotOutputPath}
# 修改启动配置
cat ${LaunchSettingPath}
echo "执行CocosCreatorBuild.sh 修改启动配置"
sed -ig 's/\$Environment\$/'${EnviromentValue}'/' ${LaunchSettingPath}
sed -ig 's/\$Platform\$/'${PlatformValue}'/' ${LaunchSettingPath}
sed -ig 's/\$IsOnline\$/'${IsOnline}'/' ${LaunchSettingPath}
sed -ig 's/\$AppVersion\$/'${AppVersion}'/' ${LaunchSettingPath}
sed -ig 's/\$DevelopVersion\$/'${DevVersion}'/' ${LaunchSettingPath}
sed -ig 's/\$BuildTime\$/'${BuildTimeSecond}'/' ${LaunchSettingPath}
cat ${LaunchSettingPath}
#构建
echo "执行CocosCreatorBuild.sh 构建"
${CocosCreatorPath} --path "${ProjectPath}" --build "${BuildCmd}"
XCode打包Shell
- MacUserDir:不能使用
~
,只能使用绝对路径,由Jenkins那边传入。
echo "执行XCodeBuild.sh"
#XCode 里面对应需要打包的target名字
SchemeName="${ProjectName}-mobile"
#XCode的绝对路径
ProjectXCode="${BuildXCodeDir}/${ProjectName}.xcodeproj"
#xcarchive的目录
ProjectXCarchiveDir="${MacUserDir}/Library/Developer/Xcode/Archives/${BuildTimeDay}"
#xcarchive的绝对路径
ProjectXCarchive="${ProjectXCarchiveDir}/${SchemeName}${BuildTimeSecond}.xcarchive"
#ipa的目录
IpaExportDir="${MacUserDir}/Builds/XCode/${ProjectName}"
#ipa的需要的打包信息,需要手动创建,可以从已经打包出来的拷贝一下
IpaExportOptionsPath=${IpaExportDir}/ExportOptions.plist
#ipa的绝对路径
IpaDir=${IpaExportDir}/${BuildTimeDay}/${SchemeName}${BuildTimeSecond}
cd ${BuildXCodeDir}
echo "执行XCodeBuild.sh 解锁钥匙串,解锁后构建再能进行下去"
security unlock-keychain -p ${MacLoginPassword} ${MacUserDir}/Library/Keychains/login.keychain
echo "执行XCodeBuild.sh 清空构建目录"
#先清空一下构建目录
xcodebuild clean -project ${ProjectXCode} -scheme ${SchemeName}
echo "执行XCodeBuild.sh 配置版本信息"
#配置版本信息, 如果失败了,要在XCode中配置命令行工具
xcrun agvtool new-marketing-version ${APP_VERSION}
xcrun agvtool new-version -all ${BUILD_NUMBER}
echo "执行XCodeBuild.sh 构建XCarchive"
#构建XCarchive
mkdir -p ${ProjectXCarchiveDir}
xcodebuild archive -project ${ProjectXCode} -scheme ${SchemeName} -archivePath ${ProjectXCarchive}
echo "执行XCodeBuild.sh 构建IPA"
#构建ipa
mkdir -p ${IpaDir}
xcodebuild -exportArchive -exportOptionsPlist ${IpaExportOptionsPath} -archivePath ${ProjectXCarchive} -exportPath ${IpaDir}
echo "执行XCodeBuild.sh 上传IPA"
#上传ipa, 需要Jenkins里面设置的MacApiKey和MacApiIssuer
xcrun altool --upload-app -f ${IpaDir}/${SchemeName}.ipa -t ios --apiKey ${MacApiKey} --apiIssuer ${MacApiIssuer} --verbose
AndroidStudio打包Shell
echo "执行ASbuild.sh"
GradlePropertiesPath="${BuildASDir}/gradle.properties"
if [ ${IsOnline} == true ]; then Assemble="assembleRelease"; else Assemble="assembleDebug"; fi
#AndroidStudio的目录
cd ${BuildASDir}
# 修改配置, Cocos的BUG,gradle.properties的PROP_COMPILE_SDK_VERSION和PROP_TARGET_SDK_VERSION始终为-1
cat ${GradlePropertiesPath}
echo "执行CocosCreatorBuild.sh 修改启动配置"
sed -ig "s/PROP_COMPILE_SDK_VERSION=-1/PROP_COMPILE_SDK_VERSION=${AndroidApiLevel}/" ${GradlePropertiesPath}
sed -ig "s/PROP_TARGET_SDK_VERSION=-1/PROP_TARGET_SDK_VERSION=${AndroidApiLevel}/" ${GradlePropertiesPath}
sed -ig "s/RELEASE_STORE_FILE=.*/RELEASE_STORE_FILE=${AndroidKeystorePath//\//\\\/}/" ${GradlePropertiesPath}
sed -ig "s/RELEASE_STORE_PASSWORD=.*/RELEASE_STORE_PASSWORD=${AndroidKeystorePassword}/" ${GradlePropertiesPath}
sed -ig "s/RELEASE_KEY_ALIAS=.*/RELEASE_KEY_ALIAS=${AndroidKeystoreAlias}/" ${GradlePropertiesPath}
sed -ig "s/RELEASE_KEY_PASSWORD=.*/RELEASE_KEY_PASSWORD=${AndroidKeystoreAliasPassword}/" ${GradlePropertiesPath}
cat ${GradlePropertiesPath}
# echo "执行ASbuild.sh 清空构建目录"
# #先清空一下构建目录
# ./gradlew :${ProjectName}:clean
echo "执行ASbuild.sh 构建APK"
./gradlew :${ProjectName}:${Assemble} -PVERSION_CODE=${DevVersion} -PVERSION_NAME=${APP_VERSION}
- Android里面的ProjectName的build.gradle需要设置一下版本号,才能用命令行进行更改:
defaultConfig {
applicationId "xxx.xxx.xxxx"
minSdkVersion PROP_MIN_SDK_VERSION
targetSdkVersion PROP_TARGET_SDK_VERSION
versionCode project.hasProperty('VERSION_CODE') ? Integer.parseInt(VERSION_CODE) : '0.0.1'
versionName project.hasProperty('VERSION_NAME') ? String.valueOf(VERSION_NAME) : 1