Skip to content

Commit

Permalink
Kpg/testing (#266)
Browse files Browse the repository at this point in the history
* Start testing. Fix spm git folder query when there is no git repo.

* Refactor build config and cleanup

* Fix workflow

* Set artificial version for local test publish

* Use newer xcode version

* Fix tests

* Revert mac to latest

* Updates

* Split tests into different test classes

* Add .kotlin to .gitignore

* Clean up API visibility

* Added deploy key helper

* Updated testing

* Verify value

* Fix value read

* Plugin class in jar

* Prep 1.1.0-a2
  • Loading branch information
kpgalligan authored Nov 27, 2024
1 parent 41ff64b commit b833550
Show file tree
Hide file tree
Showing 49 changed files with 1,466 additions and 184 deletions.
35 changes: 35 additions & 0 deletions .github/workflows/build_mac.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
name: Build and Test
on:
pull_request:
push:
workflow_dispatch:

jobs:
build:
runs-on: macos-latest
steps:
- name: Checkout the repo
uses: actions/checkout@v2

- uses: actions/setup-java@v2
with:
distribution: "adopt"
java-version: "17"

- name: Validate Gradle Wrapper
uses: gradle/wrapper-validation-action@v1

- name: Write Faktory Server Code
run: echo ${{ secrets.TOUCHLAB_TEST_ARTIFACT_CODE }} > kmmbridge/TOUCHLAB_TEST_ARTIFACT_CODE

- name: Read Faktory Server Code
run: cat kmmbridge/TOUCHLAB_TEST_ARTIFACT_CODE

- name: Local Publish For Tests
run: ./gradlew publishToMavenLocal --no-daemon --stacktrace --build-cache -PRELEASE_SIGNING_ENABLED=false -PVERSION_NAME=9.9.9

- name: Build
run: ./gradlew build --no-daemon --stacktrace --build-cache

env:
GRADLE_OPTS: -Dkotlin.incremental=false -Dorg.gradle.jvmargs="-Xmx4g -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 -XX:MaxMetaspaceSize=512m"
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,5 @@ build
*.xcbkptlist
!/.idea/codeStyles/*
!/.idea/inspectionProfiles/*
.kotlin
TOUCHLAB_TEST_ARTIFACT_CODE
36 changes: 36 additions & 0 deletions TESTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# KMMBridge Project Tests

Gradle guidance suggests using include builds to test Gradle plugins. However, after a significant effort to avoid JVM classpath and other related issues, we decided to run tests by starting external Gradle builds.

To do that, we need to locally publish KMMBridge, then point tests projects at that new version. For each test:

* A temp folder is constructed
* A sample app project is copied to that folder
* A command line process is run, generally running Gradle to perform whatever task we intend to test

## Publishing KMMBridge locally

We want to publish KMMBridge as version `9.9.9`. This is a fake local version, just for testing. To do that, run the following on the root folder of KMMBridge:

```shell
./gradlew publishToMavenLocal -PVERSION_NAME=9.9.9
```

## Editing the test project

Our simple test project lives at `test-projects/basic`. It points at KMMBridge version `9.9.9`. You should be able to open it directly with IJ or AS.

## Tests

See class `co.touchlab.kmmbridge.SimplePluginTest`. `fun setup()` copies the test project an initializes the test project.

Here is a sample test:

```kotlin
@Test
fun runSpmDevBuild() {
val result = ProcessHelper.runSh("./gradlew spmDevBuild --stacktrace", workingDir = testProjectDir)
logExecResult(result)
assertEquals(0, result.status)
}
```
33 changes: 33 additions & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,37 @@ plugins {
alias(libs.plugins.kotlin) apply false
id("org.jetbrains.kotlin.plugin.allopen") version "1.9.0" apply false
alias(libs.plugins.maven.publish) apply false
}

subprojects {
repositories {
gradlePluginPortal()
mavenCentral()
}

extensions.findByType<org.jetbrains.kotlin.gradle.dsl.KotlinJvmProjectExtension>()?.apply {
jvmToolchain(17)
}

val GROUP: String by project
val VERSION_NAME: String by project

group = GROUP
version = VERSION_NAME

extensions.findByType<com.vanniktech.maven.publish.MavenPublishBaseExtension>()?.apply {
publishToMavenCentral()
val releaseSigningEnabled =
project.properties["RELEASE_SIGNING_ENABLED"]?.toString()?.equals("false", ignoreCase = true) != true
if (releaseSigningEnabled) signAllPublications()
@Suppress("UnstableApiUsage")
pomFromGradleProperties()
configureBasedOnAppliedPlugins()
}

afterEvaluate {
tasks.getByName<Test>("test") {
useJUnitPlatform()
}
}
}
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ org.gradle.jvmargs=-Xmx4g
RELEASE_SIGNING_ENABLED=true

GROUP=co.touchlab.kmmbridge
VERSION_NAME=1.1.0-a1
VERSION_NAME=1.1.0-a2
VERSION_NAME_3x=0.3.7

POM_URL=https://github.com/touchlab/KMMBridge
Expand Down
2 changes: 1 addition & 1 deletion gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
33 changes: 4 additions & 29 deletions kmmbridge-github/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,13 @@

plugins {
`kotlin-dsl`
kotlin("jvm")
alias(libs.plugins.kotlin)
id("org.jetbrains.kotlin.plugin.allopen")
id("java-gradle-plugin")
id("com.vanniktech.maven.publish.base")
alias(libs.plugins.maven.publish)
id("com.gradle.plugin-publish") version "1.0.0"
}

repositories {
gradlePluginPortal()
mavenCentral()
}

@Suppress("UnstableApiUsage")
gradlePlugin {
website = "https://github.com/touchlab/KMMBridge"
Expand All @@ -36,8 +31,8 @@ gradlePlugin {
plugins {
register("kmmbridge-github-plugin") {
id = "co.touchlab.kmmbridge.github"
implementationClass = "co.touchlab.kmmbridge.KMMBridgePlugin"
displayName = "KMMBridge/GitHub for Teams"
implementationClass = "co.touchlab.kmmbridge.github.KMMBridgeGitHubPlugin"
displayName = "KMMBridge/GitHub"
tags = listOf(
"kmm",
"kotlin",
Expand All @@ -62,23 +57,3 @@ dependencies {

testImplementation(kotlin("test"))
}

kotlin {
jvmToolchain(11)
}

val GROUP: String by project
val VERSION_NAME: String by project

group = GROUP
version = VERSION_NAME

mavenPublishing {
publishToMavenCentral()
val releaseSigningEnabled =
project.properties["RELEASE_SIGNING_ENABLED"]?.toString()?.equals("false", ignoreCase = true) != true
if (releaseSigningEnabled) signAllPublications()
@Suppress("UnstableApiUsage")
pomFromGradleProperties()
configureBasedOnAppliedPlugins()
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import org.gradle.api.tasks.TaskProvider
import org.gradle.kotlin.dsl.getByType
import java.io.File

class GithubReleaseArtifactManager(
internal class GithubReleaseArtifactManager(
private val repository: String?, private val releaseString: String?, private val useExistingRelease: Boolean
) : ArtifactManager {

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
package co.touchlab.kmmbridge.github

import co.touchlab.kmmbridge.BaseKMMBridgePlugin
import co.touchlab.kmmbridge.TASK_GROUP_NAME
import co.touchlab.kmmbridge.findStringProperty
import co.touchlab.kmmbridge.github.internal.procRunFailLog
import org.gradle.api.Action
import org.gradle.api.Project
import org.gradle.api.Task
import java.io.File
import java.nio.file.Files

@Suppress("unused")
class KMMBridgeGitHubPlugin : BaseKMMBridgePlugin() {
override fun apply(project: Project) {
super.apply(project)
val githubDeploySourceRepo = project.findStringProperty("githubDeploySourceRepo")
val githubDeployTargetRepo = project.findStringProperty("githubDeployTargetRepo")
if (githubDeploySourceRepo != null && githubDeployTargetRepo != null) {
project.tasks.register("setupDeployKeys") {
group = TASK_GROUP_NAME
description = "Helper task to setup GitHub deploy keys"
outputs.upToDateWhen { false } // This should always run

@Suppress("ObjectLiteralToLambda")
doLast(object : Action<Task> {
override fun execute(t: Task) {
val githubDeployKeyPrefix = project.findStringProperty("githubDeployKeyPrefix") ?: "KMMBridge"

val keyname = "$githubDeployKeyPrefix Key"

val tempDir = Files.createTempDirectory("kmmbridge")
println("Generated temp dir: $tempDir")
val deployKeyName = "deploykey"
val deployKeyPrivateFilePath = File(tempDir.toFile(), deployKeyName)
val deployKeyPublicFilePath = File(tempDir.toFile(), "${deployKeyName}.pub")

try {
project.procRunFailLog(
"ssh-keygen",
"-t",
"ed25519",
"-f",
deployKeyPrivateFilePath.toString(),
"-C",
"[email protected]:$githubDeployTargetRepo",
"-P",
""
)

project.procRunFailLog(
"gh",
"repo",
"deploy-key",
"add",
deployKeyPublicFilePath.toString(),
"-w",
"-R",
githubDeployTargetRepo,
"-t",
keyname
)

project.procRunFailLog(
"gh",
"secret",
"set",
"${githubDeployKeyPrefix}_SSH_KEY",
"--body",
deployKeyPrivateFilePath.readText(),
"-R",
githubDeploySourceRepo
)
} finally {
deployKeyPrivateFilePath.delete()
deployKeyPublicFilePath.delete()
Files.deleteIfExists(tempDir)
}
}
})
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,6 @@ internal val Project.githubPublishTokenOrNull: String?
internal val Project.githubPublishUser: String?
get() = project.findStringProperty("GITHUB_PUBLISH_USER")

internal val Project.skipGitHumReleaseSpmChecks: Boolean
get() = project.findStringProperty("SKIP_GITHUB_RELEASE_SPM_CHECKS") == "true"

internal val Project.githubRepoOrNull: String?
get() {
val repo = project.findStringProperty("GITHUB_REPO") ?: return null
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package co.touchlab.kmmbridge.github.internal

import org.gradle.api.GradleException
import org.gradle.api.Project
import java.io.BufferedReader
import java.io.File
import java.io.InputStreamReader

internal fun procRun(vararg params: String, dir: File?, processLines: (String, Int) -> Unit) {
val processBuilder = ProcessBuilder(*params)
.redirectErrorStream(true)
if (dir != null) {
println("*** Running proc in ${dir.path}")
processBuilder.directory(dir)
}

val process = processBuilder
.start()

val streamReader = InputStreamReader(process.inputStream)
val bufferedReader = BufferedReader(streamReader)
var lineCount = 1

bufferedReader.forEachLine { line ->
processLines(line, lineCount)
lineCount++
}

bufferedReader.close()
val returnValue = process.waitFor()
if (returnValue != 0)
throw GradleException("Process failed: ${params.joinToString(" ")}")
}

internal fun Project.procRunFailLog(vararg params: String, dir: File? = null): List<String> {
val output = mutableListOf<String>()
try {
logger.info("Project.procRunFailLog: ${params.joinToString(" ")}")
procRun(*params, dir = dir) { line, _ -> output.add(line) }
} catch (e: Exception) {
output.forEach { logger.error("error: $it") }
throw e
}
return output
}
Loading

0 comments on commit b833550

Please sign in to comment.