Skip to content

Commit 667ca6b

Browse files
committed
Simplify publishing for Swift SDK
1 parent db76b6d commit 667ca6b

File tree

7 files changed

+118
-225
lines changed

7 files changed

+118
-225
lines changed

.github/workflows/deploy-swit.yml

+96
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
name: Create Swift release
2+
3+
on:
4+
push:
5+
# TODO Remove
6+
branches:
7+
- refactor-swift-release
8+
# tags:
9+
# - 'v[0-9]+.[0-9]+.[0-9]+SWIFT'
10+
11+
jobs:
12+
draft_release:
13+
name: Create Draft Release on GitHub
14+
runs-on: ubuntu-latest
15+
outputs:
16+
tag: ${{ steps.tag.outputs.tag }}
17+
steps:
18+
- uses: actions/checkout@v4
19+
with:
20+
fetch-depth: 0
21+
22+
- name: Set tag name
23+
id: tag
24+
# TODO Remove, adding this for testing
25+
run: |
26+
tag="1.1.0+SWIFT"
27+
echo "tag=$tag" >> $GITHUB_OUTPUT
28+
# run: |
29+
# tag=$(basename "${{ github.ref }}")
30+
# echo "tag=$tag" >> $GITHUB_OUTPUT
31+
- name: Create Release
32+
env:
33+
GH_TOKEN: ${{ github.token }}
34+
GH_REPO: ${{ github.repository }}
35+
run: |
36+
tag="${{ steps.tag.outputs.tag }}"
37+
body="Pending release for XCFramework, $tag"
38+
gh release create --draft "$tag" --title "$tag" --notes "$body"
39+
40+
build_xcframeworks:
41+
name: Build XCFrameworks
42+
runs-on: macos-latest
43+
steps:
44+
- uses: actions/checkout@v4
45+
- name: Validate Gradle Wrapper
46+
uses: gradle/wrapper-validation-action@v1
47+
- uses: actions/cache@v3
48+
with:
49+
path: ~/.konan
50+
key: ${{ runner.os }}-${{ hashFiles('**/.lock') }}
51+
- name: Set up JDK 17
52+
uses: actions/setup-java@v3
53+
with:
54+
java-version: '17'
55+
distribution: 'temurin'
56+
- name: Set up Gradle
57+
uses: gradle/actions/setup-gradle@v4
58+
- name: Build frameworks
59+
run: "./gradlew PowerSyncKotlin:buildRelease"
60+
61+
- uses: actions/upload-artifact@v4
62+
with:
63+
name: XCFramework
64+
retention-days: 1 # Only used temporarily
65+
compression-level: 0 # We're already uploading a compressed file
66+
path: PowerSyncKotlin/build/FrameworkArchives/PowersyncKotlinRelease.zip
67+
if-no-files-found: error
68+
69+
add_assets:
70+
needs: [draft_release, build_xcframeworks]
71+
name: Add assets to pending release
72+
runs-on: ubuntu-latest
73+
steps:
74+
- uses: actions/checkout@v4
75+
with:
76+
fetch-depth: 0
77+
- uses: actions/download-artifact@v4
78+
- name: Upload XCFramework
79+
env:
80+
GH_TOKEN: ${{ github.token }}
81+
GH_REPO: ${{ github.repository }}
82+
run: |
83+
gh release upload "${{ needs.draft_release.outputs.tag }}" PowersyncKotlinRelease.zip
84+
85+
- name: "Update checksum"
86+
shell: zsh
87+
run: |
88+
checksums=$(sha256sum PowersyncKotlinRelease.zip)
89+
cat > RELEASE_NOTES <<- NOTES_END
90+
File hashes:
91+
\`\`\`
92+
$checksums
93+
\`\`\`
94+
NOTES_END
95+
96+
gh release edit "${{ needs.draft_release.outputs.tag }}" -F RELEASE_NOTES

.github/workflows/deploy.yml

-14
Original file line numberDiff line numberDiff line change
@@ -38,17 +38,3 @@ jobs:
3838
-Ppowersync.binaries.allPlatforms="true" \
3939
publishAllPublicationsToSonatypeRepository
4040
shell: bash
41-
# This will change Package.swift in Github packages to direct to new maven central KMMBridge zip file
42-
call-kmmbridge-publish:
43-
needs: deploy
44-
permissions:
45-
contents: write
46-
packages: write
47-
uses: touchlab/KMMBridgeGithubWorkflow/.github/workflows/[email protected]
48-
with:
49-
jvmVersion: 17
50-
versionBaseProperty: SWIFT_LIBRARY_VERSION
51-
publishTask: kmmBridgePublish
52-
secrets:
53-
gradle_params: -PsigningInMemoryKey="${{ secrets.SIGNING_KEY }}" -PsigningInMemoryKeyId="${{ secrets.SIGNING_KEY_ID }}" -PsigningInMemoryKeyPassword="${{ secrets.SIGNING_PASSWORD }}"
54-

Package.swift

-25
This file was deleted.

PowerSyncKotlin/build.gradle.kts

+22-178
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,15 @@
1-
import co.touchlab.faktory.KmmBridgeExtension
2-
import co.touchlab.faktory.artifactmanager.ArtifactManager
3-
import co.touchlab.faktory.capitalized
41
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget
5-
import java.security.MessageDigest
2+
import org.jetbrains.kotlin.gradle.plugin.mpp.apple.XCFramework
63

74
plugins {
85
alias(libs.plugins.kotlinMultiplatform)
9-
alias(libs.plugins.kmmbridge)
106
alias(libs.plugins.skie)
11-
alias(libs.plugins.mavenPublishPlugin)
127
alias(libs.plugins.kotlinter)
13-
id("com.powersync.plugins.sonatype")
148
}
159

1610
kotlin {
11+
val xcf = XCFramework()
12+
1713
listOf(
1814
iosX64(),
1915
iosArm64(),
@@ -22,8 +18,14 @@ kotlin {
2218
macosX64(),
2319
).forEach {
2420
it.binaries.framework {
21+
baseName = "PowerSyncKotlin"
22+
xcf.add(this)
23+
2524
export(project(":core"))
2625
isStatic = true
26+
27+
binaryOption("bundleId", "PowerSyncKotlin")
28+
binaryOption("bundleVersion", project.version.toString())
2729
}
2830
}
2931

@@ -64,180 +66,22 @@ configurations.all {
6466
}
6567
}
6668

67-
kmmbridge {
68-
artifactManager.set(SonatypePortalPublishArtifactManager(project, repositoryName = null))
69-
artifactManager.finalizeValue()
70-
spm()
71-
}
72-
73-
// We need this so that when a user includes the package in XCode they are able to
74-
// import the package using Github
75-
if (System.getenv().containsKey("CI")) {
76-
// Setup github publishing based on GitHub action variables
77-
addGithubPackagesRepository()
78-
}
79-
80-
// This is required for KMMBridge zip to be uploaded to Sonatype (Maven Central)
81-
// Since this will only ever be used in this build file it does not make sense to make a
82-
// plugin to use this.
83-
class SonatypePortalPublishArtifactManager(
84-
val project: Project,
85-
private val publicationName: String = "KMMBridgeFramework",
86-
artifactSuffix: String = "kmmbridge",
87-
private val repositoryName: String?
88-
) : ArtifactManager {
89-
private val group: String = project.group.toString().replace(".", "/")
90-
private val kmmbridgeArtifactId =
91-
"${project.name}-$artifactSuffix"
92-
private val zipName = "powersync-$artifactSuffix"
93-
private val LIBRARY_VERSION: String by project
94-
95-
// This is the URL that will be added to Package.swift in Github package so that
96-
// KMMBridge is downloaded when a user includes the package in XCode
97-
private val MAVEN_CENTRAL_PACKAGE_ZIP_URL = "https://repo1.maven.org/maven2/com/powersync/${zipName}/${LIBRARY_VERSION}/${zipName}-${LIBRARY_VERSION}.zip"
98-
99-
override fun deployArtifact(
100-
project: Project,
101-
zipFilePath: File,
102-
version: String
103-
): String = MAVEN_CENTRAL_PACKAGE_ZIP_URL
104-
105-
override fun configure(
106-
project: Project,
107-
version: String,
108-
uploadTask: TaskProvider<Task>,
109-
kmmPublishTask: TaskProvider<Task>
110-
) {
111-
val zipXCFramework = project.tasks.named<Zip>("zipXCFramework")
112-
zipXCFramework.configure {
113-
// KMMBridge uses the Gradle Zip tasks to create XCFramework archives, but Gradle
114-
// doesn't support symlinks. XCFrameworks for macOS need to use symlinks though, so we
115-
// patch the task to generate zip files properly.
116-
doLast {
117-
val bridge = project.extensions.getByName<KmmBridgeExtension>("kmmbridge")
118-
val source = project.layout.buildDirectory.map { it.dir("XCFrameworks/${bridge.buildType.get().name}") }.get().asFile
119-
120-
val out = archiveFile.get().asFile
121-
out.delete()
69+
listOf("Debug", "Release").forEach { buildType ->
70+
tasks.register<Exec>("build$buildType") {
71+
group = "build"
72+
description = "Create an XCFramework archive for $buildType"
12273

123-
providers.exec {
124-
executable = "zip"
125-
args("-r", "--symlinks", out.absolutePath, "PowerSyncKotlin.xcframework")
126-
workingDir(source)
127-
}.result.get().assertNormalExitValue()
128-
}
129-
}
130-
131-
project.extensions.getByType<PublishingExtension>().publications.create(
132-
publicationName,
133-
MavenPublication::class.java,
134-
) {
135-
this.version = version
136-
val archiveProvider = zipXCFramework.flatMap {
137-
it.archiveFile
138-
}
139-
artifact(archiveProvider) {
140-
extension = "zip"
141-
}
142-
artifactId = kmmbridgeArtifactId
143-
}
144-
145-
// Register the task
146-
project.tasks.register<UpdatePackageSwiftChecksumTask>("updatePackageSwiftChecksum") {
147-
artifactId.set(kmmbridgeArtifactId)
148-
zipUrl.set(MAVEN_CENTRAL_PACKAGE_ZIP_URL)
149-
dependsOn("updatePackageSwift")
150-
}
151-
152-
// Make sure this task runs after updatePackageSwift
153-
project.tasks.named("kmmBridgePublish") {
154-
dependsOn("updatePackageSwiftChecksum")
155-
}
74+
val originalFramework = tasks.getByName("assemblePowerSyncKotlin${buildType}XCFramework")
75+
dependsOn(originalFramework)
15676

157-
publishingTasks().forEach {
158-
uploadTask.configure {
159-
dependsOn(it)
160-
}
161-
}
162-
try {
163-
project.tasks.named("publish").also { task ->
164-
task.configure {
165-
dependsOn(kmmPublishTask)
166-
}
167-
}
168-
} catch (_: UnknownTaskException) {
169-
project.logger.warn("Gradle publish task not found")
170-
}
171-
}
172-
173-
private fun publishingTasks(): List<TaskProvider<Task>> {
174-
val publishingExtension = project.extensions.getByType<PublishingExtension>()
175-
176-
// Either the user has supplied a correct name, or we use the default. If neither is found, fail.
177-
val publicationNameCap =
178-
publishingExtension.publications
179-
.getByName(
180-
publicationName,
181-
).name
182-
.capitalized()
183-
184-
return publishingExtension.repositories
185-
.filterIsInstance<MavenArtifactRepository>()
186-
.map { repo ->
187-
val repositoryName = repo.name.capitalized()
188-
val publishTaskName =
189-
"publish${publicationNameCap}PublicationTo${repositoryName}Repository"
190-
// Verify that the "publish" task exists before collecting
191-
project.tasks.named(publishTaskName)
192-
}
193-
}
194-
}
195-
196-
// This task is used to update Package.swift with the checksum of the zip file
197-
// located on maven central.
198-
abstract class UpdatePackageSwiftChecksumTask : DefaultTask() {
199-
@get:Input
200-
abstract val artifactId: Property<String>
201-
202-
@get:Input
203-
abstract val zipUrl: Property<String>
204-
205-
@TaskAction
206-
fun updateChecksum() {
207-
val LIBRARY_VERSION: String by project
208-
209-
val zipFile = project.file("${project.layout.buildDirectory.get()}/tmp/${artifactId.get().lowercase()}-$LIBRARY_VERSION.zip")
210-
211-
// Download the zip file
212-
zipFile.parentFile.mkdirs()
213-
project.uri(zipUrl.get()).toURL().openStream().use { input ->
214-
zipFile.outputStream().use { output ->
215-
input.copyTo(output)
216-
}
217-
}
218-
219-
// Compute the checksum
220-
val checksum =
221-
zipFile.inputStream().use { input ->
222-
val digest = MessageDigest.getInstance("SHA-256")
223-
val buffer = ByteArray(8192)
224-
var bytes = input.read(buffer)
225-
while (bytes >= 0) {
226-
digest.update(buffer, 0, bytes)
227-
bytes = input.read(buffer)
228-
}
229-
digest.digest().joinToString("") { "%02x".format(it) }
230-
}
77+
val source = project.layout.buildDirectory.map { it.dir("XCFrameworks/${buildType.lowercase()}") }.get().asFile
78+
val archiveFile = project.layout.buildDirectory.map { it.file("FrameworkArchives/PowersyncKotlin$buildType.zip") }.get().asFile
23179

232-
// Update Package.swift
233-
val packageSwiftFile = project.rootProject.file("Package.swift")
234-
val updatedContent =
235-
packageSwiftFile.readText().replace(
236-
Regex("let remoteKotlinChecksum = \"[a-f0-9]+\""),
237-
"let remoteKotlinChecksum = \"$checksum\"",
238-
)
239-
packageSwiftFile.writeText(updatedContent)
80+
archiveFile.parentFile.mkdirs()
81+
archiveFile.delete()
24082

241-
println("Updated Package.swift with new checksum: $checksum")
83+
executable = "zip"
84+
args("-r", "--symlinks", archiveFile.absolutePath, "PowerSyncKotlin.xcframework")
85+
workingDir(source)
24286
}
24387
}

build.gradle.kts

-2
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,6 @@ plugins {
1010
alias(libs.plugins.androidApplication) apply false
1111
alias(libs.plugins.androidLibrary) apply false
1212
alias(libs.plugins.kotlinMultiplatform) apply false
13-
alias(libs.plugins.cocoapods) apply false
14-
alias(libs.plugins.kmmbridge) apply false
1513
alias(libs.plugins.skie) apply false
1614
alias(libs.plugins.kotlin.jvm) apply false
1715
alias(libs.plugins.kotlin.android) apply false

gradle.properties

-4
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,6 @@ RELEASE_SIGNING_ENABLED=true
1818
# Library config
1919
GROUP=com.powersync
2020
LIBRARY_VERSION=1.1.0
21-
# The Swift KMM bridge artifacts are published to SPM via a unique tag version
22-
# The version is the same as the LIBRARY_VERSION, but with a suffix of +SWIFT
23-
# Please update this when updating the LIBRARY_VERSION
24-
SWIFT_LIBRARY_VERSION=1.1.0+SWIFT
2521
GITHUB_REPO=https://github.com/powersync-ja/powersync-kotlin.git
2622
# POM
2723
POM_URL=https://github.com/powersync-ja/powersync-kotlin/

0 commit comments

Comments
 (0)