Skip to content

Commit

Permalink
Replace git submodules for test projects with custom GitCheckoutTask (#…
Browse files Browse the repository at this point in the history
…3483)

Replace git submodules for test projects with custom GitCheckoutTask

This improves the experience when running Dokka tests. External projects used for testing can be managed using Gradle. Because the commitId is defined in code it's easier to see what version the external projects are used.

* remove submodules checkout from GitHub actions
* gitignore downloaded projects
* move `fs.sync` outside of `use { git -> ... }` so it's easier to view & understand the steps
* add more comments to explain git checkout process
  • Loading branch information
adam-enko committed Feb 6, 2024
1 parent 664933e commit 5978f46
Show file tree
Hide file tree
Showing 11 changed files with 164 additions and 28 deletions.
6 changes: 0 additions & 6 deletions .github/workflows/preview-publish-ga.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@ jobs:
steps:
- name: Checkout dokka
uses: actions/checkout@v3
with:
submodules: true
- uses: actions/setup-java@v3
with:
distribution: 'zulu'
Expand Down Expand Up @@ -45,8 +43,6 @@ jobs:
steps:
- name: Checkout dokka
uses: actions/checkout@v3
with:
submodules: true
- uses: actions/setup-java@v3
with:
distribution: 'zulu'
Expand Down Expand Up @@ -74,8 +70,6 @@ jobs:
steps:
- name: Checkout dokka
uses: actions/checkout@v3
with:
submodules: true
- uses: actions/setup-java@v3
with:
distribution: 'zulu'
Expand Down
6 changes: 0 additions & 6 deletions .github/workflows/preview-publish-web-s3.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@ jobs:
steps:
- name: Checkout dokka
uses: actions/checkout@v3
with:
submodules: true
- uses: actions/setup-java@v3
with:
distribution: 'zulu'
Expand Down Expand Up @@ -44,8 +42,6 @@ jobs:
steps:
- name: Checkout dokka
uses: actions/checkout@v3
with:
submodules: true
- uses: actions/setup-java@v3
with:
distribution: 'zulu'
Expand Down Expand Up @@ -75,8 +71,6 @@ jobs:
steps:
- name: Checkout dokka
uses: actions/checkout@v3
with:
submodules: true
- uses: actions/setup-java@v3
with:
distribution: 'zulu'
Expand Down
9 changes: 0 additions & 9 deletions .gitmodules

This file was deleted.

5 changes: 1 addition & 4 deletions .idea/vcs.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions build-logic/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ dependencies {
implementation("org.gradle.kotlin:gradle-kotlin-dsl-plugins:$expectedKotlinDslPluginsVersion")
implementation(libs.gradlePlugin.gradlePublish)

implementation(libs.eclipse.jgit)

// workaround for accessing version-catalog in convention plugins
// https://github.com/gradle/gradle/issues/15383#issuecomment-779893192
implementation(files(libs.javaClass.superclass.protectionDomain.codeSource.location))
Expand Down
124 changes: 124 additions & 0 deletions build-logic/src/main/kotlin/dokkabuild/tasks/GitCheckoutTask.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
/*
* Copyright 2014-2024 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
*/
package dokkabuild.tasks

import org.eclipse.jgit.api.Git
import org.eclipse.jgit.api.ResetCommand.ResetType.HARD
import org.eclipse.jgit.lib.NullProgressMonitor
import org.eclipse.jgit.lib.ProgressMonitor
import org.eclipse.jgit.lib.RepositoryCache
import org.eclipse.jgit.lib.TextProgressMonitor
import org.eclipse.jgit.util.FS
import org.gradle.api.DefaultTask
import org.gradle.api.file.DirectoryProperty
import org.gradle.api.file.FileSystemOperations
import org.gradle.api.provider.Property
import org.gradle.api.tasks.CacheableTask
import org.gradle.api.tasks.Input
import org.gradle.api.tasks.OutputDirectory
import org.gradle.api.tasks.TaskAction
import java.io.File
import javax.inject.Inject

/**
* Clones a remote Git repository into [GitCheckoutTask.destination].
*/
@CacheableTask
abstract class GitCheckoutTask @Inject constructor(
private val fs: FileSystemOperations
) : DefaultTask() {

@get:OutputDirectory
abstract val destination: DirectoryProperty

/** Public HTTP URI of the Git repo. */
@get:Input
abstract val uri: Property<String>

/** Specific git hash to checkout. */
@get:Input
abstract val commitId: Property<String>

private val localRepoDir: File
get() = temporaryDir.resolve("repo")

private val gitOperationsPrinter: ProgressMonitor =
if (logger.isInfoEnabled) {
TextProgressMonitor()
} else {
NullProgressMonitor.INSTANCE
}

init {
group = "git checkout"
}

@TaskAction
fun action() {
initializeRepo()

fs.sync {
from(localRepoDir)
into(destination)
// exclude the .git dir:
// - prevent the root git repo getting confused with a nested git repo
// - improves Gradle caching
exclude(".git/")
}

logger.lifecycle("initialized git repo $uri in ${destination.asFile.orNull}")
}

/**
* Initialize [uri] in [localRepoDir].
*
* If a git repo already exists in [localRepoDir], try to re-use it.
*
* Any changes to tracked or untracked files will be forcibly removed.
*/
private fun initializeRepo() {
val uri = uri.get()
val commitId = commitId.get()

// Check if the repo is already cloned. If yes, then we can re-use it to save time.
val gitRepoInitialized = RepositoryCache.FileKey.isGitRepository(localRepoDir, FS.DETECTED)

val repo = if (gitRepoInitialized) {
// re-use existing cloned repo
Git.open(localRepoDir)
} else {
// repo is either not cloned or is not recognizable, so delete it and make a fresh clone
fs.delete { delete(localRepoDir) }

Git.cloneRepository()
.setProgressMonitor(gitOperationsPrinter)
.setNoCheckout(true)
.setURI(uri)
.setDirectory(localRepoDir)
.call()
}

repo.use { git ->
// checkout the specific commitId specified in the task input
git.checkout()
.setProgressMonitor(gitOperationsPrinter)
.setForced(true)
.setName(commitId)
.call()

// git reset --hard (wipe changes to tracked files, if any)
git.reset()
.setProgressMonitor(gitOperationsPrinter)
.setMode(HARD)
.call()

// git clean -fdx (remove any changes in untracked files)
git.clean()
.setForce(true)
.setCleanDirectories(true)
.setIgnore(false)
.call()
}
}
}
24 changes: 21 additions & 3 deletions dokka-integration-tests/gradle/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import org.jetbrains.kotlin.gradle.dsl.ExplicitApiMode

/*
* Copyright 2014-2024 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
*/
import dokkabuild.tasks.GitCheckoutTask
import org.jetbrains.kotlin.gradle.dsl.ExplicitApiMode

plugins {
id("dokkabuild.test-integration")
Expand All @@ -25,14 +25,20 @@ kotlin {
explicitApi = ExplicitApiMode.Disabled
}

val templateProjectsDir = layout.projectDirectory.dir("projects")

val aggregatingProject = gradle.includedBuild("dokka")

tasks.integrationTest {
dependsOn(aggregatingProject.task(":publishToMavenLocal"))
dependsOn(
checkoutKotlinxCoroutines,
checkoutKotlinxSerialization,
)

environment("DOKKA_VERSION", project.version)

inputs.dir(file("projects"))
inputs.dir(templateProjectsDir)

javaLauncher.set(javaToolchains.launcherFor {
// kotlinx.coroutines requires Java 11+
Expand All @@ -41,3 +47,15 @@ tasks.integrationTest {
})
})
}

val checkoutKotlinxCoroutines by tasks.registering(GitCheckoutTask::class) {
uri = "https://github.com/Kotlin/kotlinx.coroutines.git"
commitId = "b78bbf518bd8e90e9ed2133ebdacc36441210cd6"
destination = templateProjectsDir.dir("coroutines/kotlinx-coroutines")
}

val checkoutKotlinxSerialization by tasks.registering(GitCheckoutTask::class) {
uri = "https://github.com/Kotlin/kotlinx.serialization.git"
commitId = "ed1b05707ec27f8864c8b42235b299bdb5e0015c"
destination = templateProjectsDir.dir("serialization/kotlinx-serialization")
}
2 changes: 2 additions & 0 deletions dokka-integration-tests/gradle/projects/coroutines/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# kotlinx-coroutines is automatically downloaded with a Gradle task
kotlinx-coroutines/
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# kotlinx-serialization is automatically downloaded with a Gradle task
kotlinx-serialization/
10 changes: 10 additions & 0 deletions dokka-integration-tests/maven/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/*
* Copyright 2014-2024 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
*/
import dokkabuild.tasks.GitCheckoutTask

plugins {
id("dokkabuild.test-integration")
Expand All @@ -14,13 +15,16 @@ dependencies {
implementation(libs.junit.jupiterApi)
}

val templateProjectsDir = layout.projectDirectory.dir("projects")

val dokkaSubprojects = gradle.includedBuild("dokka")
val mavenPlugin = gradle.includedBuild("runner-maven-plugin")

tasks.integrationTest {
dependsOn(
dokkaSubprojects.task(":publishToMavenLocal"),
mavenPlugin.task(":publishToMavenLocal"),
checkoutBioJava,
)

dependsOn(tasks.installMavenBinary)
Expand All @@ -33,3 +37,9 @@ tasks.integrationTest {
environment("MVN_BINARY_PATH", mvn.get().asFile.invariantSeparatorsPath)
}
}

val checkoutBioJava by tasks.registering(GitCheckoutTask::class) {
uri = "https://github.com/biojava/biojava.git"
commitId = "059fbf1403d0704801df1427b0ec925102a645cd"
destination = templateProjectsDir.dir("biojava/biojava")
}
2 changes: 2 additions & 0 deletions dokka-integration-tests/maven/projects/biojava/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# biojava is automatically downloaded with a Gradle task
biojava/

0 comments on commit 5978f46

Please sign in to comment.