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
3 changes: 2 additions & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ SONATYPE_HOST=DEFAULT
RELEASE_SIGNING_ENABLED=true

GROUP=co.touchlab.kmmbridge
VERSION_NAME=1.1.1

VERSION_NAME=1.2.0
VERSION_NAME_3x=0.3.7

POM_URL=https://github.com/touchlab/KMMBridge
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
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)
}