前言
本文主要介绍在android studio中使用artifactory进行maven配置的最终方案,具体过程及工作原理可参考 android studio的maven私服使用配置踩坑实录 中的介绍
本文不介绍MAVEN + JENKINS + ARTIFACTORY整合的具体内容,有兴趣的同学可通过 上一篇文章 中的传送门了解更多
以下为正文
涉及到的文件
- 各module的build.gradle
按maven方式依赖lib module,如:
//v_lib_db 在gradle.properties
compile "com.xiwei.commonlib:lib_db:${v_lib_db}"
以下文件均在android studio 工程的根目录
- artifactory.gradle(新建)
- artifactory_version.properties (新建)
- build.gradle
- deploy.sh(新建)
- modify.sh(新建)
- deploy.bat(新建)
- modify.bat(新建)
- gradle.properties
文件内容
artifactory.gradle
allprojects {
repositories {
maven { url 'http://repo.jfrog.org/artifactory/gradle-plugins' }
maven{
url 'http://192.168.199.119:8080/artifactory/libs-release-local'
}
maven{
url 'http://192.168.199.119:8080/artifactory/libs-snapshot-local'
}
}
}
def SNAPSHOT_MAVEN_TYPE = 'snapshot'
subprojects {
//artifactory相关
apply plugin: 'com.jfrog.artifactory'
apply plugin: 'maven-publish'
//读取module的version
def Properties props = new Properties()
File propFile = file(file("temp").parentFile.parentFile.absolutePath + "/artifactory_version.properties");
if (propFile.exists()) {
props.load(new FileInputStream(propFile))
}
def myGroupId = 'com.xiwei.commonlib'
def maven_type = props.getProperty("maven_type")
ext{
//定义该module是否进行deploy
deploy = true //若project不需要deploy到maven上,在project的build.gradle中添加代码:project.ext.deploy = false
versionType = maven_type == SNAPSHOT_MAVEN_TYPE ? '-SNAPSHOT' : ''
}
publishing {
publications {
aar(MavenPublication) {
if (!project.hasProperty('android') || !project.ext.deploy)
return
def libVersion = "${props.getProperty(project.name)}${versionType}"
println("${project.getName()}:${libVersion}")
groupId myGroupId
version = libVersion
artifactId project.getName()
// Tell maven to prepare the generated "*.aar" file for publishing
artifact("${buildDir}/outputs/aar/${project.getName()}-release.aar")
//The publication doesn't know about our dependencies, so we have to manually add them to the pom
pom.withXml {
//Creating additional node for dependencies
def dependenciesNode = asNode().appendNode('dependencies')
//Defining configuration names from which dependencies will be taken (debugCompile or releaseCompile and compile)
def configurationNames = ["releaseCompile", 'compile']
configurationNames.each { configurationName ->
project.configurations.getByName(configurationName).allDependencies.each {
if (it.group != null && it.name != null) {
def dependencyNode = dependenciesNode.appendNode('dependency')
dependencyNode.appendNode('groupId', it.group)
dependencyNode.appendNode('artifactId', it.name)
dependencyNode.appendNode('version', it.version)
//If there are any exclusions in dependency
if (it.excludeRules.size() > 0) {
def exclusionsNode = dependencyNode.appendNode('exclusions')
it.excludeRules.each { rule ->
def exclusionNode = exclusionsNode.appendNode('exclusion')
exclusionNode.appendNode('groupId', rule.group)
exclusionNode.appendNode('artifactId', rule.module)
}
}
}
}
}
}
}
}
}
artifactory {//artifactory配置
contextUrl = "${artifactory_contextUrl}" //The base Artifactory URL if not overridden by the publisher/resolver
publish {
repository {
repoKey = maven_type == SNAPSHOT_MAVEN_TYPE ? 'libs-snapshot-local' : 'libs-release-local'
username = "${artifactory_user}"
password = "${artifactory_password}"
maven = true
}
defaults {
skip = !(project.ext.deploy)
// Tell the Artifactory Plugin which artifacts should be published to Artifactory.
publications('aar')
publishArtifacts = true
// Properties to be attached to the published artifacts.
properties = ['qa.level': 'basic', 'dev.team': 'core']
// Publish generated POM files to Artifactory (true by default)
publishPom = true //Publish generated POM files to Artifactory (true by default)
publishIvy = false //Publish generated Ivy descriptor files to Artifactory (true by default)
}
}
}
}
artifactory_version.properties
##############################################################################
#
# 打包设置信息
# 开发环境下,maven_type为snapshot
# 测试&正式环境下,maven_type为release
# module升级版本时,依赖该module的module也要升级版本
#
# 开发者进行版本升级发布只需要更新这个文件即可
# 发布单个module:
# 升级模块名称对应的版本号(注:snapshot发布不需要更新版本,直接调用./deploy.sh 模块名称)
# ./deploy.sh 模块名称 如:./deploy.sh lib_db
#
# 发布所有module:
# 升级所有需要升级的module对应的版本号
# ./deployAll.sh
##############################################################################
#发布的类型:snapshot/release
maven_type=snapshot
#lib升级版本时,要
lib_utils=1.0.0
#...others
lib_xiwei_common=1.0.5
build.gradle
// Top-level build file where you can add configuration options common to all sub-projects/modules.
apply from: "artifactory.gradle"
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:2.1.0'
//artfactory plugin need
classpath(group: 'org.jfrog.buildinfo', name: 'build-info-extractor-gradle', version: '4.1.1')
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
jcenter()
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
deploy.sh
#!/bin/sh
#================================================================================================
# usage:
# 发布所有module: ./deploy.sh -a
# 发布单个module: ./deploy.sh lib_db
# 注:
# 1. 从release版到snapshot发布时,需要修改artifactory_version.properties的类型为snapshot,反之亦然
# 2. snapshot版本更新时,无需更新版本号,直接deploy即可
#================================================================================================
function deploy() {
#按照artifactory_version.properties里配置的版本进行发布
./gradlew :$1:clean :$1:assembleRelease :$1:artifactoryPublish
#将gradle.properties里的版本改成与artifactory_version.properties里的配置一致
ROOT=${PWD}
./modify.sh $1 $ROOT/
}
param=$1
if [[ ${param} = '-a' ]]; then
#发布所有module到maven
#注意依赖顺序:被依赖的要放在前面
deploy lib_utils
#...others
deploy lib_xiwei_common
else
deploy $1
fi
modify.sh
#!/bin/sh
#################################################################################
#
# 从一个文件中读取配置,并替换另一个文件中对应的配置项
# usage: ./modify lib_db
# 效果为:将build.gradle的v_lib_db=1.0.0 替换为 v_lib_db=1.0.1
#
#################################################################################
#project的版本定义文件
SOURCE_FILE_NAME="artifactory_version.properties"
#dependencies的版本定义文件
GRADLE_FILE_NAME=$2"gradle.properties"
#从SOURCE_FILE_NAME的key到GRADLE_FILE_NAME的key需要添加的前缀:比如:lib_db -> v_lib_db 前缀为 v_
KEY_PRE_FIX="v_"
function contains
{
STRING_A=$1
STRING_B=$2
if [[ ${STRING_A/${STRING_B}//} == $STRING_A ]]
then
return 0
else
return 1
fi
}
function replace_prop() {
KEY=$1
VALUE=$2
SUFFIX=''
if [[ ${maven_type} = 'snapshot' ]]; then
SUFFIX='-SNAPSHOT'
fi
cat $GRADLE_FILE_NAME | while read LINE
do
contains $LINE "$KEY_PRE_FIX$KEY="
result=$?
if [[ $result = 1 ]]; then
#包含$KEY_PRE_FIX$2=的行内容替换为v_$2=$3
sed -ig "s/$LINE/$KEY_PRE_FIX$KEY=$VALUE$SUFFIX/g" ${GRADLE_FILE_NAME}
rm -f ${GRADLE_FILE_NAME}g
return
fi
done
}
#读取需要拷贝的properties文件
. ${SOURCE_FILE_NAME}
#todo check params
#替换GRADLE_FILE_NAME文件中key为$1的行内容:例如v_lib_db=1.0.0 -> v_lib_db=1.0.1
replace_prop $1 ${!1}
deploy.bat
@echo off
REM ** edit common libs dependencies ***
set ROOT=%cd%
if /i "%1"=="-a" (
call:deploy lib_utils
rem ...others
call:deploy lib_xiwei_common
goto :eof
) else (
call:deploy %1
goto :eof
)
:deploy
call gradlew :%1:clean :%1:assembleRelease :%1:generatePomFileForAarPublication :%1:artifactoryPublish
call %~dp0modify.bat %1 %ROOT%
goto :eof
modify.bat
@echo off
setlocal enabledelayedexpansion
SET ROOT=%~dp0
SET CONFIG_FILE=%ROOT%artifactory_version.properties
SET GRADLE_PATH=%2
SET GRADLE_FILE_NAME=%GRADLE_PATH%gradle.properties
SET TEMP=%GRADLE_PATH%tmp.properties
SET KEY_PRE_FIX=v_
FOR /F "tokens=1,2 delims==" %%i in (%CONFIG_FILE%) DO (
SET %%i=%%j
)
set SUFFIX=
if /i "%maven_type%"=="snapshot" (
set SUFFIX=-SNAPSHOT
)
call:replace_prop %1 !%1!
goto :eof
:replace_prop
set KEY=%KEY_PRE_FIX%%~1=
set VALUE=%~2
set /a index=0
del /f /s /q /a %TEMP%
for /f "delims=" %%a in ('findstr /n .* %GRADLE_FILE_NAME%') do (
set /aindex=!index! + 1
set "str=%%a"
set contains=false
echo !str!|find "%KEY%">nul&&set contains=true
if /i "!contains!"=="true" (
echo %KEY%%VALUE%%SUFFIX%>>%TEMP%
) else (
if !index! gtr 99 (
echo.!str:~4!>>%TEMP%
) else (
if !index! gtr 9 (
echo.!str:~3!>>%TEMP%
) else (
echo.!str:~2!>>%TEMP%
)
)
)
)
del %GRADLE_FILE_NAME%
ren %TEMP% gradle.properties
goto :eof
gradle.properties
artifactory_user=yourusername
artifactory_password=yourpassword
artifactory_contextUrl=http://192.168.199.119:8080/artifactory
v_lib_utils=1.0.0
#...others
v_lib_xiwei_common=1.0.5
使用方式
- module修改后,artifactory_version.properties中对应module及传递依赖的module要进行升级,并将maven_type改为snapshot进行发布
- 测试验收结束后,maven_type改为release进行发布(调用)
- 发布命令
- 发布单个module:
- mac:
./deploy.sh moduleName
- windows:
deploy.bat moduleName
- mac:
- 发布当前工程中的所有module:
- mac:
./deploy.sh -a
- windows:
deploy.bat -a
- mac:
- 发布单个module:
2016-07-14添加
在实际使用中发现还是不够方便:
- module之间存在依赖关系时,发生修改后需要手动deploy改动的module和所有直接/间接依赖该module的所有module
- 用这种方式将工程从之前的module依赖改为maven依赖的过程比较费时
- 同时维护shell脚本和batch脚本成本较大
为了解决这些问题,做了以下改动:
- 添加自动deploy直接/间接依赖当前发布脚本的所有module的功能,从而实现一键deploy
- 提供自动按照依赖关系顺序deploy all的功能
- shell脚本和batch脚本的功能用python脚本来实现
demo传送门:Android studio基于artifactory的maven私服一键deploy工具
原文地址:http://blog.youkuaiyun.com/cdecde111/article/details/51777427