Skip to content

Commit

Permalink
ci: 基于GIT版本进行版本管理
Browse files Browse the repository at this point in the history
  • Loading branch information
liyujiang-gzu committed Jul 15, 2020
1 parent 8517aab commit edee22f
Show file tree
Hide file tree
Showing 8 changed files with 158 additions and 64 deletions.
12 changes: 8 additions & 4 deletions .github/workflows/gradle-publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,11 @@ jobs:

- name: Grant execute permission for gradlew
run: chmod +x gradlew
- name: Publish to maven local
run: ./gradlew build publishToMavenLocal --warning-mode all


- name: Build with Gradle
run: ./gradlew build
#- name: Publish to maven local
# run: ./gradlew publishToMavenLocal --warning-mode all
- name: Publish to GitHub Packages
env:
TOKEN: ${{ secrets.TOKEN }}
run: ./gradlew publishReleasePublicationToGitHub --warning-mode all
57 changes: 42 additions & 15 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ android {

defaultConfig {
multiDexEnabled false
applicationId appPackageName
//按不同维度打包,必须添加,不添加编译不通过,后面的数值任何字符串都可以
flavorDimensions "MODE", "CHANNEL"
signingConfigs {
//直接使用真实的密钥库文件,避免微信、高德地图等第三方SDK校验失败
releaseConfig {
Expand Down Expand Up @@ -61,34 +62,45 @@ android {
keyAlias signingKeyAlias
keyPassword signingKeyPassword
v1SigningEnabled true
// 注:直接在IDE里运行APP,启用V2签名的话生成的APK里不会有签名信息的
// 注:直接在IDE里运行APP,启用V2签名的话生成的APK里可能不会有签名信息的
v2SigningEnabled true
}
}
}
//按不同维度打包,必须添加,不添加编译不通过,后面的数值任何字符串都可以
flavorDimensions "MODE"
// 修改 AndroidManifest.xml 里的变量,占位值无法覆盖的坑可参阅 https://www.jianshu.com/p/1d5271c2c366
manifestPlaceholders = [
MY_CHANNEL: "default",
MY_CHANNEL: "unknown",
]
buildConfigField "String", "BUILD_DATE", '"' + new Date().format("yyyy.MM.dd HH:mm:sss") + '"'
}

// 打包纬度,会按纬度名称字母顺序执行
// 打包维度列表,会按维度名字母顺序执行,最终发布的具体渠道包的生成可以借助360加固等工具修改
productFlavors {
// 开发模式/测试环境
developer {
dimension "MODE"
// 环境信息
buildConfigField "String", "ENVIRONMENT", '"dev"'
// 修改 AndroidManifest.xml 里的变量
manifestPlaceholders = [
MY_CHANNEL: "developer",
]
}
// 发布模式/正式环境
publisher {
dimension "MODE"
// 环境信息
buildConfigField "String", "ENVIRONMENT", '"prod"'
// 修改 AndroidManifest.xml 里的变量
manifestPlaceholders = [
MY_CHANNEL: "publisher",
]
buildConfigField "String", "ENVIRONMENT", '"pub"'
}
developer {
dimension "MODE"
// 官方发布渠道
official {
dimension "CHANNEL"
manifestPlaceholders = [
MY_CHANNEL: "developer",
MY_CHANNEL: "official",
]
buildConfigField "String", "ENVIRONMENT", '"dev"'
}
}

Expand Down Expand Up @@ -120,19 +132,32 @@ android {

}

// 批量处理渠道
println "********** product flavors **********"
android.productFlavors.all { flavor ->
String channelName = flavor.name
println "flavor name is $channelName"
//替换AndroidManifest.xml中的默认值
flavor.manifestPlaceholders = [
MY_CHANNEL: channelName,
]
}

//APK重命名
println "********** apk outputs **********"
android.applicationVariants.all { variant ->
variant.outputs.all {
if (variant.buildType.name == 'debug') {
//debug版本不重定义输出目录,也不重命名
return
}
if (outputFileName != null && outputFileName.endsWith(".apk")) {
def versionCode = android.defaultConfig.versionCode
def versionName = android.defaultConfig.versionName
String fileName = "${outputFile.name.replace('-release.apk', '')}-v${versionName}-built${versionCode}.apk"
def versionName = rootProject.getGitLatestTag();
def date = new Date().format("yyyyMMddHHmm", TimeZone.getTimeZone("GMT+08:00"))
String fileName = "${outputFile.name.replace('-release.apk', '')}-v${versionName}-${date}.apk"
//这里只能用相对路径,不然报错
outputFileName = new File(fileName)
println "outputFile=$outputFile"
}
}
//APK构建完成后,备份release版本到指定目录
Expand All @@ -154,6 +179,8 @@ android.applicationVariants.all { variant ->
from outputFile
into targetDir
}
File copyOutputFile = new File(targetDir, outputFile.name)
println "copyOutputFile=$copyOutputFile"
}
}
}
Expand Down
59 changes: 57 additions & 2 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ buildscript {
dependencies {
classpath 'com.android.tools.build:gradle:4.0.0'
classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.8.5'
classpath "com.tencent.mm:AndResGuard-gradle-plugin:${appResGuardVersion}"
classpath "com.tencent.mm:AndResGuard-gradle-plugin:${andResGuardVersion}"
}
}

Expand Down Expand Up @@ -39,7 +39,7 @@ subprojects {
}

task clean(type: Delete) {
println("********** delete all compile **********")
println("********** clean build **********")
println("delete project dir:" + rootProject.buildDir)
rootProject.buildDir.deleteDir()
def dir = new File(new File(".").getAbsolutePath())
Expand All @@ -53,3 +53,58 @@ task clean(type: Delete) {
}
}
}

@SuppressWarnings(["GrMethodMayBeStatic", "unused"])
def gitGitCommitNumber() {
try {
// See https://www.jianshu.com/p/1f81af606e41
def cmd = 'git rev-list HEAD --first-parent --count'
return cmd.execute().text.trim().toInteger()
} catch (ignored) {
return 1
}
}

@SuppressWarnings(["GrMethodMayBeStatic", "unused"])
def getGitLatestTag() {
try {
// See https://www.jianshu.com/p/1f81af606e41
def cmd = 'git describe --tags'
return cmd.execute().text.trim()
} catch (ignored) {
return "1.0.0"
}
}

@SuppressWarnings(["GrMethodMayBeStatic", "unused"])
def getGitBranch() {
try {
// See https://www.jianshu.com/p/1f81af606e41
def cmd = 'git symbolic-ref --short -q HEAD'
return cmd.execute().text.trim()
} catch (ignored) {
return "unknown"
}
}

@SuppressWarnings(["GrMethodMayBeStatic", "unused"])
def getGitLatestCommitHash() {
try {
// See https://www.cnblogs.com/fuyaozhishang/p/7675551.html
def cmd = 'git rev-parse HEAD'
return cmd.execute().text.trim()
} catch (ignored) {
return "unknown"
}
}

@SuppressWarnings(["GrMethodMayBeStatic", "unused"])
def getGitLatestCommitHashShort() {
try {
// See https://www.jianshu.com/p/1f81af606e41
def cmd = 'git rev-parse --short HEAD'
return cmd.execute().text.trim()
} catch (ignored) {
return "unknown"
}
}
30 changes: 15 additions & 15 deletions docs/index.md
Original file line number Diff line number Diff line change
@@ -1,25 +1,23 @@
# 安卓项目工程模板

[![Release APK](https://github.com/gzu-liyujiang/AliyunGradleConfig/workflows/Release%20APK/badge.svg)](https://github.com/gzu-liyujiang/AliyunGradleConfig/actions)
[![Gradle Package](https://github.com/gzu-liyujiang/AliyunGradleConfig/workflows/Gradle%20Package/badge.svg)](https://github.com/gzu-liyujiang/AliyunGradleConfig/actions)
[![MulanPSL](https://img.shields.io/badge/license-MulanPSL-blue.svg)](http://license.coscl.org.cn/MulanPSL)
[![Anti-996](https://img.shields.io/badge/license-Anti%20996-blue.svg)](https://github.com/996icu/996.ICU/blob/master/LICENSE)

- 阿里云远程仓库加速
- 发布到Maven仓库
- 发布到Maven仓库:Github Packages、Jitpack、Jcenter Bintray
- 代码混淆、资源混淆
- 多维度打包APK
- 多维度打包APK:区分测试环境及线上环境
- 自动化工作流:Github Actions
- 依赖冲突解决

### 项目模板文件介绍

- .github/workflows/gradle-publish.yml 基于GithubActions及GithubPackages进行打包发布
- .gitignore 通用的GIT版本控制文件忽略规则
- build.gradle Gradle项目构建管理
- build.gradle 项目构建管理
- gradle.properties 通用的项目配置
- app/proguard-common.pro 通用的混淆规则
- app/build.gradle 多维度打包APK
- gradle/publish.gradle Gradle项目发布到Maven仓库及上传到jcenter
- gradle/resguard.gradle Gradle项目资源文件混淆配置管理
- app/build.gradle 通用的APK打包
- gradle/common.gradle 通用的项目配置
- gradle/publish.gradle 项目发布到Maven仓库及上传到jcenter
- gradle/resguard.gradle 项目资源文件混淆配置管理

在天朝使用jcenter、mavenCentral及google三个远程仓库,Gradle Sync会很慢,google仓库甚至需要[科学上网](https://github.com/hugetiny/awesome-vpn)才能访问。为了加快Gradle Sync速度,一招教你优先用 [阿里云仓库服务](https://maven.aliyun.com/mvn/view) 的仓库作为下载源。

Expand Down Expand Up @@ -102,36 +100,38 @@ allprojects {

### 项目发布到Maven仓库

手动执行命令`gradlew publishToMavenLocal`可以发布到`mavenLocal()`,手动执行命令`gradlew bintrayPublish`可以发布到`jcenter()`。项目发布到`jitpack`前,需要基于某个`git commit`创建相应发布版本的`tag`,推送该`tag`才会触发`jitpack`的构建。
手动执行命令`gradlew publishToMavenLocal`可以发布到`mavenLocal()`,手动执行命令`gradlew bintrayUpload`可以发布到`jcenter()`。项目发布到`jitpack`前,需要基于某个`git commit`创建相应发布版本的`tag`,推送该`tag`才会触发`jitpack`的构建。

- 项目发布到`jitpack`,需要使用github账号[登录到JitPack](https://jitpack.io)`Look up`相应的库然后去`Get it`
- 项目发布到`jcenter`,需要[登录到Bintray](https://bintray.com/login)后选择`maven`创建相应应的包(Add a Package)。
- 修改`publish.gradle`中的以下下信息为您自己的:

```groovy
//项目相关信息
def includeJar = false
def pomLibGroupName = 'com.github.gzuliyujiang'
def pomLibArtifactId = rootProject.name
def pomLibVersion = new Date().format("yyyy.M.d")
def pomLibVersion = rootProject.getGitLatestTag()
def pomLibDescription = "TODO description: ${rootProject.name} for Android"
def pomSiteUrl = "https://github.com/gzu-liyujiang/${rootProject.name}"
def pomGitUrl = "https://github.com/gzu-liyujiang/${rootProject.name}.git"
def pomIssueUrl = "https://github.com/gzu-liyujiang/${rootProject.name}/issues"
def pomReleaseNotesUrl = "https://github.com/gzu-liyujiang/${rootProject.name}/README.md"
def pomLicenses = ["MIT"]
def pomLicenses = ["Apache License 2.0", "Mulan PSL v1"]
//开发者信息
def pomDeveloperId = 'liyujiang-gzu'
def pomDeveloperOrg = 'gzu-liyujiang'
def pomDeveloperName = '李玉江'
def pomDeveloperEmail = '1032694760@qq.com'
......
```

### License

```text
Copyright (c) 2019-2020 gzu-liyujiang <1032694760@qq.com>
AliyunGradleConfig is licensed under the Mulan PSL v1.
The software is licensed under the Mulan PSL v1.
You can use this software according to the terms and conditions of the Mulan PSL v1.
You may obtain a copy of Mulan PSL v1 at:
http://license.coscl.org.cn/MulanPSL
Expand Down
9 changes: 3 additions & 6 deletions gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@ org.gradle.daemon=true
# 按需配置
org.gradle.configureondemand=true
# 项目路径含中文需加上此句
android.overridePathCheck=false
#android.overridePathCheck=true
# 启用AndroidX
android.useAndroidX=true
# 将依赖包迁移到AndroidX
android.enableJetifier=true
# R8混淆模式
android.enableR8.fullMode=false
#android.enableR8.fullMode=true
# 显示有问题的gradle堆栈
android.debug.obsoleteApi=true
# INSTALL_FAILED_TEST_ONLY
Expand All @@ -30,8 +30,5 @@ androidTargetSdkVersion=28
# AndroidX 版本
androidxCoreVersion=1.1.0
androidxLifecycleVersion=2.1.0
# APP包名,在AndroidManifest.xml里可通过`applicationId`引用
appPackageName=com.github.gzuliyujiang.demo
appVersionName=1.0.0
# AndResGuard插件版本
appResGuardVersion=1.2.18
andResGuardVersion=1.2.18
8 changes: 6 additions & 2 deletions gradle/common.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,12 @@ android {
defaultConfig {
minSdkVersion androidMinSdkVersion as int
targetSdkVersion androidTargetSdkVersion as int
versionCode Integer.parseInt(new Date().format("yyyyMMdd"))
versionName appVersionName + '.' + versionCode
versionCode rootProject.gitGitCommitNumber()
versionName rootProject.getGitLatestTag()
println("versionCode: $versionCode\nversionName: $versionName")
buildConfigField "String", "GIT_BRANCH", '"' + rootProject.getGitBranch() + '"'
buildConfigField "String", "GIT_LATEST_COMMIT_HASH", '"' + rootProject.getGitLatestCommitHash() + '"'
buildConfigField "String", "GIT_LATEST_COMMIT_HASH_SHORT", '"' + rootProject.getGitLatestCommitHashShort() + '"'
}

sourceSets {
Expand Down
45 changes: 26 additions & 19 deletions gradle/publish.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@ apply plugin: 'maven-publish'
apply plugin: 'com.jfrog.bintray'

//项目相关信息
def includeJAR = false
def includeJar = false
def pomLibGroupName = 'com.github.gzuliyujiang'
def pomLibArtifactId = rootProject.name
def pomLibVersion = '1.0.0.' + new Date().format("yyyyMMdd")
def pomLibVersion = rootProject.getGitLatestTag()
def pomLibDescription = "TODO description: ${rootProject.name} for Android"
def pomSiteUrl = "https://github.com/gzu-liyujiang/${rootProject.name}"
def pomGitUrl = "https://github.com/gzu-liyujiang/${rootProject.name}.git"
Expand All @@ -28,22 +28,20 @@ def pomDeveloperId = 'liyujiang-gzu'
def pomDeveloperOrg = 'gzu-liyujiang'
def pomDeveloperName = '李玉江'
def pomDeveloperEmail = '1032694760@qq.com'
//GitHub仓库信息
def githubRepositoryOwner = pomDeveloperOrg
def githubRepositoryName = pomLibArtifactId
def githubUsername = project.findProperty("githubUserName") ?: pomDeveloperId
//1、在`https://github.com/settings/tokens`创建个人token,勾选包读写权限。
//2、在`https://github.com/gzu-liyujiang/${rootProject.name}/settings/secrets`将token添加为secrets。
//3、在GithubActions文件里添加`env:TOKEN: ${{ secrets.TOKEN }}`。
def githubToken = project.findProperty("githubToken") ?: System.getenv("TOKEN")
println("github credentials: user=$githubUsername token=$githubToken")

def bintrayUserName = ''
def bintrayApiKey = ''
try {
// {PROJECT_ROOT}/local.properties
Properties localProp = new Properties()
localProp.load(project.rootProject.file('local.properties').newDataInputStream())
// {USER_HOME}/.gradle/gradle.properties
Map rootProp = project.getProperties()
//Bintray用户信息
bintrayUserName = localProp.getProperty('bintrayUserName', rootProp.get('bintrayUserName', ''))
bintrayApiKey = localProp.getProperty('bintrayApiKey', rootProp.get('bintrayApiKey', ''))
println("bintray properties: user=$bintrayUserName apikey=$bintrayApiKey")
} catch (ignore) {
System.err.println('read bintray user&apiKey failed')
}
// {USER_HOME}/.gradle/gradle.properties
def bintrayUserName = project.findProperty('bintrayUserName') ?: ''
def bintrayApiKey = project.findProperty('bintrayApiKey') ?: ''
println("bintray credentials: user=$bintrayUserName apikey=$bintrayApiKey")

task sourcesJar(type: Jar) {
getArchiveClassifier().set('sources')
Expand All @@ -53,7 +51,16 @@ task sourcesJar(type: Jar) {
afterEvaluate {
publishing {
repositories {
mavenLocal()
maven {
// See https://docs.github.com/en/packages/using-github-packages-with-your-projects-ecosystem/configuring-gradle-for-use-with-github-packages
// See https://docs.github.com/en/actions/configuring-and-managing-workflows/creating-and-storing-encrypted-secrets
name = 'GitHub Packages'
url = uri("https://maven.pkg.github.com/${githubRepositoryOwner}/${githubRepositoryName}")
credentials {
username = githubUsername
password = githubToken
}
}
}
publications {
// See https://developer.android.google.cn/studio/build/maven-publish-plugin
Expand All @@ -63,7 +70,7 @@ afterEvaluate {
version = pomLibVersion
description = pomLibDescription
artifactId pomLibArtifactId
if (includeJAR) {
if (includeJar) {
artifact "${buildDir}/intermediates/aar_main_jar/release/classes.jar"
}
artifact sourcesJar
Expand Down
Loading

0 comments on commit edee22f

Please sign in to comment.