Skip to content

Commit

Permalink
Fix an issue where changing git HEAD does not invalidate task cache.
Browse files Browse the repository at this point in the history
  • Loading branch information
ychescale9 committed Apr 20, 2022
1 parent 4df1fc0 commit 3574f26
Show file tree
Hide file tree
Showing 5 changed files with 118 additions and 1 deletion.
2 changes: 2 additions & 0 deletions api/app-versioning.api
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ public final class io/github/reactivecircus/appversioning/internal/CommitId {
public final class io/github/reactivecircus/appversioning/internal/GitClient {
public static final field Companion Lio/github/reactivecircus/appversioning/internal/GitClient$Companion;
public synthetic fun <init> (Ljava/io/File;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
public final fun checkoutTag (Ljava/lang/String;)V
public final fun commit-HhBVPuw (Ljava/lang/String;Z)Ljava/lang/String;
public static synthetic fun commit-HhBVPuw$default (Lio/github/reactivecircus/appversioning/internal/GitClient;Ljava/lang/String;ZILjava/lang/Object;)Ljava/lang/String;
public final fun describeLatestTag (Ljava/lang/String;)Ljava/lang/String;
Expand All @@ -129,6 +130,7 @@ public abstract class io/github/reactivecircus/appversioning/tasks/GenerateAppVe
public fun <init> (Lorg/gradle/workers/WorkerExecutor;)V
public final fun generate ()V
public abstract fun getFetchTagsWhenNoneExistsLocally ()Lorg/gradle/api/provider/Property;
public abstract fun getGitHead ()Lorg/gradle/api/file/RegularFileProperty;
public abstract fun getGitRefsDirectory ()Lorg/gradle/api/file/DirectoryProperty;
public abstract fun getGroovyVersionCodeCustomizer ()Lorg/gradle/api/provider/Property;
public abstract fun getGroovyVersionNameCustomizer ()Lorg/gradle/api/provider/Property;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -946,6 +946,83 @@ class GenerateAppVersionInfoTest {
gitClient.tag(name = "1.3.0", message = "2nd tag", commitId = commitId2)

runner.runAndCheckResult(
"clean",
"generateAppVersionInfoForRelease",
"--build-cache"
) {
assertThat(task(":app:generateAppVersionInfoForRelease")?.outcome).isEqualTo(TaskOutcome.SUCCESS)
}
}

@Test
fun `GenerateAppVersionInfo (up-to-date) is re-executed after changing git HEAD`() {
val gitClient = GitClient.initialize(fixtureDir.root).apply {
val commitId1 = commit(message = "1st commit.")
tag(name = "1.2.3", message = "1st tag", commitId = commitId1)
val commitId2 = commit(message = "2nd commit.")
tag(name = "1.2.4", message = "2st tag", commitId = commitId2)
}

val runner = withFixtureRunner(
fixtureDir = fixtureDir,
subprojects = listOf(AppProjectTemplate())
)

runner.runAndCheckResult(
"generateAppVersionInfoForRelease"
) {
assertThat(task(":app:generateAppVersionInfoForRelease")?.outcome).isEqualTo(TaskOutcome.SUCCESS)
}

runner.runAndCheckResult(
"generateAppVersionInfoForRelease"
) {
assertThat(task(":app:generateAppVersionInfoForRelease")?.outcome).isEqualTo(TaskOutcome.UP_TO_DATE)
}

gitClient.checkoutTag(tag = "1.2.3")

runner.runAndCheckResult(
"generateAppVersionInfoForRelease"
) {
assertThat(task(":app:generateAppVersionInfoForRelease")?.outcome).isEqualTo(TaskOutcome.SUCCESS)
}
}

@Test
fun `GenerateAppVersionInfo (from cache) is re-executed after changing git HEAD`() {
val gitClient = GitClient.initialize(fixtureDir.root).apply {
val commitId1 = commit(message = "1st commit.")
tag(name = "1.2.3", message = "1st tag", commitId = commitId1)
val commitId2 = commit(message = "2nd commit.")
tag(name = "1.2.4", message = "2st tag", commitId = commitId2)
}

val runner = withFixtureRunner(
fixtureDir = fixtureDir,
subprojects = listOf(AppProjectTemplate())
)

runner.runAndCheckResult(
"generateAppVersionInfoForRelease",
"--build-cache"
) {
assertThat(task(":app:generateAppVersionInfoForRelease")?.outcome).isEqualTo(TaskOutcome.SUCCESS)
}

runner.runAndCheckResult(
"clean",
"generateAppVersionInfoForRelease",
"--build-cache"
) {
assertThat(task(":app:clean")?.outcome).isEqualTo(TaskOutcome.SUCCESS)
assertThat(task(":app:generateAppVersionInfoForRelease")?.outcome).isEqualTo(TaskOutcome.FROM_CACHE)
}

gitClient.checkoutTag(tag = "1.2.3")

runner.runAndCheckResult(
"clean",
"generateAppVersionInfoForRelease",
"--build-cache"
) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ class AppVersioningPlugin : Plugin<Project> {
group = APP_VERSIONING_TASK_GROUP
description = "${GenerateAppVersionInfo.TASK_DESCRIPTION_PREFIX} for the ${variant.name} variant."
gitRefsDirectory.set(findGitRefsDirectory(extension))
gitHead.set(findGitHeadFile(extension))
rootProjectDirectory.set(project.rootProject.rootDir)
rootProjectDisplayName.set(project.rootProject.displayName)
fetchTagsWhenNoneExistsLocally.set(extension.fetchTagsWhenNoneExistsLocally)
Expand Down Expand Up @@ -133,6 +134,22 @@ class AppVersioningPlugin : Plugin<Project> {
}
}

private fun Project.findGitHeadFile(extension: AppVersioningExtension): File? {
return when {
extension.bareGitRepoDirectory.isPresent -> {
extension.bareGitRepoDirectory.let { bareGitRepoDirectory ->
bareGitRepoDirectory.asFile.orNull?.resolve(HEAD_FILE)?.takeIf { it.exists() }
}
}
extension.gitRootDirectory.isPresent -> {
extension.gitRootDirectory.let { gitRootDirectory ->
gitRootDirectory.asFile.orNull?.resolve(STANDARD_GIT_HEAD_FILE)?.takeIf { it.exists() }
}
}
else -> project.rootProject.file(STANDARD_GIT_HEAD_FILE).takeIf { it.exists() }
}
}

companion object {
private const val MIN_GRADLE_VERSION = "6.8"
private const val MIN_AGP_VERSION = "7.0.0-beta04"
Expand All @@ -142,6 +159,8 @@ class AppVersioningPlugin : Plugin<Project> {
private const val APP_VERSIONING_TASK_GROUP = "versioning"
private const val APP_VERSIONING_TASK_OUTPUT_DIR = "outputs/app_versioning"
private const val REFS_DIRECTORY = "refs"
private const val HEAD_FILE = "HEAD"
private const val STANDARD_GIT_REFS_DIRECTORY = ".git/$REFS_DIRECTORY"
private const val STANDARD_GIT_HEAD_FILE = ".git/$HEAD_FILE"
private const val VERSION_CODE_RESULT_FILE = "version_code.txt"
private const val VERSION_NAME_RESULT_FILE = "version_name.txt"
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,15 @@ class GitClient private constructor(private val projectDir: File) {
command.execute(projectDir)
}

fun checkoutTag(tag: String) {
val commitCommand = buildList {
add("git")
add("checkout")
add(tag)
}
commitCommand.execute(projectDir)
}

companion object {

fun initialize(projectDir: File): GitClient {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import org.gradle.api.tasks.CacheableTask
import org.gradle.api.tasks.IgnoreEmptyDirectories
import org.gradle.api.tasks.Input
import org.gradle.api.tasks.InputDirectory
import org.gradle.api.tasks.InputFile
import org.gradle.api.tasks.Internal
import org.gradle.api.tasks.Optional
import org.gradle.api.tasks.OutputFile
Expand Down Expand Up @@ -48,6 +49,12 @@ abstract class GenerateAppVersionInfo @Inject constructor(
@get:NormalizeLineEndings
abstract val gitRefsDirectory: DirectoryProperty

@get:Optional
@get:InputFile
@get:PathSensitive(PathSensitivity.RELATIVE)
@get:NormalizeLineEndings
abstract val gitHead: RegularFileProperty

@get:Internal
abstract val rootProjectDirectory: DirectoryProperty

Expand Down Expand Up @@ -90,6 +97,7 @@ abstract class GenerateAppVersionInfo @Inject constructor(
fun generate() {
workerExecutor.noIsolation().submit(GenerateAppVersionInfoWorkAction::class.java) {
gitRefsDirectory.set(this@GenerateAppVersionInfo.gitRefsDirectory)
gitHead.set(this@GenerateAppVersionInfo.gitHead)
rootProjectDirectory.set(this@GenerateAppVersionInfo.rootProjectDirectory)
rootProjectDisplayName.set(this@GenerateAppVersionInfo.rootProjectDisplayName)
fetchTagsWhenNoneExistsLocally.set(this@GenerateAppVersionInfo.fetchTagsWhenNoneExistsLocally)
Expand All @@ -114,6 +122,7 @@ abstract class GenerateAppVersionInfo @Inject constructor(

private interface GenerateAppVersionInfoWorkParameters : WorkParameters {
val gitRefsDirectory: DirectoryProperty
val gitHead: RegularFileProperty
val rootProjectDirectory: DirectoryProperty
val rootProjectDisplayName: Property<String>
val fetchTagsWhenNoneExistsLocally: Property<Boolean>
Expand All @@ -135,6 +144,7 @@ private abstract class GenerateAppVersionInfoWorkAction @Inject constructor(

override fun execute() {
val gitRefsDirectory = parameters.gitRefsDirectory
val gitHead = parameters.gitHead
val rootProjectDirectory = parameters.rootProjectDirectory
val rootProjectDisplayName = parameters.rootProjectDisplayName
val fetchTagsWhenNoneExistsLocally = parameters.fetchTagsWhenNoneExistsLocally
Expand All @@ -147,7 +157,7 @@ private abstract class GenerateAppVersionInfoWorkAction @Inject constructor(
val versionNameFile = parameters.versionNameFile
val variantInfo = parameters.variantInfo

check(gitRefsDirectory.isPresent) {
check(gitRefsDirectory.isPresent && gitHead.isPresent) {
"Android App Versioning Gradle Plugin works with git tags but ${rootProjectDisplayName.get()} is not a git root directory, and a valid gitRootDirectory is not provided."
}

Expand Down

0 comments on commit 3574f26

Please sign in to comment.