Skip to content

Commit 0e308d8

Browse files
Merge branch 'main' into ks/UpdatingDescriptions
2 parents 0afd3bc + 53aa73a commit 0e308d8

File tree

8 files changed

+163
-24
lines changed

8 files changed

+163
-24
lines changed

gradle.properties

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ SONATYPE_HOST=DEFAULT
1818
RELEASE_SIGNING_ENABLED=true
1919

2020
GROUP=co.touchlab.kmmbridge
21-
VERSION_NAME=1.1.0-a4
22-
VERSION_NAME_3x=0.3.7
21+
22+
VERSION_NAME=1.2.0
2323

2424
POM_URL=https://github.com/touchlab/KMMBridge
2525
POM_DESCRIPTION=KMP Xcode XCFramework Packaging and tooling

gradle/libs.versions.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ mavenPublish = "0.30.0"
66
aws = { module = "software.amazon.awssdk:s3", version = "2.23.8" }
77
okhttp = { module = "com.squareup.okhttp3:okhttp", version = "4.12.0" }
88
gson = { module = "com.google.code.gson:gson", version = "2.10.1" }
9+
kotlin-gradle-plugin = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin-api", version.ref = "kotlin" }
910

1011
[plugins]
1112
kotlin = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" }

kmmbridge-github/src/main/kotlin/co/touchlab/kmmbridge/github/GithubReleaseArtifactManager.kt

Lines changed: 44 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ package co.touchlab.kmmbridge.github
33
import co.touchlab.kmmbridge.KmmBridgeExtension
44
import co.touchlab.kmmbridge.artifactmanager.ArtifactManager
55
import co.touchlab.kmmbridge.github.internal.GithubCalls
6+
import co.touchlab.kmmbridge.github.internal.githubArtifactIdentifierName
7+
import co.touchlab.kmmbridge.github.internal.githubArtifactReleaseId
68
import co.touchlab.kmmbridge.github.internal.githubPublishToken
79
import co.touchlab.kmmbridge.github.internal.githubRepo
810
import org.gradle.api.GradleException
@@ -12,9 +14,14 @@ import org.gradle.api.tasks.Input
1214
import org.gradle.api.tasks.TaskProvider
1315
import org.gradle.kotlin.dsl.getByType
1416
import java.io.File
15-
16-
internal class GithubReleaseArtifactManager(
17-
private val repository: String?, private val releaseString: String?, private val useExistingRelease: Boolean
17+
import kotlin.properties.Delegates
18+
19+
open class GithubReleaseArtifactManager(
20+
private val repository: String?,
21+
private val releaseString: String?,
22+
@Deprecated("Releases should be created externally. This parameter controls the flow for releases created " +
23+
"by this class, which will eventually be unsupported.")
24+
private val useExistingRelease: Boolean
1825
) : ArtifactManager {
1926

2027
@get:Input
@@ -26,52 +33,69 @@ internal class GithubReleaseArtifactManager(
2633
@get:Input
2734
lateinit var frameworkName: String
2835

36+
@get:Input
37+
lateinit var artifactIdentifierName: String
38+
39+
@get:Input
40+
var artifactReleaseId by Delegates.notNull<Int>()
41+
2942
// TODO: This value is stored in the config cache. It is encrypted, but this still feels insecure. Review alternatives.
3043
// https://docs.gradle.org/current/userguide/configuration_cache.html#config_cache:secrets
3144
lateinit var githubPublishToken: String
3245

3346
override fun configure(
34-
project: Project,
35-
version: String,
36-
uploadTask: TaskProvider<Task>,
37-
kmmPublishTask: TaskProvider<Task>
47+
project: Project, version: String, uploadTask: TaskProvider<Task>, kmmPublishTask: TaskProvider<Task>
3848
) {
3949
this.releaseVersion = releaseString ?: project.version.toString()
4050
this.repoName = this.repository ?: project.githubRepo
4151
this.githubPublishToken = project.githubPublishToken
4252
this.frameworkName = project.kmmBridgeExtension.frameworkName.get()
53+
artifactReleaseId = project.githubArtifactReleaseId?.toInt() ?: 0
54+
this.artifactIdentifierName = project.githubArtifactIdentifierName ?: ""
4355
}
4456

4557
override fun deployArtifact(task: Task, zipFilePath: File, version: String): String {
46-
val existingReleaseId = GithubCalls.findReleaseId(
47-
githubPublishToken, repoName, releaseVersion
48-
)
58+
val uploadReleaseId = if (artifactReleaseId == 0) {
59+
val existingReleaseId = GithubCalls.findReleaseId(
60+
githubPublishToken, repoName, releaseVersion
61+
)
4962

50-
task.logger.info("existingReleaseId: $existingReleaseId")
63+
task.logger.info("existingReleaseId: $existingReleaseId")
5164

52-
if (existingReleaseId != null && !useExistingRelease) {
53-
throw GradleException("Release for '$releaseVersion' exists. Set 'useExistingRelease = true' to update existing releases.")
54-
}
65+
if (existingReleaseId != null && !useExistingRelease) {
66+
throw GradleException("Release for '$releaseVersion' exists. Set 'useExistingRelease = true' to update existing releases.")
67+
}
5568

56-
val idReply: Int = existingReleaseId ?: GithubCalls.createRelease(
57-
githubPublishToken, repoName, releaseVersion, null
58-
)
69+
val idReply: Int = existingReleaseId ?: GithubCalls.createRelease(
70+
githubPublishToken, repoName, releaseVersion, null
71+
)
5972

60-
task.logger.info("GitHub Release created with id: $idReply")
73+
task.logger.info("GitHub Release created with id: $idReply")
74+
75+
idReply
76+
} else {
77+
artifactReleaseId
78+
}
6179

6280
val fileName = artifactName(version, useExistingRelease)
6381

64-
val uploadUrl = GithubCalls.uploadZipFile(githubPublishToken, zipFilePath, repoName, idReply, fileName)
82+
val uploadUrl = GithubCalls.uploadZipFile(githubPublishToken, zipFilePath, repoName, uploadReleaseId, fileName)
6583
return "${uploadUrl}.zip"
6684
}
6785

6886
private fun artifactName(versionString: String, useExistingRelease: Boolean): String {
6987
return if (useExistingRelease) {
7088
"$frameworkName-${versionString}-${(System.currentTimeMillis() / 1000)}.xcframework.zip"
7189
} else {
72-
"$frameworkName.xcframework.zip"
90+
uploadZipFileName(versionString)
7391
}
7492
}
93+
94+
open fun uploadZipFileName(versionString: String) = if (artifactIdentifierName.isNotEmpty()) {
95+
"$frameworkName-${artifactIdentifierName}.xcframework.zip"
96+
} else {
97+
"$frameworkName.xcframework.zip"
98+
}
7599
}
76100

77101
internal val Project.kmmBridgeExtension get() = extensions.getByType<KmmBridgeExtension>()

kmmbridge-github/src/main/kotlin/co/touchlab/kmmbridge/github/internal/GithubApi.kt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,12 @@ internal val Project.githubPublishToken
3939
get() = (project.property("GITHUB_PUBLISH_TOKEN")
4040
?: throw IllegalArgumentException("KMMBridge Github operations need property GITHUB_PUBLISH_TOKEN")) as String
4141

42+
internal val Project.githubArtifactReleaseId
43+
get() = project.findStringProperty("GITHUB_ARTIFACT_RELEASE_ID")
44+
45+
internal val Project.githubArtifactIdentifierName
46+
get() = project.findStringProperty("GITHUB_ARTIFACT_IDENTIFIER_NAME")
47+
4248
internal val Project.githubRepo: String
4349
get() = githubRepoOrNull
4450
?: throw IllegalArgumentException("KMMBridge Github operations need a repo param or property GITHUB_REPO")

kmmbridge/build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ dependencies {
5757
implementation(libs.gson)
5858

5959
testImplementation(kotlin("test"))
60+
testImplementation(libs.kotlin.gradle.plugin)
6061
testImplementation(gradleTestKit())
6162
testImplementation("commons-io:commons-io:2.18.0")
6263
}

kmmbridge/src/main/kotlin/co/touchlab/kmmbridge/KMMBridge.kt

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,14 @@ abstract class BaseKMMBridgePlugin : Plugin<Project> {
5252
val extension = extensions.create<KmmBridgeExtension>(EXTENSION_NAME)
5353

5454
extension.dependencyManagers.convention(emptyList())
55-
extension.buildType.convention(NativeBuildType.RELEASE)
55+
56+
val defaultNativeBuildType = if (project.findStringProperty("NATIVE_BUILD_TYPE") == "DEBUG") {
57+
NativeBuildType.DEBUG
58+
} else {
59+
NativeBuildType.RELEASE
60+
}
61+
62+
extension.buildType.convention(defaultNativeBuildType)
5663

5764
afterEvaluate {
5865
val kmmBridgeExtension = extensions.getByType<KmmBridgeExtension>()

kmmbridge/src/main/kotlin/co/touchlab/kmmbridge/KmmBridgeExtension.kt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@ interface KmmBridgeExtension {
4242

4343
val buildType: Property<NativeBuildType>
4444

45-
4645
@Suppress("unused")
4746
fun Project.s3PublicArtifacts(
4847
region: String,
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
package co.touchlab.kmmbridge
2+
3+
import co.touchlab.kmmbridge.artifactmanager.ArtifactManager
4+
import co.touchlab.kmmbridge.artifactmanager.AwsS3PublicArtifactManager
5+
import co.touchlab.kmmbridge.artifactmanager.MavenPublishArtifactManager
6+
import co.touchlab.kmmbridge.dependencymanager.CocoapodsDependencyManager
7+
import co.touchlab.kmmbridge.dependencymanager.DependencyManager
8+
import co.touchlab.kmmbridge.dependencymanager.SpmDependencyManager
9+
import org.gradle.api.Project
10+
import org.gradle.api.provider.Property
11+
import org.gradle.testfixtures.ProjectBuilder
12+
import org.jetbrains.kotlin.gradle.plugin.mpp.NativeBuildType
13+
import kotlin.test.BeforeTest
14+
import kotlin.test.Ignore
15+
import kotlin.test.Test
16+
import kotlin.test.assertEquals
17+
import kotlin.test.assertTrue
18+
19+
class KmmBridgeExtensionTest {
20+
private lateinit var project: Project
21+
private lateinit var extension: TestKmmBridgeExtension
22+
23+
@BeforeTest
24+
fun setup() {
25+
project = ProjectBuilder.builder().build()
26+
extension = TestKmmBridgeExtension(project)
27+
}
28+
29+
@Test
30+
fun `test s3 artifact configuration`() {
31+
extension.apply {
32+
project.s3PublicArtifacts(
33+
region = "us-east-1",
34+
bucket = "test-bucket",
35+
accessKeyId = "test-key",
36+
secretAccessKey = "test-secret"
37+
)
38+
}
39+
40+
val artifactManager = extension.artifactManager.get()
41+
assertTrue(artifactManager is AwsS3PublicArtifactManager)
42+
}
43+
44+
@Test
45+
fun `test maven publish configuration`() {
46+
extension.apply {
47+
project.mavenPublishArtifacts(
48+
repository = "test-repo",
49+
publication = "test-pub",
50+
isMavenCentral = true
51+
)
52+
}
53+
54+
val artifactManager = extension.artifactManager.get()
55+
assertTrue(artifactManager is MavenPublishArtifactManager)
56+
}
57+
58+
@Test
59+
fun `test spm configuration`() {
60+
extension.apply {
61+
project.spm(
62+
spmDirectory = "test-dir",
63+
useCustomPackageFile = true
64+
)
65+
}
66+
67+
val dependencyManager = extension.dependencyManagers.get().first()
68+
assertTrue(dependencyManager is SpmDependencyManager)
69+
}
70+
71+
@Test
72+
@Ignore("CocoaPods plugin not loaded in test environment. Trunk specifically isn't important.")
73+
fun `test cocoapods trunk configuration`() {
74+
extension.apply {
75+
project.cocoapodsTrunk(
76+
allowWarnings = true,
77+
verboseErrors = true
78+
)
79+
}
80+
81+
val dependencyManager = extension.dependencyManagers.get().first()
82+
assertTrue(dependencyManager is CocoapodsDependencyManager)
83+
}
84+
85+
@Test
86+
fun `test property finalization`() {
87+
val testValue = "test-framework"
88+
extension.frameworkName.set(testValue)
89+
extension.frameworkName.finalizeValue()
90+
91+
assertEquals(testValue, extension.frameworkName.get())
92+
assertTrue(extension.frameworkName.isPresent)
93+
}
94+
}
95+
96+
private class TestKmmBridgeExtension(private val project: Project) : KmmBridgeExtension {
97+
override val frameworkName: Property<String> = project.objects.property(String::class.java)
98+
override val dependencyManagers = project.objects.listProperty(DependencyManager::class.java)
99+
override val artifactManager = project.objects.property(ArtifactManager::class.java)
100+
override val buildType: Property<NativeBuildType> = project.objects.property(NativeBuildType::class.java)
101+
}

0 commit comments

Comments
 (0)