Migrate versioning to Gradle plugin and automate version bumps (#1282)
This commit is contained in:
parent
405e1d1772
commit
3a2cfd22e6
6 changed files with 180 additions and 12 deletions
61
.github/workflows/draft_new_release.yml
vendored
61
.github/workflows/draft_new_release.yml
vendored
|
@ -9,32 +9,73 @@ jobs:
|
|||
name: "Draft a new release"
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f
|
||||
with:
|
||||
ref: 'release'
|
||||
- name: Extract version from milestone
|
||||
run: |
|
||||
VERSION="${{ github.event.milestone.title }}"
|
||||
echo "RELEASE_VERSION=${VERSION/v/}" >> $GITHUB_ENV
|
||||
RELEASE_VERSION="${VERSION/v/}"
|
||||
# Transforms 1.13.2 to 1.13 so that we can re-use the same
|
||||
# branch for patch releases.
|
||||
BRANCH_VERSION="${RELEASE_VERSION:$i:-2}"
|
||||
if [[ "${RELEASE_VERSION: -1}" == "0" ]]; then
|
||||
CHECKOUT_REF="develop"
|
||||
else
|
||||
CHECKOUT_REF="release-${BRANCH_VERSION}"
|
||||
fi
|
||||
|
||||
# Export variables separately so the scripting above is more legible,
|
||||
# and we can actually use them within this block. Changes to $GITHUB_ENV
|
||||
# only affect the next step, not the current one.
|
||||
echo "RELEASE_VERSION=${RELEASE_VERSION}" >> $GITHUB_ENV
|
||||
echo "CHECKOUT_REF=${CHECKOUT_REF}" >> $GITHUB_ENV
|
||||
echo "BRANCH_VERSION=${BRANCH_VERSION}" >> $GITHUB_ENV
|
||||
echo "PR_BASE=release-${BRANCH_VERSION}" >> $GITHUB_ENV
|
||||
echo "PR_HEAD=release-prep" >> $GITHUB_ENV
|
||||
|
||||
- uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f
|
||||
with:
|
||||
ref: ${{ env.CHECKOUT_REF }}
|
||||
|
||||
- name: Update changelog
|
||||
uses: thomaseizinger/keep-a-changelog-new-release@96ebf19f2bddaf72406c84691b9c2d827da53140
|
||||
with:
|
||||
version: ${{ env.RELEASE_VERSION }}
|
||||
version: ${{ github.event.milestone.title }}
|
||||
|
||||
- name: Initialize git config and commit changes
|
||||
run: |
|
||||
# Configure name and email for Actions user
|
||||
git config user.name "GitHub Actions"
|
||||
git config user.email noreply@github.com
|
||||
|
||||
# It is necessary to create the $PR_BASE branch if it doesn't
|
||||
# already exist because we want to start a PR against it.
|
||||
if [[ "${CHECKOUT_REF}" == "develop" ]]; then
|
||||
git branch -c develop "${PR_BASE}"
|
||||
git push origin "${PR_BASE}"
|
||||
fi
|
||||
|
||||
# Stage and commit changes to the changelog
|
||||
git add CHANGELOG.md
|
||||
git commit -m "CHANGELOG: bump for ${{ github.event.milestone.title }}"
|
||||
|
||||
# Increment the version as necessary. If we checked out develop it means
|
||||
# that the version number is already correct, and we only need to drop the
|
||||
# -SNAPSHOT suffix.
|
||||
if [[ "${CHECKOUT_REF}" == "develop" ]]; then
|
||||
./gradlew clearPreRelease
|
||||
else
|
||||
./gradlew bumpPatch
|
||||
fi
|
||||
|
||||
# Commit changes to the versioning
|
||||
git add **/version.properties
|
||||
git commit -m "build: bump version"
|
||||
|
||||
- name: Create Pull Request
|
||||
uses: peter-evans/create-pull-request@45c510e1f68ba052e3cd911f661a799cfb9ba3a3
|
||||
with:
|
||||
author: GitHub Actions <noreply@github.com>
|
||||
base: release
|
||||
body: This is an automated pull request to bump the changelog for the v${{ env.RELEASE_VERSION }} release.
|
||||
branch: release-${{ env.RELEASE_VERSION }}
|
||||
commit-message: "CHANGELOG: bump for ${{ env.RELEASE_VERSION }}"
|
||||
draft: true
|
||||
body: This is an automated pull request to bump the changelog for the ${{ github.event.milestone.title }} release.
|
||||
base: ${{ env.PR_BASE }}
|
||||
branch: ${{ env.PR_HEAD }}
|
||||
title: Release v${{ env.RELEASE_VERSION }}
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
|
|
@ -7,6 +7,7 @@ import com.android.build.gradle.internal.api.BaseVariantOutputImpl
|
|||
plugins {
|
||||
id("com.android.application")
|
||||
kotlin("android")
|
||||
`versioning-plugin`
|
||||
`aps-plugin`
|
||||
`crowdin-plugin`
|
||||
}
|
||||
|
@ -26,8 +27,6 @@ android {
|
|||
|
||||
defaultConfig {
|
||||
applicationId = "dev.msfjarvis.aps"
|
||||
versionCode = 2_00_00
|
||||
versionName = "2.0.0-SNAPSHOT"
|
||||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||
}
|
||||
|
||||
|
|
6
app/version.properties
Normal file
6
app/version.properties
Normal file
|
@ -0,0 +1,6 @@
|
|||
#
|
||||
#This file was automatically generated by 'versioning-plugin'. DO NOT EDIT MANUALLY.
|
||||
#
|
||||
#Sun Jan 17 12:32:03 IST 2021
|
||||
versioning-plugin.versionCode=20000
|
||||
versioning-plugin.versionName=2.0.0-SNAPSHOT
|
|
@ -25,6 +25,10 @@ gradlePlugin {
|
|||
id = "crowdin-plugin"
|
||||
implementationClass = "CrowdinDownloadPlugin"
|
||||
}
|
||||
register("versioning") {
|
||||
id = "versioning-plugin"
|
||||
implementationClass = "VersioningPlugin"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -33,4 +37,5 @@ dependencies {
|
|||
implementation(build.getValue("androidGradlePlugin"))
|
||||
implementation(build.getValue("binaryCompatibilityValidator"))
|
||||
implementation(build.getValue("downloadTaskPlugin"))
|
||||
implementation(build.getValue("jsemver"))
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ rootProject.ext.versions = [
|
|||
kotlin : '1.4.21',
|
||||
binary_compatibility_validator : '0.2.4',
|
||||
download_plugin : '4.1.1',
|
||||
semver : '0.9.0',
|
||||
]
|
||||
|
||||
rootProject.ext.build = [
|
||||
|
@ -10,4 +11,5 @@ rootProject.ext.build = [
|
|||
kotlinGradlePlugin : "org.jetbrains.kotlin:kotlin-gradle-plugin:${versions.kotlin}",
|
||||
binaryCompatibilityValidator : "org.jetbrains.kotlinx:binary-compatibility-validator:${versions.binary_compatibility_validator}",
|
||||
downloadTaskPlugin : "de.undercouch:gradle-download-task:${versions.download_plugin}",
|
||||
jsemver : "com.github.zafarkhaja:java-semver:${versions.semver}",
|
||||
]
|
||||
|
|
115
buildSrc/src/main/java/VersioningPlugin.kt
Normal file
115
buildSrc/src/main/java/VersioningPlugin.kt
Normal file
|
@ -0,0 +1,115 @@
|
|||
/*
|
||||
* Copyright © 2014-2021 The Android Password Store Authors. All Rights Reserved.
|
||||
* SPDX-License-Identifier: GPL-3.0-only
|
||||
*/
|
||||
|
||||
|
||||
import com.android.build.gradle.internal.plugins.AppPlugin
|
||||
import com.github.zafarkhaja.semver.Version
|
||||
import java.io.OutputStream
|
||||
import java.util.Properties
|
||||
import org.gradle.api.Plugin
|
||||
import org.gradle.api.Project
|
||||
|
||||
private const val VERSIONING_PROP_FILE = "version.properties"
|
||||
private const val VERSIONING_PROP_VERSION_NAME = "versioning-plugin.versionName"
|
||||
private const val VERSIONING_PROP_VERSION_CODE = "versioning-plugin.versionCode"
|
||||
private const val VERSIONING_PROP_COMMENT = """
|
||||
This file was automatically generated by 'versioning-plugin'. DO NOT EDIT MANUALLY.
|
||||
"""
|
||||
|
||||
/**
|
||||
* A Gradle [Plugin] that takes a [Project] with the [AppPlugin] applied and dynamically sets the
|
||||
* versionCode and versionName properties based on values read from a [VERSIONING_PROP_FILE] file in
|
||||
* the [Project.getBuildDir] directory. It also adds Gradle tasks to bump the major, minor, and patch
|
||||
* versions along with one to prepare the next snapshot.
|
||||
*/
|
||||
@Suppress(
|
||||
"UnstableApiUsage",
|
||||
"NAME_SHADOWING"
|
||||
)
|
||||
class VersioningPlugin : Plugin<Project> {
|
||||
|
||||
/**
|
||||
* Generate the Android 'versionCode' property
|
||||
*/
|
||||
private fun Version.androidCode(): Int {
|
||||
return majorVersion * 1_00_00 +
|
||||
minorVersion * 1_00 +
|
||||
patchVersion
|
||||
}
|
||||
|
||||
/**
|
||||
* Write an Android-specific variant of [this] to [stream]
|
||||
*/
|
||||
private fun Version.writeForAndroid(stream: OutputStream) {
|
||||
val newVersionCode = androidCode()
|
||||
val props = Properties()
|
||||
props.setProperty(VERSIONING_PROP_VERSION_CODE, "$newVersionCode")
|
||||
props.setProperty(VERSIONING_PROP_VERSION_NAME, toString())
|
||||
props.store(stream, VERSIONING_PROP_COMMENT)
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the same [Version], but with build metadata stripped.
|
||||
*/
|
||||
private fun Version.clearPreRelease(): Version {
|
||||
return Version.forIntegers(majorVersion, minorVersion, patchVersion)
|
||||
}
|
||||
|
||||
override fun apply(project: Project) {
|
||||
with(project) {
|
||||
val appPlugin = requireNotNull(plugins.findPlugin(AppPlugin::class.java)) {
|
||||
"Plugin 'com.android.application' must be applied to use this plugin"
|
||||
}
|
||||
val propFile = layout.projectDirectory.file(VERSIONING_PROP_FILE)
|
||||
require(propFile.asFile.exists()) {
|
||||
"A 'version.properties' file must exist in the project subdirectory to use this plugin"
|
||||
}
|
||||
val contents = providers.fileContents(propFile).asText.forUseAtConfigurationTime()
|
||||
val versionProps = Properties().also { it.load(contents.get().byteInputStream()) }
|
||||
val versionName = requireNotNull(versionProps.getProperty(VERSIONING_PROP_VERSION_NAME)) {
|
||||
"version.properties must contain a '$VERSIONING_PROP_VERSION_NAME' property"
|
||||
}
|
||||
val versionCode = requireNotNull(versionProps.getProperty(VERSIONING_PROP_VERSION_CODE).toInt()) {
|
||||
"version.properties must contain a '$VERSIONING_PROP_VERSION_CODE' property"
|
||||
}
|
||||
appPlugin.extension.defaultConfig.versionName = versionName
|
||||
appPlugin.extension.defaultConfig.versionCode = versionCode
|
||||
afterEvaluate {
|
||||
val version = Version.valueOf(versionName)
|
||||
tasks.register("clearPreRelease") {
|
||||
doLast {
|
||||
version.clearPreRelease()
|
||||
.writeForAndroid(propFile.asFile.outputStream())
|
||||
}
|
||||
}
|
||||
tasks.register("bumpMajor") {
|
||||
doLast {
|
||||
version.incrementMajorVersion()
|
||||
.writeForAndroid(propFile.asFile.outputStream())
|
||||
}
|
||||
}
|
||||
tasks.register("bumpMinor") {
|
||||
doLast {
|
||||
version.incrementMinorVersion()
|
||||
.writeForAndroid(propFile.asFile.outputStream())
|
||||
}
|
||||
}
|
||||
tasks.register("bumpPatch") {
|
||||
doLast {
|
||||
version.incrementPatchVersion()
|
||||
.writeForAndroid(propFile.asFile.outputStream())
|
||||
}
|
||||
}
|
||||
tasks.register("bumpSnapshot") {
|
||||
doLast {
|
||||
version.incrementMinorVersion()
|
||||
.setPreReleaseVersion("SNAPSHOT")
|
||||
.writeForAndroid(propFile.asFile.outputStream())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue