Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Road to KMP 🚀 #21

Merged
merged 31 commits into from
Mar 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
6e2ead9
refactor(openfeedback): migrate firebase to firebase KMP.
GerardPaligot Nov 8, 2023
7c917d6
refactor(openfeedback): migrate to KMP.
GerardPaligot Nov 23, 2023
49ece40
refactor: migrate Compose to Compose multiplatform.
GerardPaligot Nov 24, 2023
e5cdfa7
refactor: migrate ViewModel to moko mvvm.
GerardPaligot Nov 24, 2023
55e7440
refactor: migrate ViewModel to kmm locale.
GerardPaligot Nov 24, 2023
fa49745
refactor(openfeedback-viewmodel): migrate to KMP.
GerardPaligot Nov 24, 2023
1d766fa
refactor(openfeedback-m3): use moko resources compose to load res.
GerardPaligot Nov 25, 2023
270b7e3
refactor(openfeedback-m3): migrate to KMP.
GerardPaligot Nov 25, 2023
4da227b
refactor(openfeedback-m2): remove the module.
GerardPaligot Nov 25, 2023
9d54c2d
chore: upgrade Kotlin to 1.9.20 and Compose 1.5.11.
GerardPaligot Nov 25, 2023
6543356
feat(openfeedback): support ios target.
GerardPaligot Nov 26, 2023
4c40137
feat(openfeedback-viewmodel): support ios target.
GerardPaligot Nov 26, 2023
9dbc707
feat(openfeedback-m3): support ios target.
GerardPaligot Nov 26, 2023
6930a45
update Gradle
martinbonnin Mar 24, 2024
912ea85
sample-app -> sample-app-android
martinbonnin Mar 24, 2024
23ab0c1
remove cocoapods
martinbonnin Mar 24, 2024
d4fbfd4
Simplify firebase setup
martinbonnin Mar 24, 2024
256019e
move libs.versions.toml to its standard location
martinbonnin Mar 24, 2024
ecc6424
bump versions
martinbonnin Mar 24, 2024
1784172
bump a bunch of dependencies
martinbonnin Mar 24, 2024
28759f8
remove warnings
martinbonnin Mar 24, 2024
7b99782
update credentials
martinbonnin Mar 24, 2024
b218ca8
Fix crash if no user vote is present
martinbonnin Mar 24, 2024
eecef9c
add sample-app-shared
martinbonnin Mar 24, 2024
8a08d27
Add iOS app
martinbonnin Mar 24, 2024
c9aab43
wip
martinbonnin Mar 24, 2024
b4d2c4b
wip
martinbonnin Mar 24, 2024
1692c7b
wip
martinbonnin Mar 25, 2024
6855591
fix Firebase init
martinbonnin Mar 25, 2024
878bad2
remove kotlin-dsl
martinbonnin Mar 25, 2024
ea18d38
make publishToMavenLocal work again
martinbonnin Mar 25, 2024
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
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,8 @@ repositories {
val openfeedbackVersion = "0.1.2"
dependencies {
// Material 3
implementation("io.openfeedback:feedback-android-sdk-m3:$openfeedbackVersion")
implementation("io.openfeedback:feedback-sdk-m3:$openfeedbackVersion")
// ViewModel
implementation("io.openfeedback:feedback-android-sdk-viewmodel:$openfeedbackVersion")
implementation("io.openfeedback:feedback-sdk-viewmodel:$openfeedbackVersion")
}
```
26 changes: 7 additions & 19 deletions build-logic/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,34 +1,22 @@
plugins {
`embedded-kotlin`
`kotlin-dsl`
`java-gradle-plugin`
}

group = "build-logic"

repositories {
mavenCentral()
google()
gradlePluginPortal()
}

dependencies {
implementation(gradleApi())
implementation(libs.vespene)
implementation(libs.kotlin.coroutines.core)
implementation(libs.android.gradle.plugin)
implementation(libs.kotlin.gradle.plugin)
}

gradlePlugin {
plugins {
register("io.openfeedback.plugins.lib") {
id = "io.openfeedback.plugins.lib"
implementationClass = "io.openfeedback.plugins.LibraryPlugin"
}
register("io.openfeedback.plugins.compose.lib") {
id = "io.openfeedback.plugins.compose.lib"
implementationClass = "io.openfeedback.plugins.ComposeLibraryPlugin"
}
register("io.openfeedback.plugins.app") {
id = "io.openfeedback.plugins.app"
implementationClass = "io.openfeedback.plugins.AppPlugin"
}
}
implementation(libs.kotlin.serialization.plugin)
implementation(libs.moko.gradle.plugin)
implementation(libs.jetbrains.compose)
}
3 changes: 2 additions & 1 deletion build-logic/settings.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
rootProject.name = "build-logic"
enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS")

dependencyResolutionManagement {
versionCatalogs {
create("libs") {
from(files("../libs.versions.toml"))
from(files("../gradle/libs.versions.toml"))
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
package io.openfeedback

object EnvVarKeys {
object Nexus {
const val username = "SONATYPE_NEXUS_USERNAME"
Expand All @@ -16,4 +14,4 @@ object EnvVarKeys {
const val event = "GITHUB_EVENT_NAME"
const val ref = "GITHUB_REF"
}
}
}
23 changes: 23 additions & 0 deletions build-logic/src/main/kotlin/accessors.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import org.gradle.api.Project
import org.gradle.api.plugins.ExtensionAware
import org.jetbrains.compose.ComposePlugin
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension


inline fun <reified T> Project.extensionOrNull(): T? {
return extensions.findByType(T::class.java)
}

inline fun <reified T> Project.extension(): T {
return extensionOrNull<T>() ?: error("No extension of type '${T::class.java.name}")
}

inline fun <reified T> Project.extension(block: T.() -> Unit) {
extension<T>().apply(block)
}


val KotlinMultiplatformExtension.compose: ComposePlugin.Dependencies
get() {
return (this as ExtensionAware).extensions.getByName("compose") as ComposePlugin.Dependencies
}
221 changes: 221 additions & 0 deletions build-logic/src/main/kotlin/internal/Publishing.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,221 @@
package internal

import EnvVarKeys
import applyPublishingPlugin
import applySigningPlugin
import extension
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.withTimeout
import net.mbonnin.vespene.lib.NexusStagingClient
import org.gradle.api.Project
import org.gradle.api.Task
import org.gradle.api.UnknownDomainObjectException
import org.gradle.api.artifacts.dsl.RepositoryHandler
import org.gradle.api.logging.LogLevel
import org.gradle.api.plugins.ExtensionContainer
import org.gradle.api.provider.Provider
import org.gradle.api.publish.PublishingExtension
import org.gradle.api.publish.maven.MavenPublication
import org.gradle.api.tasks.TaskProvider
import org.gradle.plugins.signing.Sign
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinAndroidTarget
import kotlin.time.Duration.Companion.minutes

internal fun Project.configurePublications(
publishing: PublishingExtension,
artifactName: String
) {
val project = this

publishing.publications.configureEach {
(it as MavenPublication).apply {
groupId = "io.openfeedback"
version = project.rootProject.version.toString()
artifactId = artifactName

pom {
it.name.set(artifactName)

it.description.set(artifactId)
it.url.set("https://github.com/paug/openfeedback-android-sdk")

it.scm {
it.url.set("https://github.com/paug/openfeedback-android-sdk")
it.connection.set("https://github.com/paug/openfeedback-android-sdk")
it.developerConnection.set("https://github.com/paug/openfeedback-android-sdk")
}

it.licenses {
it.license {
it.name.set("MIT License")
it.url.set("https://github.com/paug/openfeedback-android-sdk/blob/master/LICENSE")
}
}

it.developers {
it.developer {
it.id.set("openfeedback team")
it.name.set("openfeedback team")
}
}
}
}
}
}


internal fun Project.configurePublishingInternal(
androidTarget: KotlinAndroidTarget
) {
val publishing = applyPublishingPlugin()

/**
* Signing
*/
val privateKey = System.getenv(EnvVarKeys.GPG.privateKey)
val password = System.getenv(EnvVarKeys.GPG.password)
applySigningPlugin().apply {
// GPG_PRIVATE_KEY should contain the armoured private key that starts with -----BEGIN PGP PRIVATE KEY BLOCK-----
// It can be obtained with gpg --armour --export-secret-keys KEY_ID
useInMemoryPgpKeys(
privateKey,
password
)
sign(publishing.publications)
}

tasks.withType(Sign::class.java).configureEach {
it.isEnabled = !privateKey.isNullOrBlank()
}

/**
* Android publication
*/
androidTarget.apply {
publishLibraryVariants("release")
}

/**
* Pom
*/
configurePublications(
publishing = publishing,
artifactName = name
)

/**
* Repositories
*/
publishing.repositories {
it.mavenSonatypeSnapshot(project = project)
it.mavenSonatypeStaging(project = project)
}

rootProject.tasks.named("ossStagingRelease").configure {
it.dependsOn(this@configurePublishingInternal.tasks.named("publishAllPublicationsToOssStagingRepository"))
}
}

private fun Project.getOrCreateRepoIdTask(): TaskProvider<Task> {
return try {
rootProject.tasks.named("createStagingRepo")
} catch (e: UnknownDomainObjectException) {
rootProject.tasks.register("createStagingRepo") {
it.outputs.file(rootProject.layout.buildDirectory.file("stagingRepoId"))

it.doLast {
val repoId = runBlocking {
nexusStagingClient.createRepository(
profileId = System.getenv(EnvVarKeys.Nexus.profileId),
description = "io.openfeedback ${rootProject.version}"
)
}
logger.log(LogLevel.LIFECYCLE, "repo created: $repoId")
it.outputs.files.singleFile.writeText(repoId)
}
}
}
}

fun Project.publishIfNeededTaskProvider(): TaskProvider<Task> {
return try {
tasks.named("publishIfNeeded")
} catch (ignored: Exception) {
tasks.register("publishIfNeeded")
}
}

private val baseUrl = "https://s01.oss.sonatype.org/service/local/"

private val nexusStagingClient by lazy {
NexusStagingClient(
baseUrl = baseUrl,
username = System.getenv(EnvVarKeys.Nexus.username)
?: error("please set the ${EnvVarKeys.Nexus.username} environment variable"),
password = System.getenv(EnvVarKeys.Nexus.password)
?: error("please set the ${EnvVarKeys.Nexus.password} environment variable"),
)
}

fun Project.getOrCreateRepoId(): Provider<String> {
return getOrCreateRepoIdTask().map {
it.outputs.files.singleFile.readText()
}
}

fun Project.getOrCreateRepoUrl(): Provider<String> {
return getOrCreateRepoId().map { "${baseUrl}staging/deployByRepositoryId/$it/" }
}

fun Task.closeAndReleaseStagingRepository(repoId: String) {
runBlocking {
logger.log(LogLevel.LIFECYCLE, "Closing repository $repoId")
nexusStagingClient.closeRepositories(listOf(repoId))
withTimeout(5.minutes) {
nexusStagingClient.waitForClose(repoId, 1000) {
logger.log(LogLevel.LIFECYCLE, ".")
}
}
nexusStagingClient.releaseRepositories(listOf(repoId), true)
}
}

internal fun Project.registerReleaseTask(name: String): TaskProvider<Task> {
val task = try {
rootProject.tasks.named(name)
} catch (e: UnknownDomainObjectException) {
val repoId = getOrCreateRepoId()
rootProject.tasks.register(name) {
it.inputs.property(
"repoId",
repoId
)
it.doLast {
it.closeAndReleaseStagingRepository(it.inputs.properties.get("repoId") as String)
}
}
}

return task
}

fun RepositoryHandler.mavenSonatypeSnapshot(project: Project) = maven {
it.name = "ossSnapshots"
it.url = project.uri("https://s01.oss.sonatype.org/content/repositories/snapshots/")
it.credentials {
it.username = System.getenv(EnvVarKeys.Nexus.username)
it.password = System.getenv(EnvVarKeys.Nexus.password)
}
}

fun RepositoryHandler.mavenSonatypeStaging(project: Project) = maven {
it.name = "ossStaging"
it.setUrl {
project.uri(project.getOrCreateRepoUrl())
}
it.credentials {
it.username = System.getenv(EnvVarKeys.Nexus.username)
it.password = System.getenv(EnvVarKeys.Nexus.password)
}
}

10 changes: 0 additions & 10 deletions build-logic/src/main/kotlin/io/openfeedback/OpenFeedback.kt

This file was deleted.

This file was deleted.

Loading
Loading