很多关于Jenkins的Android的构建,基本都是用gradle构建整个项目的。但是模块化后,不同模块就存在不同项目里,即不同的git地址。而且,上传代码的时候,只会上传模块的源代码,不会上传根目录下的配置文件,如: gradle.propertiesbuild.gradlelocal.propertiessettings.gradle等等。

这里就讲讲,当拆成一个个module后,我们是如何使用Jenkins进行自动构建的。分为一、二两篇,分别讲library的构建和app的构建。

前提条件:

1、在主机上安装上JenkinsjdkgradleAndroid 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地址的配置

-1484068595630.png

虽然后面构建的时候没有用到这里的配置,但是这里的配置作用在于每次构建能检查到changes

-1484068929404.png

  • build部分,如图:

    -1484068522067.png

    这里,使用了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地址


  • 构建结果处理

-1484068861964.png

这里配置的目的在于每次构建完成后,能知道是否构建成功了,以及构建的版本,如:

-1484068911160.png

4、构建脚本build.py

  • 整体的思路就是新建一个目录sourcecode,然后将project根目录下需要的文件(setting.gradle,build.gradle,gradle.propertiesgradlew,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


标签: none

评论已关闭