jenkins+svn+android studio自动化构建(持续集成)
来源:互联网 发布:javascript生成随机数 编辑:程序博客网 时间:2024/04/30 12:52
大概的看一下,意思就是说有好几种方法下载和安装Jenkins,针对windows操作系统可以选择的方法是,下载Jenkins提供的exe直接安装,以服务的方式运行,还有一种是下载Jenkins提供的war,war文件需要通过tomcat安装,还有许多的配置项需要设置,简单起见,本文采用exe的方式进行安装,下载完成之后解压出来,运行setup.exe,安装完成之后进入控制面板->管理工具->服务就可以看到jenkins。通过http://localhost:8080/就可以进入到jenkins的web页面了,如果需要配置jenkins的工作目录,先停止jenkins服务,然后再增加环境变量JENKINS_HOME即可。
还有几个插件要安装一下,进入到系统管理->管理插件->可选插件,安装一下Email Extension Plugin(用于邮件通知)和Gradle plugin(用于gradle编译)这两个插件。安装完成之后,再配置一些信息
- 进入到系统管理->系统设置,修改系统设置
Jenkins Location标签中
系统管理员邮件地址:sender@163.com
邮件通知标签中
SMTP服务器:smtp.163.com
用户名:sender
密码:xxxxxx
SMTP端口:选中SSL填465,没选中填25
Reply-To Address:sender@163.com
字符集:UTF-8
- 项目设置
高级项目选项标签中
使用自定义的工作空间:可以配置自定义的工作空间
源码管理标签中Subversion
Repository URL: svn地址,注意这里都要填写小写的字母,否则如果真是svn路径中有大写字母的话,会导致svn版本号获取不到以及变更集获取不到
Local modle directory(optional):.
Repository depth:infinity
Check out Strategy:use 'svn update' as much as possible
构建标签中
Gradle Version:选中最新版本吧,我选的是2.9
Tasks:clean buildAll,这个是build.gradle中的任务,后面会把测试工程的build.gradle放出来
构建后操作步骤中加入Archive the artifacts,Email Notificatioin,Editable Email Notification
Archive the artifacts标签中
用于存档的文件:app/build/release/*.zip
Email Notificatioin标签中
Recipients:收件人的名字,这里是配置发送编译错误以及编译恢复邮件的收件人
Editable Email Notification标签中要增加触发器,成功后发送给Rccipient List
Project Recipient List:receiver1@163.com,receiver2@163.com,...,receivern@163.com
Project Reply-To List:sender@163.com
Content Type:HTML(text/html)
Default Subject:构建通知:$PROJECT_NAME - Build # $BUILD_NUMBER - $BUILD_STATUS!
Default Content:
(本邮件是程序自动下发的,请勿回复!)<br/>
项目名称:$PROJECT_NAME<br/>
构建编号:$BUILD_NUMBER<br/>
svn版本号:${SVN_REVISION}<br/>
构建状态:$BUILD_STATUS<br/>
触发原因:${CAUSE}<br/>
构建日志地址:<a href="${BUILD_URL}console">${BUILD_URL}console</a><br/>
构建地址:<a href="$BUILD_URL">$BUILD_URL</a><br/>
变更集:${JELLY_SCRIPT,template="html"}<br/>
这里是分割线,服务器的配置都ok了,Android Studio的工程当然也是要做一些配合才可以完成的,下面把Android Studio工程中app的build.gradle贴出来
import org.tmatesoft.svn.core.wc.*import org.tmatesoft.svn.core.wc2.*import org.tmatesoft.svn.core.*apply plugin: 'com.android.application'android { compileSdkVersion 22 buildToolsVersion "22.0.1" defaultConfig { // 包名 applicationId "com.zhb.studiotest" minSdkVersion 19 targetSdkVersion 22 versionCode 1 versionName "1.0.0.1" manifestPlaceholders = [ CHANNEL_NAME:"Unspecified",APPLICATION_LABLE:"StudioTest"] } sourceSets.main.jni.srcDirs = [] sourceSets.main.jniLibs.srcDir 'src/main/libs' def versionPropsFile = file('version.properties') if (versionPropsFile.canRead()) { def Properties versionProps = new Properties() versionProps.load(new FileInputStream(versionPropsFile)) def prename = versionProps['VERSION_NAME_MAJOR'] def name = versionProps['VERSION_NAME_BUILD'].toInteger() def runTasks = gradle.startParameter.taskNames if ('buildAll' in runTasks) { name++ } versionProps['VERSION_NAME_BUILD']=name.toString() versionProps.store(versionPropsFile.newWriter(), null) defaultConfig { versionName prename + name } } signingConfigs { releaseConfig { // 写死签名密码 keyAlias 'xxx' keyPassword 'xxxx' storeFile file("keystore.jks") storePassword 'xxxx' // 要求输入签名密码// storeFile file("keystore.jks")// keyAlias System.console().readLine("\nkeyAlias: ")// storePassword System.console().readLine("\nKeystore password: ")// keyPassword System.console().readLine("\nKey password: ") } } /*productFlavors { xiaomi { applicationId = "com.zhb.xiaomi" manifestPlaceholders = [UMENG_CHANNEL_VALUE: name,APPLICATION_LABLE:name] } baidu { applicationId = "com.zhb.baidu" manifestPlaceholders = [UMENG_CHANNEL_VALUE: name,APPLICATION_LABLE:name] } wandoujia { applicationId = "com.zhb.wandoujia" manifestPlaceholders = [UMENG_CHANNEL_VALUE: name,APPLICATION_LABLE:name] } }*/ productFlavors { wandoujia {} baidu {} //c360 {} //uc {} productFlavors.all { flavor -> applicationId = "com.zhb."+name flavor.manifestPlaceholders = [UMENG_CHANNEL_VALUE: name,APPLICATION_LABLE:name] } } buildTypes { debug { buildConfigField "boolean", "LOG_DEBUG", "true" versionNameSuffix "-debug" // 混淆开关 minifyEnabled false // 在Android中,每个应用程序中储存的数据文件都会被多个进程访问: // 安装程序会读取应用程序的manifest文件来处理与之相关的权限问题; // Home应用程序会读取资源文件来获取应用程序的名和图标; // 系统服务会因为很多种原因读取资源(例如,显示应用程序的Notification); // 此外,就是应用程序自身用到资源文件。 // 当资源文件通过内存映射对齐到4字节边界时,访问资源文件的代码才是有效率的。 zipAlignEnabled false // 删除没用的资源文件 shrinkResources false } release { buildConfigField "boolean", "LOG_DEBUG", "false" minifyEnabled true zipAlignEnabled true shrinkResources true // 混淆文件 proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' // 签名 signingConfig signingConfigs.releaseConfig applicationVariants.all { variant -> // 修改APK名称 variant.outputs.each { output -> def file = output.outputFile def fileName = file.name fileName = fileName.replace(".apk", "-V${defaultConfig.versionName}.apk") fileName = fileName.replace("app", "StudioTest") fileName = fileName.replace("debug-unaligned", "debug") output.outputFile = new File(file.parent, fileName) } // 修改values.xml variant.mergeResources.doLast(){ File valuesFile = file("${buildDir}/intermediates/res/merged/${variant.dirName}/values/values.xml") String content = valuesFile.getText('UTF-8') content = content.replaceAll("CHANNEL_NAME","${variant.productFlavors[0].name}") valuesFile.write(content,'UTF-8') } } } }}def getSvnRevision(){ ISVNOptions options = SVNWCUtil.createDefaultOptions(true); SVNClientManager clientManager = SVNClientManager.newInstance(options); SVNStatusClient statusClient = clientManager.getStatusClient(); SVNStatus status = statusClient.doStatus(project.rootDir, false); SVNRevision revision = status.getRevision(); return revision.getNumber();}task svnCommitVersionFile(){ description = "Commits a single file to an SVN repository" doLast{ if (!project.hasProperty("commitMsg")){ ext.commitMsg = "//change version" } SvnOperationFactory svnOperationFactory = new SvnOperationFactory() def authentication = SVNWCUtil.createDefaultAuthenticationManager("haibo.zhou", "hbzhou0622") svnOperationFactory.setAuthenticationManager(authentication) try { SvnCommit commit = svnOperationFactory.createCommit() commit.setSingleTarget(SvnTarget.fromFile(new File('app/version.properties'))) commit.setCommitMessage(commitMsg) SVNCommitInfo commitInfo = commit.run() println "Commit info: " + commitInfo println "Commit message: " + commitMsg } finally{ svnOperationFactory.dispose() } }}task generateZip(type: Zip){ def versionPropsFile = file('version.properties') def Properties versionProps = new Properties() versionProps.load(new FileInputStream(versionPropsFile)) def prename = versionProps['VERSION_NAME_MAJOR'] def name = versionProps['VERSION_NAME_BUILD'].toInteger() def version = "V" + prename + name + "_(" + getSvnRevision() + ")" from 'build/outputs' archiveName "StudioTest_" + version + ".zip" destinationDir file("build/release") doLast(){ copy{ from ("build/release/"+archiveName) into ("release") } if (!project.hasProperty("commitMsg")){ ext.commitMsg = "//upload compile result" } SvnOperationFactory svnOperationFactory = new SvnOperationFactory() def authentication = SVNWCUtil.createDefaultAuthenticationManager("haibo.zhou", "hbzhou0622") svnOperationFactory.setAuthenticationManager(authentication) try { SvnScheduleForAddition add = svnOperationFactory.createScheduleForAddition(); SvnTarget target = SvnTarget.fromFile(new File("app/release/"+archiveName)); add.addTarget(target); add.setAddParents(true); add.setForce(true); add.run(); SvnCommit commit = svnOperationFactory.createCommit() commit.setSingleTarget(SvnTarget.fromFile(new File("app/release/"+archiveName))) commit.setCommitMessage(commitMsg) SVNCommitInfo commitInfo = commit.run() println "Commit info: " + commitInfo println "Commit message: " + commitMsg } finally{ svnOperationFactory.dispose() } }}// build script for jenkins onlytask buildAll(){ println 'start build'}svnCommitVersionFile.dependsOn buildgenerateZip.dependsOn svnCommitVersionFilebuildAll.dependsOn generateZiptasks.withType(JavaCompile) { compileTask -> compileTask.dependsOn ndkBuild}task ndkBuild(type: Exec) { workingDir file('src/main/jni') commandLine getNdkBuildCmd()}task cleanNative(type: Exec){ workingDir file('src/main/jni') commandLine getNdkBuildCmd(), 'clean'}clean.dependsOn cleanNativedef getNdkDir() { if (System.env.ANDROID_NDK_ROOT != null) return System.env.ANDROID_NDK_ROOT Properties properties = new Properties() properties.load(project.rootProject.file('local.properties').newDataInputStream()) def ndkdir = properties.getProperty('ndk.dir', null) if (ndkdir == null) throw new GradleException("NDK location not found. Define location with ndk.dir in the local.properties file or with an ANDROID_NDK_ROOT environment variable.") return ndkdir}def getNdkBuildCmd() { def ndkbuild = getNdkDir() + "/ndk-build" ndkbuild += ".cmd" return ndkbuild}dependencies { // 工程目录里面的libs文件夹下所有的jar包 compile fileTree(dir: 'libs', include: ['*.jar']) // 网络仓库里面的工程 //compile 'com.github.chrisbanes.photoview:library:1.2.4' // 本地的工程 compile project(':PhotoView-master')}
大概描述一下脚本,在控制台运行gradle buildAll,将会把build/output目录打成压缩生成到build/release目录,并自动修改版本号文件version.property提交到svn,同时将编译结果提交到svn。
ok,在到我们的jenkins里面,编译一下,结果生成了,看一下我们收到的邮件
<span style=
"font-size: 14px;"
> 编译日志,编译结果,上一次构建到这次构建的svn提交记录都可以看到了,作为一个简单的持续集成环境还是可以的。<br><br><br></span>
2016.01.16
- jenkins+svn+android studio自动化构建(持续集成)
- Windows环境下jenkins +svn+android studio自动化构建(持续集成,打包)
- Windows环境下jenkins +svn+android studio自动化构建(持续集成,打包)
- selenium+robot+svn+jenkins自动化测试系列二:Jenkins配置自动化持续集成构建
- Jenkins 持续集成实现 Android 自动化打包
- Jenkins 持续集成构建
- 【mac+Android Studio】搭建Jenkins+svn+Android Studio持续集成环境
- 【mac+Android Studio】【持续集成优化】搭建Jenkins+svn+Android Studio+发布到蒲公英+发邮件
- NT_iOS笔记—持续集成Jenkins(自动化构建打包)
- 持续集成——使用Jenkins配置自动化构建
- Jenkins搭建Egret H5开发的自动化构建(持续集成)
- Jenkins+SVN+AndoriodStudio自动打包(自动化持续构建)
- selenium+testng+gitblit+jenkins+ant自动化测试系列十:Jenkins配置自动化持续集成构建
- RF+Jenkins构建持续集成
- 基于Jenkins的Android持续集成(自动化打包)
- Windows下Android项目搭建Jenkins持续构建+自动化测试
- Windows下Android项目搭建Jenkins持续构建+自动化测试
- Windows下Android项目搭建Jenkins持续构建+自动化测试
- java log4j 详细教程
- Session的原理
- USB Camera V4L2 视频录制——ubuntu(1)
- iOS使用HHealthKit读取修改健康步数
- 守护进程
- jenkins+svn+android studio自动化构建(持续集成)
- Git-GitHub搭建远程仓库
- 牛客网 8.2 网易2017校招 Java 第一题 下厨房
- js CORS
- springmvc整合mybatis框架源码
- 【Akka】Akka入门编程实例
- 9i 数据库Monitoring(转载)
- U盾的原理
- 数据结构 分别用递归和非递归方法实现二叉树先序,中序,后序遍历