Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,12 @@ import org.gradle.api.Task
interface DataConnectExecutableConfig {
var outputDirectory: File?
var connectors: Collection<String>
var connectorId: Collection<String>
var listen: String?
var localConnectionString: String?
var logFile: File?
var schemaExtensionsOutputEnabled: Boolean?
var platform: String?
}

fun Task.runDataConnectExecutable(
Expand All @@ -37,10 +39,12 @@ fun Task.runDataConnectExecutable(
object : DataConnectExecutableConfig {
override var outputDirectory: File? = null
override var connectors: Collection<String> = emptyList()
override var connectorId: Collection<String> = emptyList()
override var listen: String? = null
override var localConnectionString: String? = null
override var logFile: File? = null
override var schemaExtensionsOutputEnabled: Boolean? = null
override var platform: String? = null
}
.apply(configure)

Expand Down Expand Up @@ -76,7 +80,13 @@ fun Task.runDataConnectExecutable(
args("-connectors=${it.joinToString(",")}")
}
}
config.connectorId.let {
if (it.isNotEmpty()) {
args("-connector_id=${it.joinToString(",")}")
}
}
config.listen?.let { args("-listen=${it}") }
config.platform?.let { args("-platform=${it}") }
config.localConnectionString?.let { args("-local_connection_string=${it}") }
config.schemaExtensionsOutputEnabled?.let { args("-enable_output_schema_extensions=${it}") }
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,24 +15,30 @@
*/
package com.google.firebase.dataconnect.gradle.plugin

import com.google.firebase.dataconnect.gradle.plugin.DataConnectGenerateCodeTask.CallingConvention
import java.io.File
import javax.inject.Inject
import org.gradle.api.DefaultTask
import org.gradle.api.Task
import org.gradle.api.file.DirectoryProperty
import org.gradle.api.file.RegularFileProperty
import org.gradle.api.provider.Property
import org.gradle.api.provider.Provider
import org.gradle.api.tasks.Input
import org.gradle.api.tasks.InputFile
import org.gradle.api.tasks.InputFiles
import org.gradle.api.tasks.Internal
import org.gradle.api.tasks.Optional
import org.gradle.api.tasks.OutputDirectory
import org.gradle.api.tasks.TaskAction
import org.gradle.process.ExecOperations
import org.slf4j.Logger

abstract class DataConnectGenerateCodeTask : DefaultTask() {

@get:InputFile abstract val dataConnectExecutable: RegularFileProperty

@get:Input abstract val dataConnectExecutableCallingConvention: Property<CallingConvention>

@get:Optional @get:InputFiles abstract val configDirectory: DirectoryProperty

@get:Input abstract val connectors: Property<Collection<String>>
Expand All @@ -43,16 +49,32 @@ abstract class DataConnectGenerateCodeTask : DefaultTask() {

@get:Optional @get:InputFile abstract val ktfmtJarFile: RegularFileProperty

@get:Inject abstract val execOperations: ExecOperations

/**
* The subcommand of the Data Connect executable to use to perform code generation.
*
* In August 2025 the subcommand was changed by cl/795582011 from "gradle generate" to "sdk
* generate -platform=kotlin". The "gradle generate" command was last supported in version 2.11.0
* of the Data Connect executable.
*/
enum class CallingConvention {
GRADLE,
SDK_GENERATE,
}

@TaskAction
fun run() {
val dataConnectExecutable: File = dataConnectExecutable.get().asFile
val dataConnectExecutableCallingConvention = dataConnectExecutableCallingConvention.get()
val configDirectory: File? = configDirectory.orNull?.asFile
val connectors: Collection<String> = connectors.get().distinct().sorted()
val buildDirectory: File = buildDirectory.get().asFile
val outputDirectory: File = outputDirectory.get().asFile
val ktfmtJarFile: File? = ktfmtJarFile.orNull?.asFile

logger.info("dataConnectExecutable={}", dataConnectExecutable.absolutePath)
logger.info("dataConnectExecutableCallingConvention={}", dataConnectExecutableCallingConvention)
logger.info("configDirectory={}", configDirectory?.absolutePath)
logger.info("connectors={}", connectors.joinToString(", "))
logger.info("buildDirectory={}", buildDirectory.absolutePath)
Expand All @@ -69,14 +91,26 @@ abstract class DataConnectGenerateCodeTask : DefaultTask() {
return
}

val subCommand =
when (dataConnectExecutableCallingConvention) {
CallingConvention.GRADLE -> listOf("gradle", "generate")
CallingConvention.SDK_GENERATE -> listOf("sdk", "generate")
}

runDataConnectExecutable(
dataConnectExecutable = dataConnectExecutable,
subCommand = listOf("gradle", "generate"),
subCommand = subCommand,
configDirectory = configDirectory,
) {
this.connectors = connectors
when (dataConnectExecutableCallingConvention) {
CallingConvention.GRADLE -> this.connectors = connectors
CallingConvention.SDK_GENERATE -> this.connectorId = connectors
}
this.outputDirectory = outputDirectory
this.logFile = File(buildDirectory, "codegen.log.txt")
if (dataConnectExecutableCallingConvention == CallingConvention.SDK_GENERATE) {
this.platform = "kotlin"
}
}

if (ktfmtJarFile !== null) {
Expand All @@ -92,7 +126,7 @@ abstract class DataConnectGenerateCodeTask : DefaultTask() {
}
}

private fun Task.runKtfmt(
private fun DataConnectGenerateCodeTask.runKtfmt(
ktfmtJarFile: File,
directory: File,
logFile: File,
Expand Down Expand Up @@ -123,3 +157,80 @@ private fun Task.runKtfmt(
}
}
}

fun DataConnectGenerateCodeTask.detectedCallingConvention(
dataConnectExecutable: RegularFileProperty = this.dataConnectExecutable,
buildDirectory: DirectoryProperty = this.buildDirectory,
execOperations: ExecOperations = this.execOperations,
logger: Logger = this.logger
): Provider<CallingConvention> =
dataConnectExecutable.map {
determineCallingConvention(
dataConnectExecutable = it.asFile,
workDirectory = File(buildDirectory.get().asFile, "determineCallingConvention"),
execOperations = execOperations,
logger = logger,
)
}

private fun determineCallingConvention(
dataConnectExecutable: File,
workDirectory: File,
execOperations: ExecOperations,
logger: Logger,
): CallingConvention {
logger.info(
"Determining calling convention of Data Connect executable: {}",
dataConnectExecutable.absolutePath
)

val callingConventionResults =
CallingConvention.entries.map { callingConvention ->
val logFile =
File(workDirectory, "$callingConvention.log.txt").also { it.parentFile.mkdirs() }
logger.info(
"Testing {} for support of calling convention {} (log file: {})",
dataConnectExecutable.absolutePath,
callingConvention,
logFile.absolutePath
)

val exitCode: Int =
logFile.outputStream().use { logFileStream ->
execOperations
.exec { execSpec ->
execSpec.run {
executable(dataConnectExecutable)
isIgnoreExitValue = true
standardOutput = logFileStream
errorOutput = logFileStream
when (callingConvention) {
CallingConvention.GRADLE -> args("gradle", "help", "generate")
CallingConvention.SDK_GENERATE -> args("sdk", "help", "generate")
}
}
}
.exitValue
}

val callingConventionSupported = exitCode == 0
logger.info(
"Testing {} for support of calling convention {} completed: {} (exitCode={})",
dataConnectExecutable.absolutePath,
callingConvention,
callingConventionSupported,
exitCode
)
Pair(callingConvention, callingConventionSupported)
}

val supportedCallingConventions: List<CallingConvention> =
callingConventionResults.filter { it.second }.map { it.first }
return supportedCallingConventions.singleOrNull()
?: throw DataConnectGradleException(
"d24j9dm3r6",
"could not detect calling convention of Data Connect executable ${dataConnectExecutable.absolutePath}: " +
"found ${supportedCallingConventions.size} supported calling conventions, but expected exactly 1: " +
supportedCallingConventions.joinToString(", ")
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,7 @@ abstract class DataConnectGradlePlugin : Plugin<Project> {
connectors.set(dataConnectProviders.connectors)
buildDirectory.set(baseBuildDirectory.map { it.dir("generateCode") })
ktfmtJarFile.set(dataConnectProviders.ktfmtJarFile)
dataConnectExecutableCallingConvention.set(detectedCallingConvention())
}

variant.sources.java!!.addGeneratedSourceDirectory(
Expand Down