很多关于Jenkins的Android的构建,基本都是用gradle构建整个项目的。但是模块化后,不同模块就存在不同项目里,即不同的git地址。而且,上传代码的时候,只会上传模块的源代码,不会上传根目录
下的配置文件,如: gradle.properties
,build.gradle
, local.properties
,settings.gradle
等等。
这里就讲讲,当拆成一个个module后,我们是如何使用Jenkins进行自动构建的。分为一、二两篇,分别讲library的构建和app的构建。
前提条件:
1、在主机上安装上Jenkins
, jdk
,gradle
, Android sdk
;
2、在主机上搭建自己的maven私服
首先本文先说说子模块library的构建。
一、子模块library的构建
1、首先给出子模块的build.gradle
示例:
apply plugin: 'com.android.library'
version = '1.1.5'
description = 'shop chat library'
ext.pom_packaging = 'aar'
ext.pom_groupId = 'com.showjoy.shop'
ext.pom_artifactId = 'chat'
ext.pom_name = 'shopandroid_chat'
ext.pom_snapshot = false
android {
useLibrary 'org.apache.http.legacy'
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile('com.showjoy.shop:common:1.7.7')
compile('com.showjoy.shop:webview:1.2.1')
compile 'com.android.support:appcompat-v7:24.0.0'
}
apply from: System.properties['libraryBaseGradle']
以上的配置,打包的结果会生成 shopandroid_chat-release-1.1.5.aar
,然后自动上传到maven仓库。这样简单的配置,把共同的gradle代码都封装到了 libraryBaseGradle
里,每个模块的 build.gradle
都依赖它,然后只要配置自己的 dependencies
和模块的 名称和版本信息
即可。
构建完成后,在其他模块里依赖即可使用:
compile 'com.showjoy.shop:chat:1.1.5'
当然需要在project 根目录的build.gradle配置上自己的maven 私服地址:
allprojects {
repositories {
maven {url 'http://192.168.0.62:8081/repository/maven-releases/'}
maven {url 'http://192.168.0.62:8081/repository/maven-snapshots/'}
jcenter()
mavenCentral()
}
}
2、libraryBaseGradle.gradle
封装的共同配置还是要看 System.properties['libraryBaseGradle']
这个参数配置的gradle文件,这个参数在project 根目录下的gradle.properties
:
示例如下:
systemProp.compileSdkVersion=23
android.useDeprecatedNdk=true
org.gradle.daemon=true
org.gradle.parallel=true
systemProp.buildToolsVersion=23.0.2
systemProp.targetSdkVersion=21
org.gradle.jvmargs=-XX\:MaxPermSize\=4096m
org.gradle.configureondemand=true
systemProp.minSdkVersion=14
systemProp.scheme=showjoyshop
systemProp.libraryBaseGradle=http://git.xxxxxx.com/android/mvn-repo/raw/master/library.gradle
而http://git.xxxxxx.com/android/mvn-repo/raw/master/library.gradle
的内容如下:
apply plugin: 'com.android.library'
apply plugin: 'maven'
android {
compileSdkVersion Integer.parseInt(System.properties['compileSdkVersion'])
buildToolsVersion System.properties['buildToolsVersion']
defaultConfig {
minSdkVersion Integer.parseInt(System.properties['minSdkVersion'])
targetSdkVersion Integer.parseInt(System.properties['targetSdkVersion'])
}
lintOptions {
abortOnError false
}
libraryVariants.all {
variant ->
variant.outputs.each {
output ->
def outputFile = output.outputFile
if (outputFile != null && outputFile.name.endsWith('.aar')) {
def fileName = outputFile.name.replace(".aar", "-" + version + ".aar")
output.outputFile = new File(outputFile.parent, fileName)
}
}
}
uploadArchives {
repositories {
mavenDeployer {
if (pom_snapshot) {
repository (url: 'http://192.168.0.62:8081/repository/maven-snapshots/') {
authentication(userName: 'admin', password: 'xxxxxx')
}
version = version + '-SNAPSHOT'
} else {
repository (url: 'http://192.168.0.62:8081/repository/maven-releases/') {
authentication(userName: 'admin', password: 'xxxxxx')
}
}
pom.version = version
pom.artifactId = pom_artifactId
pom.groupId = pom_groupId
pom.name = pom_name
pom.packaging = pom_packaging
pom.project {
description description
dependencies {
project.configurations.collectMany { it.allDependencies }
.findAll { it instanceof ProjectDependency ||
it instanceof ExternalModuleDependency}
.each { dep ->
dependency {
groupId dep.getGroup()
artifactId dep.getName()
version dep.getVersion()
scope 'compile'
}
}
}
}
}
}
}
}
3、Jenkins的配置
在Jenkins上正常new item,基本信息配置没有什么特别,按照自己需要填写即可,主要讲三个注意点:
-
git地址的配置
虽然后面构建的时候没有用到这里的配置,但是这里的配置作用在于每次构建能检查到changes
-
build部分,如图:
这里,使用了Python脚本进行构建
python ${JENKINS_HOME}/workspace/publish/jenkins/library/build.py ${JOB_NAME} "git@git.showjoy.net:shopandroid/shopandroid_chat.git"
其中,${JENKINS_HOME}/workspace/publish/jenkins/library/build.py
是构建脚本放置在主机上的路径,${JENKINS_HOME}
表示Jenkins的安装目录。后面跟了两个参数,参数一:job 名称${JOB_NAME}
,参数二:项目git地址
-
构建结果处理
这里配置的目的在于每次构建完成后,能知道是否构建成功了,以及构建的版本,如:
4、构建脚本build.py
-
整体的思路就是新建一个目录sourcecode,然后将project根目录下需要的文件(
setting.gradle
,build.gradle
,gradle.properties
,gradlew
,local.properties
)从指定目录复制到sourcecode。其中注意local.properties
配置的sdk路径需要是主机上sdk的安装目录。 -
然后动态修改
setting.gradle
只包含当前library的module name,然后clone library的代码到sourcecode,然后用gradle clean build uploadArchives
构建。
代码如下:
#coding:utf-8
OUTPUTS_PATH = "/var/lib/jenkins/workspace/"
GRADL_HOME = "/root/gradle-2.10/bin/"
SOURCE_CODE = "sourcecode"
MODULE_NAME = "shopandroid"
BRANCH = "master"
def copyFiles(sourceDir, targetDir): #把某一目录下的所有文件复制到指定目录中
for file in os.listdir(sourceDir):
sourceFile = os.path.join(sourceDir, file)
targetFile = os.path.join(targetDir, file)
if os.path.isfile(sourceFile):
if not os.path.exists(targetDir):
os.makedirs(targetDir)
if not os.path.exists(targetFile) or(os.path.exists(targetFile) and (os.path.getsize(targetFile) != os.path.getsize(sourceFile))):
open(targetFile, "wb").write(open(sourceFile, "rb").read())
if os.path.isdir(sourceFile):
First_Directory = False
copyFiles(sourceFile, targetFile)
def chdir(dir):
os.chdir(dir)
print ('当前目录:' + os.getcwd())
def getVersionName(path):
import re
versionName = ""
f = open(path)
for line in f:
searchObj = re.search( r'version(\s*)=(\s*)\'(.*)\'', line, re.M|re.I)
if searchObj:
versionName = searchObj.group(3)
break
return versionName
if __name__ == "__main__":
import shutil
import sys
import os
content = "n"
print sys.path[0]
chdir(sys.path[0])
import time
start_time = time.time()
print ('start time %f' %start_time)
# 开始读取参数
if len(sys.argv) < 2:
print "构建脚本 参数不够2个,第0个是脚本路径,第1个是git地址"
exit()
#项目名称
OUTPUTS_PATH = OUTPUTS_PATH + sys.argv[1] + "/outputs"
if (os.path.exists(OUTPUTS_PATH)):
shutil.rmtree(OUTPUTS_PATH)
# 代码
git_path = sys.argv[2]
# 第2个可以是分支
if len(sys.argv) >= 4:
BRANCH = sys.argv[3]
pass
print ('代码地址:' + git_path + ",分支:" + BRANCH)
import re
MODULE_NAME = re.search(r'/(.*)\.git', git_path).group(1)
print ('项目名称:' + MODULE_NAME)
# clone代码
SOURCE_CODE = MODULE_NAME;
if os.path.exists(SOURCE_CODE):
shutil.rmtree(SOURCE_CODE)
os.mkdir(SOURCE_CODE)
chdir(SOURCE_CODE)
print ('start to clone codes')
clone_command = "/usr/bin/git clone -b " + BRANCH + " " + git_path
print clone_command
print os.system(clone_command)
# 复制gradle配置文件
chdir(os.path.dirname(os.getcwd()))
print ('copy files from gradle_config to ' + SOURCE_CODE)
copyFiles('../gradle_config', SOURCE_CODE)
# 进入library目录,开始编译
chdir(SOURCE_CODE)
# 修改setting.gradle
settingFile = open('settings.gradle', "wb")
print settingFile.write("include '" + MODULE_NAME + "'")
print settingFile.close()
chdir(MODULE_NAME)
print ('start to build library')
output = os.popen(GRADL_HOME + "gradle clean build uploadArchives")
# 读取版本号
versionName = getVersionName("build.gradle")
print ("版本号为:" + versionName)
buildResult = False
outputLog = output.read()
copyFiles("build/outputs", OUTPUTS_PATH)
chdir(OUTPUTS_PATH)
if "BUILD SUCCESSFUL" in outputLog:
f = open( versionName + '.txt','w')
f.write(outputLog)
f.close()
buildResult = True
pass
print outputLog
end_time = time.time()
cost_time = (end_time - start_time)
minutes = cost_time/60
seconds = cost_time - 60 * minutes
print ('cost time : %d mins %d secs' %(minutes, seconds))
import sys
if False == buildResult:
sys.exit(-1)
pass
赏一个 您的支持是对我最大的鼓励。加班再忙,也要熬夜继续码字分享! 码字辛苦 赏个五毛 支持: 微信支付 支付宝
好人一生平安 谢谢!
微信支付 支付宝
用 [微信] 扫描二维码打赏

用 [支付宝] 扫描二维码打赏