Skip to content

Commit

Permalink
Merge branch 'main' into ks/UpdatingDescriptions
Browse files Browse the repository at this point in the history
  • Loading branch information
KevinSchildhorn committed Dec 19, 2024
2 parents 0afd3bc + 53aa73a commit 0e308d8
Show file tree
Hide file tree
Showing 8 changed files with 163 additions and 24 deletions.
4 changes: 2 additions & 2 deletions gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ SONATYPE_HOST=DEFAULT
RELEASE_SIGNING_ENABLED=true

GROUP=co.touchlab.kmmbridge
VERSION_NAME=1.1.0-a4
VERSION_NAME_3x=0.3.7

VERSION_NAME=1.2.0

POM_URL=https://github.com/touchlab/KMMBridge
POM_DESCRIPTION=KMP Xcode XCFramework Packaging and tooling
Expand Down
1 change: 1 addition & 0 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ mavenPublish = "0.30.0"
aws = { module = "software.amazon.awssdk:s3", version = "2.23.8" }
okhttp = { module = "com.squareup.okhttp3:okhttp", version = "4.12.0" }
gson = { module = "com.google.code.gson:gson", version = "2.10.1" }
kotlin-gradle-plugin = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin-api", version.ref = "kotlin" }

[plugins]
kotlin = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ package co.touchlab.kmmbridge.github
import co.touchlab.kmmbridge.KmmBridgeExtension
import co.touchlab.kmmbridge.artifactmanager.ArtifactManager
import co.touchlab.kmmbridge.github.internal.GithubCalls
import co.touchlab.kmmbridge.github.internal.githubArtifactIdentifierName
import co.touchlab.kmmbridge.github.internal.githubArtifactReleaseId
import co.touchlab.kmmbridge.github.internal.githubPublishToken
import co.touchlab.kmmbridge.github.internal.githubRepo
import org.gradle.api.GradleException
Expand All @@ -12,9 +14,14 @@ import org.gradle.api.tasks.Input
import org.gradle.api.tasks.TaskProvider
import org.gradle.kotlin.dsl.getByType
import java.io.File

internal class GithubReleaseArtifactManager(
private val repository: String?, private val releaseString: String?, private val useExistingRelease: Boolean
import kotlin.properties.Delegates

open class GithubReleaseArtifactManager(
private val repository: String?,
private val releaseString: String?,
@Deprecated("Releases should be created externally. This parameter controls the flow for releases created " +
"by this class, which will eventually be unsupported.")
private val useExistingRelease: Boolean
) : ArtifactManager {

@get:Input
Expand All @@ -26,52 +33,69 @@ internal class GithubReleaseArtifactManager(
@get:Input
lateinit var frameworkName: String

@get:Input
lateinit var artifactIdentifierName: String

@get:Input
var artifactReleaseId by Delegates.notNull<Int>()

// TODO: This value is stored in the config cache. It is encrypted, but this still feels insecure. Review alternatives.
// https://docs.gradle.org/current/userguide/configuration_cache.html#config_cache:secrets
lateinit var githubPublishToken: String

override fun configure(
project: Project,
version: String,
uploadTask: TaskProvider<Task>,
kmmPublishTask: TaskProvider<Task>
project: Project, version: String, uploadTask: TaskProvider<Task>, kmmPublishTask: TaskProvider<Task>
) {
this.releaseVersion = releaseString ?: project.version.toString()
this.repoName = this.repository ?: project.githubRepo
this.githubPublishToken = project.githubPublishToken
this.frameworkName = project.kmmBridgeExtension.frameworkName.get()
artifactReleaseId = project.githubArtifactReleaseId?.toInt() ?: 0
this.artifactIdentifierName = project.githubArtifactIdentifierName ?: ""
}

override fun deployArtifact(task: Task, zipFilePath: File, version: String): String {
val existingReleaseId = GithubCalls.findReleaseId(
githubPublishToken, repoName, releaseVersion
)
val uploadReleaseId = if (artifactReleaseId == 0) {
val existingReleaseId = GithubCalls.findReleaseId(
githubPublishToken, repoName, releaseVersion
)

task.logger.info("existingReleaseId: $existingReleaseId")
task.logger.info("existingReleaseId: $existingReleaseId")

if (existingReleaseId != null && !useExistingRelease) {
throw GradleException("Release for '$releaseVersion' exists. Set 'useExistingRelease = true' to update existing releases.")
}
if (existingReleaseId != null && !useExistingRelease) {
throw GradleException("Release for '$releaseVersion' exists. Set 'useExistingRelease = true' to update existing releases.")
}

val idReply: Int = existingReleaseId ?: GithubCalls.createRelease(
githubPublishToken, repoName, releaseVersion, null
)
val idReply: Int = existingReleaseId ?: GithubCalls.createRelease(
githubPublishToken, repoName, releaseVersion, null
)

task.logger.info("GitHub Release created with id: $idReply")
task.logger.info("GitHub Release created with id: $idReply")

idReply
} else {
artifactReleaseId
}

val fileName = artifactName(version, useExistingRelease)

val uploadUrl = GithubCalls.uploadZipFile(githubPublishToken, zipFilePath, repoName, idReply, fileName)
val uploadUrl = GithubCalls.uploadZipFile(githubPublishToken, zipFilePath, repoName, uploadReleaseId, fileName)
return "${uploadUrl}.zip"
}

private fun artifactName(versionString: String, useExistingRelease: Boolean): String {
return if (useExistingRelease) {
"$frameworkName-${versionString}-${(System.currentTimeMillis() / 1000)}.xcframework.zip"
} else {
"$frameworkName.xcframework.zip"
uploadZipFileName(versionString)
}
}

open fun uploadZipFileName(versionString: String) = if (artifactIdentifierName.isNotEmpty()) {
"$frameworkName-${artifactIdentifierName}.xcframework.zip"
} else {
"$frameworkName.xcframework.zip"
}
}

internal val Project.kmmBridgeExtension get() = extensions.getByType<KmmBridgeExtension>()
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,12 @@ internal val Project.githubPublishToken
get() = (project.property("GITHUB_PUBLISH_TOKEN")
?: throw IllegalArgumentException("KMMBridge Github operations need property GITHUB_PUBLISH_TOKEN")) as String

internal val Project.githubArtifactReleaseId
get() = project.findStringProperty("GITHUB_ARTIFACT_RELEASE_ID")

internal val Project.githubArtifactIdentifierName
get() = project.findStringProperty("GITHUB_ARTIFACT_IDENTIFIER_NAME")

internal val Project.githubRepo: String
get() = githubRepoOrNull
?: throw IllegalArgumentException("KMMBridge Github operations need a repo param or property GITHUB_REPO")
1 change: 1 addition & 0 deletions kmmbridge/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ dependencies {
implementation(libs.gson)

testImplementation(kotlin("test"))
testImplementation(libs.kotlin.gradle.plugin)
testImplementation(gradleTestKit())
testImplementation("commons-io:commons-io:2.18.0")
}
Expand Down
9 changes: 8 additions & 1 deletion kmmbridge/src/main/kotlin/co/touchlab/kmmbridge/KMMBridge.kt
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,14 @@ abstract class BaseKMMBridgePlugin : Plugin<Project> {
val extension = extensions.create<KmmBridgeExtension>(EXTENSION_NAME)

extension.dependencyManagers.convention(emptyList())
extension.buildType.convention(NativeBuildType.RELEASE)

val defaultNativeBuildType = if (project.findStringProperty("NATIVE_BUILD_TYPE") == "DEBUG") {
NativeBuildType.DEBUG
} else {
NativeBuildType.RELEASE
}

extension.buildType.convention(defaultNativeBuildType)

afterEvaluate {
val kmmBridgeExtension = extensions.getByType<KmmBridgeExtension>()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ interface KmmBridgeExtension {

val buildType: Property<NativeBuildType>


@Suppress("unused")
fun Project.s3PublicArtifacts(
region: String,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
package co.touchlab.kmmbridge

import co.touchlab.kmmbridge.artifactmanager.ArtifactManager
import co.touchlab.kmmbridge.artifactmanager.AwsS3PublicArtifactManager
import co.touchlab.kmmbridge.artifactmanager.MavenPublishArtifactManager
import co.touchlab.kmmbridge.dependencymanager.CocoapodsDependencyManager
import co.touchlab.kmmbridge.dependencymanager.DependencyManager
import co.touchlab.kmmbridge.dependencymanager.SpmDependencyManager
import org.gradle.api.Project
import org.gradle.api.provider.Property
import org.gradle.testfixtures.ProjectBuilder
import org.jetbrains.kotlin.gradle.plugin.mpp.NativeBuildType
import kotlin.test.BeforeTest
import kotlin.test.Ignore
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertTrue

class KmmBridgeExtensionTest {
private lateinit var project: Project
private lateinit var extension: TestKmmBridgeExtension

@BeforeTest
fun setup() {
project = ProjectBuilder.builder().build()
extension = TestKmmBridgeExtension(project)
}

@Test
fun `test s3 artifact configuration`() {
extension.apply {
project.s3PublicArtifacts(
region = "us-east-1",
bucket = "test-bucket",
accessKeyId = "test-key",
secretAccessKey = "test-secret"
)
}

val artifactManager = extension.artifactManager.get()
assertTrue(artifactManager is AwsS3PublicArtifactManager)
}

@Test
fun `test maven publish configuration`() {
extension.apply {
project.mavenPublishArtifacts(
repository = "test-repo",
publication = "test-pub",
isMavenCentral = true
)
}

val artifactManager = extension.artifactManager.get()
assertTrue(artifactManager is MavenPublishArtifactManager)
}

@Test
fun `test spm configuration`() {
extension.apply {
project.spm(
spmDirectory = "test-dir",
useCustomPackageFile = true
)
}

val dependencyManager = extension.dependencyManagers.get().first()
assertTrue(dependencyManager is SpmDependencyManager)
}

@Test
@Ignore("CocoaPods plugin not loaded in test environment. Trunk specifically isn't important.")
fun `test cocoapods trunk configuration`() {
extension.apply {
project.cocoapodsTrunk(
allowWarnings = true,
verboseErrors = true
)
}

val dependencyManager = extension.dependencyManagers.get().first()
assertTrue(dependencyManager is CocoapodsDependencyManager)
}

@Test
fun `test property finalization`() {
val testValue = "test-framework"
extension.frameworkName.set(testValue)
extension.frameworkName.finalizeValue()

assertEquals(testValue, extension.frameworkName.get())
assertTrue(extension.frameworkName.isPresent)
}
}

private class TestKmmBridgeExtension(private val project: Project) : KmmBridgeExtension {
override val frameworkName: Property<String> = project.objects.property(String::class.java)
override val dependencyManagers = project.objects.listProperty(DependencyManager::class.java)
override val artifactManager = project.objects.property(ArtifactManager::class.java)
override val buildType: Property<NativeBuildType> = project.objects.property(NativeBuildType::class.java)
}

0 comments on commit 0e308d8

Please sign in to comment.