chore: add Gradle convention plugin for injecting build-time secrets
This commit is contained in:
@@ -0,0 +1,84 @@
|
|||||||
|
import java.util.Properties
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Injects build-time secrets into `commonMain` so they stay out of version control.
|
||||||
|
*
|
||||||
|
* Each secret is read from the environment first (CI), then from `local.properties`
|
||||||
|
* (local development), and defaults to an empty string when neither provides it —
|
||||||
|
* consumers are expected to degrade gracefully rather than fail.
|
||||||
|
*
|
||||||
|
* The values are emitted as a generated `BuildSecrets` object, available to every
|
||||||
|
* Kotlin target of the module.
|
||||||
|
*/
|
||||||
|
|
||||||
|
plugins {
|
||||||
|
id("org.jetbrains.kotlin.multiplatform")
|
||||||
|
}
|
||||||
|
|
||||||
|
val secretsPackage = "bzh.ajaury.chombev"
|
||||||
|
|
||||||
|
private val localProperties: Provider<Properties> =
|
||||||
|
providers
|
||||||
|
.fileContents(layout.settingsDirectory.file("local.properties"))
|
||||||
|
.asText
|
||||||
|
.map { text -> Properties().apply { load(text.reader()) } }
|
||||||
|
|
||||||
|
/** Resolves a secret from [environmentVariable], falling back to [localPropertyKey], then to an empty string. */
|
||||||
|
fun secret(
|
||||||
|
environmentVariable: String,
|
||||||
|
localPropertyKey: String,
|
||||||
|
): Provider<String> =
|
||||||
|
providers
|
||||||
|
.environmentVariable(environmentVariable)
|
||||||
|
.orElse(localProperties.map { properties -> properties.getProperty(localPropertyKey).orEmpty() })
|
||||||
|
.orElse("")
|
||||||
|
|
||||||
|
// GlitchTip DSN, consumed by initializeSentry() in the shared module.
|
||||||
|
val glitchtipDsn: Provider<String> = secret(environmentVariable = "GLITCHTIP_DSN", localPropertyKey = "glitchtip.dsn")
|
||||||
|
|
||||||
|
val generateBuildSecrets =
|
||||||
|
tasks.register("generateBuildSecrets") {
|
||||||
|
description = "Generates the BuildSecrets object from local.properties and environment variables."
|
||||||
|
|
||||||
|
// Escaped here so the value can be inlined as-is in a Kotlin string literal.
|
||||||
|
val dsn =
|
||||||
|
glitchtipDsn.map { value ->
|
||||||
|
value
|
||||||
|
.replace("\\", "\\\\")
|
||||||
|
.replace("\"", "\\\"")
|
||||||
|
.replace("$", "\${'$'}")
|
||||||
|
}
|
||||||
|
val outputDir = layout.buildDirectory.dir("generated/secrets/commonMain/kotlin")
|
||||||
|
// Kept in locals so the execution-time action never captures the script instance.
|
||||||
|
val packageName = secretsPackage
|
||||||
|
val packagePath = packageName.replace('.', '/')
|
||||||
|
|
||||||
|
inputs.property("glitchtipDsn", dsn)
|
||||||
|
outputs.dir(outputDir)
|
||||||
|
|
||||||
|
doLast {
|
||||||
|
val file =
|
||||||
|
outputDir
|
||||||
|
.get()
|
||||||
|
.asFile
|
||||||
|
.resolve("$packagePath/BuildSecrets.kt")
|
||||||
|
file.parentFile.mkdirs()
|
||||||
|
file.writeText(
|
||||||
|
"""
|
||||||
|
package $packageName
|
||||||
|
|
||||||
|
// Generated by the `gwenedeg.secrets` convention plugin. Do not edit.
|
||||||
|
internal object BuildSecrets {
|
||||||
|
const val GLITCHTIP_DSN: String = "${dsn.get()}"
|
||||||
|
}
|
||||||
|
|
||||||
|
""".trimIndent(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
kotlin {
|
||||||
|
sourceSets.commonMain {
|
||||||
|
kotlin.srcDir(generateBuildSecrets)
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user