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
13 changes: 13 additions & 0 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -53,4 +53,17 @@ jobs:
-PsigningInMemoryKeyPassword="${{ secrets.SIGNING_PASSWORD }}" \
-PcentralPortal.username="${{secrets.SONATYPE_USERNAME}}" \
-PcentralPortal.password="${{secrets.SONATYPE_PASSWORD}}"
# This will change Package.swift in Github packages to direct to new maven central KMMBridge zip file
call-kmmbridge-publish:
needs: deploy
permissions:
contents: write
packages: write
uses: touchlab/KMMBridgeGithubWorkflow/.github/workflows/[email protected]
with:
jvmVersion: 17
versionBaseProperty: LIBRARY_VERSION
publishTask: kmmBridgePublish
secrets:
gradle_params: -PsigningInMemoryKey="${{ secrets.SIGNING_KEY }}" -PsigningInMemoryKeyId="${{ secrets.SIGNING_KEY_ID }}" -PsigningInMemoryKeyPassword="${{ secrets.SIGNING_PASSWORD }}"

21 changes: 0 additions & 21 deletions .github/workflows/publish-swift.yml

This file was deleted.

4 changes: 2 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ local.properties
captures
.externalNativeBuild
**/.cxx
**/*.xcodeproj/*
*.xcodeproj/*
**/.swiftpm
!*.xcodeproj/project.pbxproj
Expand All @@ -18,6 +19,5 @@ captures
!*.xcworkspace/contents.xcworkspacedata
**/xcshareddata/WorkspaceSettings.xcsettings
Pods/
plugins/sonatype
dialect/bin
.build
.build
150 changes: 146 additions & 4 deletions PowerSync/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
import co.touchlab.faktory.versionmanager.TimestampVersionManager
import co.touchlab.faktory.artifactmanager.ArtifactManager
import co.touchlab.faktory.capitalized
import co.touchlab.skie.configuration.SuspendInterop
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget
import java.net.URL
import java.security.MessageDigest

plugins {
alias(libs.plugins.kotlinMultiplatform)
alias(libs.plugins.kmmbridge)
alias(libs.plugins.skie)
alias(libs.plugins.mavenPublishPlugin)
id("com.powersync.plugins.sonatype")
}

kotlin {
Expand Down Expand Up @@ -47,12 +51,150 @@ skie {
}

kmmbridge {
mavenPublishArtifacts()
artifactManager.set(SonatypePortalPublishArtifactManager(project, repositoryName = null))
artifactManager.finalizeValue()
spm()
versionManager.set(TimestampVersionManager)
}

// We need this so that when a user includes the package in XCode they are able to
// import the package using Github
if (System.getenv().containsKey("CI")) {
// Setup github publishing based on GitHub action variables
addGithubPackagesRepository()
}
}

// This is required for KMMBridge zip to be uploaded to Sonatype (Maven Central)
// Since this will only ever be used in this build file it does not make sense to make a
// plugin to use this.
class SonatypePortalPublishArtifactManager(
val project: Project,
private val publicationName: String = "KMMBridgeFramework",
artifactSuffix: String = "kmmbridge",
private val repositoryName: String?,
) : ArtifactManager {
private val group: String = project.group.toString().replace(".", "/")
private val kmmbridgeArtifactId =
"${project.name}-${artifactSuffix}"
private val LIBRARY_VERSION: String by project
// This is the URL that will be added to Package.swift in Github package so that
// KMMBridge is downloaded when a user includes the package in XCode
private val MAVEN_CENTRAL_PACKAGE_ZIP_URL = "https://repo1.maven.org/maven2/com/powersync/${kmmbridgeArtifactId.lowercase()}/${LIBRARY_VERSION}/${kmmbridgeArtifactId.lowercase()}-${LIBRARY_VERSION}.zip"

override fun deployArtifact(project: Project, zipFilePath: File, version: String): String {
return MAVEN_CENTRAL_PACKAGE_ZIP_URL
}

override fun configure(
project: Project,
version: String,
uploadTask: TaskProvider<Task>,
kmmPublishTask: TaskProvider<Task>
) {
project.extensions.getByType<PublishingExtension>().publications.create(
publicationName, MavenPublication::class.java
) {
this.version = version
val archiveProvider = project.tasks.named("zipXCFramework", Zip::class.java).flatMap {
it.archiveFile
}
artifact(archiveProvider) {
extension = "zip"
}
artifactId = kmmbridgeArtifactId
}

// Register the task
project.tasks.register<UpdatePackageSwiftChecksumTask>("updatePackageSwiftChecksum") {
artifactId.set(kmmbridgeArtifactId)
zipUrl.set(MAVEN_CENTRAL_PACKAGE_ZIP_URL)
dependsOn("updatePackageSwift")
}

// Make sure this task runs after updatePackageSwift
project.tasks.named("kmmBridgePublish") {
dependsOn("updatePackageSwiftChecksum")
}

publishingTasks().forEach {
uploadTask.configure {
dependsOn(it)
}
}
try {
project.tasks.named("publish").also { task ->
task.configure {
dependsOn(kmmPublishTask)
}
}
} catch (_: UnknownTaskException) {
project.logger.warn("Gradle publish task not found")
}
}

private fun publishingTasks(): List<TaskProvider<Task>> {
val publishingExtension = project.extensions.getByType<PublishingExtension>()

// Either the user has supplied a correct name, or we use the default. If neither is found, fail.
val publicationNameCap =
publishingExtension.publications.getByName(
publicationName
).name.capitalized()

return publishingExtension.repositories.filterIsInstance<MavenArtifactRepository>()
.map { repo ->
val repositoryName = repo.name.capitalized()
val publishTaskName =
"publish${publicationNameCap}PublicationTo${repositoryName}Repository"
// Verify that the "publish" task exists before collecting
project.tasks.named(publishTaskName)
}
}
}

// This task is used to update Package.swift with the checksum of the zip file
// located on maven central.
abstract class UpdatePackageSwiftChecksumTask : DefaultTask() {
@get:Input
abstract val artifactId: Property<String>

@get:Input
abstract val zipUrl: Property<String>

@TaskAction
fun updateChecksum() {
val LIBRARY_VERSION: String by project

val zipFile = project.file("${project.layout.buildDirectory.get()}/tmp/${artifactId.get().lowercase()}-$LIBRARY_VERSION.zip")

// Download the zip file
zipFile.parentFile.mkdirs()
URL(zipUrl.get()).openStream().use { input ->
zipFile.outputStream().use { output ->
input.copyTo(output)
}
}

// Compute the checksum
val checksum = zipFile.inputStream().use { input ->
val digest = MessageDigest.getInstance("SHA-256")
val buffer = ByteArray(8192)
var bytes = input.read(buffer)
while (bytes >= 0) {
digest.update(buffer, 0, bytes)
bytes = input.read(buffer)
}
digest.digest().joinToString("") { "%02x".format(it) }
}

// Update Package.swift
val packageSwiftFile = project.rootProject.file("Package.swift")
val updatedContent = packageSwiftFile.readText().replace(
Regex("let remoteKotlinChecksum = \"[a-f0-9]+\""),
"let remoteKotlinChecksum = \"$checksum\""
)
packageSwiftFile.writeText(updatedContent)

println("Updated Package.swift with new checksum: $checksum")
}
}

3 changes: 2 additions & 1 deletion PowerSync/gradle.properties
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# This needs to be lowercase otherwise there will be a 422 when publishing
POM_ARTIFACT_ID=powersync
POM_NAME=PowerSync Swift Framework
POM_NAME=PowerSync Swift Framework
POM_DESCRIPTION=A PowerSync Kotlin Multiplatform to iOS Swift Bridge.
3 changes: 2 additions & 1 deletion compose/gradle.properties
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
POM_ARTIFACT_ID=compose
POM_NAME=PowerSync Compose Multiplatform factory
POM_NAME=PowerSync Compose Multiplatform factory
POM_DESCRIPTION=A PowerSync Kotlin Multiplatform Compose Library for Android and iOS
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ development=true
RELEASE_SIGNING_ENABLED=true
# Library config
GROUP=com.powersync
LIBRARY_VERSION=0.0.1-ALPHA15
LIBRARY_VERSION=0.0.1-ALPHA17
GITHUB_REPO=https://github.com/powersync-ja/powersync-kotlin.git
# POM
POM_URL=https://github.com/powersync-ja/powersync-kotlin/
Expand Down
2 changes: 1 addition & 1 deletion gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ compose-compiler = "1.5.14"

# plugins
android-gradle-plugin = "8.5.1"
kmmBridge = "0.5.1"
kmmBridge = "0.5.7"
skie = "0.8.2"
maven-publish = "0.27.0"
download-plugin = "5.5.0"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import java.net.URISyntaxException
import java.net.URLEncoder
import java.nio.charset.StandardCharsets
import java.util.Base64

internal abstract class PublishToCentralPortalTask : DefaultTask() {
@get:Input
@get:Optional
Expand Down Expand Up @@ -52,7 +53,7 @@ internal abstract class PublishToCentralPortalTask : DefaultTask() {
"Missing PublishToCentralPortal's `password` and `${SonatypeCentralExtension.SONATYPE_PASSWORD_KEY}` value and `${SonatypeCentralExtension.SONATYPE_PASSWORD_KEY}` property"
)

val outputFile = this.outputFile();
val outputFile = this.outputFile()

val name = URLEncoder.encode(
(project.group
Expand All @@ -78,7 +79,7 @@ internal abstract class PublishToCentralPortalTask : DefaultTask() {
out.write("\r\nContent-Type: application/octet-stream".toByteArray())
out.write("\r\n\r\n".toByteArray())
FileInputStream(outputFile).use { inputStream ->
val buffer: ByteArray = ByteArray(1024)
val buffer = ByteArray(1024)
var available: Long = outputFile.length()
while (available > 0) {
val read: Int = inputStream.read(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
package com.powersync.plugins.sonatype

import org.gradle.api.Action
import org.gradle.api.Project
import org.gradle.api.artifacts.repositories.MavenArtifactRepository
import org.gradle.api.artifacts.repositories.PasswordCredentials
import org.gradle.api.provider.Property
import org.gradle.api.tasks.Optional
import org.gradle.api.tasks.bundling.Zip
Expand All @@ -27,6 +24,7 @@ public abstract class SonatypeCentralExtension(
public const val PUBLISH_LOCAL_TASK_NAME: String = "publishAllPublicationsToSonatypeLocalRepository"
public const val COMPONENT_BUNDLE_TASK_NAME: String = "generateSonatypeComponentBundle"

// This should be stored in your ~/.gradle/gradle.properties
public const val SONATYPE_USERNAME_KEY: String = "centralPortal.username"
public const val SONATYPE_PASSWORD_KEY: String = "centralPortal.password"
}
Expand Down Expand Up @@ -64,4 +62,3 @@ public abstract class SonatypeCentralExtension(
}
}
}

Loading