Skip to content

Commit

Permalink
Add CI Checks for Kotlin
Browse files Browse the repository at this point in the history
  • Loading branch information
alexanderwiederin committed Nov 6, 2023
1 parent d78cab0 commit a58f4f6
Show file tree
Hide file tree
Showing 6 changed files with 175 additions and 44 deletions.
50 changes: 50 additions & 0 deletions .github/workflows/kotlin.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
name: Continuous Integration Checks - Kotlin

on: [push, pull_request]

jobs:
check-kotlin:
runs-on: ubuntu-latest

env:
LDK_NODE_JVM_DIR: bindings/kotlin/ldk-node-jvm
LDK_NODE_ANDROID_DIR: bindings/kotlin/ldk-node-android

steps:
- name: Checkout repository
uses: actions/checkout@v2

- name: Set up JDK
uses: actions/setup-java@v2
with:
distribution: temurin
java-version: 11

- name: Run ktlintCheck on ldk-node-jvm
run: |
cd $LDK_NODE_JVM_DIR
./gradlew ktlintCheck
- name: Run ktlintCheck on ldk-node-android
run: |
cd $LDK_NODE_ANDROID_DIR
./gradlew ktlintCheck
- name: Generate Kotlin JVM
run: ./scripts/uniffi_bindgen_generate_kotlin.sh

- name: Generate Kotlin Android
run: ./scripts/uniffi_bindgen_generate_kotlin_android.sh

- name: Start bitcoin and electrs
run: docker compose up -d

- name: Run ldk-node-jvm tests
run: |
cd $LDK_NODE_JVM_DIR
./gradlew test
- name: Run ldk-node-android tests
run: |
cd $LDK_NODE_ANDROID_DIR
./gradlew test
12 changes: 9 additions & 3 deletions bindings/kotlin/ldk-node-android/lib/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
import org.gradle.api.tasks.testing.logging.TestExceptionFormat.*
import org.gradle.api.tasks.testing.logging.TestLogEvent.*

// library version is defined in gradle.properties
val libraryVersion: String by project

Expand All @@ -10,6 +7,7 @@ plugins {

id("maven-publish")
id("signing")
id("org.jlleitschuh.gradle.ktlint") version "11.6.1"
}

repositories {
Expand Down Expand Up @@ -106,3 +104,11 @@ signing {
// useInMemoryPgpKeys(signingKeyId, signingKey, signingPassword)
sign(publishing.publications)
}

ktlint {
filter {
exclude { entry ->
entry.file.toString().contains("main")
}
}
}
35 changes: 24 additions & 11 deletions bindings/kotlin/ldk-node-jvm/lib/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
import org.gradle.api.tasks.testing.logging.TestExceptionFormat.*
import org.gradle.api.tasks.testing.logging.TestLogEvent.*
import org.gradle.api.tasks.testing.logging.TestExceptionFormat.FULL
import org.gradle.api.tasks.testing.logging.TestLogEvent.FAILED
import org.gradle.api.tasks.testing.logging.TestLogEvent.PASSED
import org.gradle.api.tasks.testing.logging.TestLogEvent.SKIPPED
import org.gradle.api.tasks.testing.logging.TestLogEvent.STANDARD_ERROR
import org.gradle.api.tasks.testing.logging.TestLogEvent.STANDARD_OUT

// library version is defined in gradle.properties
val libraryVersion: String by project
Expand All @@ -12,6 +16,7 @@ plugins {
id("java-library")
id("maven-publish")
id("signing")
id("org.jlleitschuh.gradle.ktlint") version "11.6.1"
}

repositories {
Expand All @@ -31,12 +36,12 @@ dependencies {
// Use the JUnit 5 integration.
testImplementation("org.junit.jupiter:junit-jupiter-engine:5.9.1")

//// This dependency is exported to consumers, that is to say found on their compile classpath.
//api("org.apache.commons:commons-math3:3.6.1")
// // This dependency is exported to consumers, that is to say found on their compile classpath.
// api("org.apache.commons:commons-math3:3.6.1")

//// This dependency is used internally, and not exposed to consumers on their own compile classpath.
//implementation("com.google.guava:guava:31.1-jre")
// Align versions of all Kotlin components
// // This dependency is used internally, and not exposed to consumers on their own compile classpath.
// implementation("com.google.guava:guava:31.1-jre")
// Align versions of all Kotlin components
implementation(platform("org.jetbrains.kotlin:kotlin-bom"))

// Use the Kotlin JDK 8 standard library.
Expand All @@ -49,13 +54,13 @@ tasks.named<Test>("test") {
// Use JUnit Platform for unit tests.
useJUnitPlatform()

testLogging {
testLogging {
events(PASSED, SKIPPED, FAILED, STANDARD_OUT, STANDARD_ERROR)
exceptionFormat = FULL
showExceptions = true
showCauses = true
showStackTraces = true
showStandardStreams = true
showStandardStreams = true
}
}

Expand Down Expand Up @@ -88,8 +93,8 @@ afterEvaluate {
developers {
developer {
id.set("tnull")
name.set("Elias Rohrer")
email.set("[email protected]")
name.set("Elias Rohrer")
email.set("[email protected]")
}
}
}
Expand All @@ -111,3 +116,11 @@ signing {
// useInMemoryPgpKeys(signingKeyId, signingKey, signingPassword)
sign(publishing.publications)
}

ktlint {
filter {
exclude { entry ->
entry.file.toString().contains("main")
}
}
}
Original file line number Diff line number Diff line change
@@ -1,16 +1,13 @@
/*
* This Kotlin source file was generated by the Gradle 'init' task.
*/
package org.lightningdevkit.ldknode

import kotlin.UInt
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.io.path.createTempDirectory
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
import java.net.URI
import java.net.http.HttpClient
import java.net.http.HttpRequest
import java.net.http.HttpResponse
import kotlin.io.path.createTempDirectory
import kotlin.test.assertEquals

fun runCommandAndWait(vararg cmd: String): String {
println("Running command \"${cmd.joinToString(" ")}\"")
Expand All @@ -25,11 +22,11 @@ fun runCommandAndWait(vararg cmd: String): String {
}

fun mine(blocks: UInt): String {
val address = runCommandAndWait("bitcoin-cli", "-regtest", "getnewaddress")
val output = runCommandAndWait("bitcoin-cli", "-regtest", "generatetoaddress", blocks.toString(), address)
val address = runCommandAndWait("docker", "exec", "lib-bitcoin-1", "bitcoin-cli", "-regtest", "-rpcuser=user", "-rpcpassword=pass", "getnewaddress")
val output = runCommandAndWait("docker", "exec", "lib-bitcoin-1", "bitcoin-cli", "-regtest", "-rpcuser=user", "-rpcpassword=pass", "generatetoaddress", blocks.toString(), address)
println("Mining output: $output")
val re = Regex("\n.+\n\\]$")
val lastBlock = re.find(output)!!.value.replace("]","").replace("\"", "").replace("\n","").trim()
val lastBlock = re.find(output)!!.value.replace("]", "").replace("\"", "").replace("\n", "").trim()
println("Last block: $lastBlock")
return lastBlock
}
Expand All @@ -41,53 +38,52 @@ fun mineAndWait(esploraEndpoint: String, blocks: UInt) {

fun sendToAddress(address: String, amountSats: UInt): String {
val amountBtc = amountSats.toDouble() / 100000000.0
val output = runCommandAndWait("bitcoin-cli", "-regtest", "sendtoaddress", address, amountBtc.toString())
val output = runCommandAndWait("docker", "exec", "lib-bitcoin-1", "bitcoin-cli", "-regtest", "-rpcuser=user", "-rpcpassword=pass", "sendtoaddress", address, amountBtc.toString())
return output
}

fun setup() {
runCommandAndWait("bitcoin-cli", "-regtest", "createwallet", "ldk_node_test")
runCommandAndWait("bitcoin-cli", "-regtest", "loadwallet", "ldk_node_test", "true")
mine(101u)
Thread.sleep(5_000)
}

fun waitForTx(esploraEndpoint: String, txid: String) {
var esploraPickedUpTx = false
val re = Regex("\"txid\":\"$txid\"");
val re = Regex("\"txid\":\"$txid\"")
while (!esploraPickedUpTx) {
val client = HttpClient.newBuilder().build()
val request = HttpRequest.newBuilder()
.uri(URI.create(esploraEndpoint + "/tx/" + txid))
.build();
.build()

val response = client.send(request, HttpResponse.BodyHandlers.ofString());
val response = client.send(request, HttpResponse.BodyHandlers.ofString())

esploraPickedUpTx = re.containsMatchIn(response.body());
esploraPickedUpTx = re.containsMatchIn(response.body())
Thread.sleep(500)
}
}

fun waitForBlock(esploraEndpoint: String, blockHash: String) {
var esploraPickedUpBlock = false
val re = Regex("\"in_best_chain\":true");
val re = Regex("\"in_best_chain\":true")
while (!esploraPickedUpBlock) {
val client = HttpClient.newBuilder().build()
val request = HttpRequest.newBuilder()
.uri(URI.create(esploraEndpoint + "/block/" + blockHash + "/status"))
.build();
.build()

val response = client.send(request, HttpResponse.BodyHandlers.ofString());
val response = client.send(request, HttpResponse.BodyHandlers.ofString())

esploraPickedUpBlock = re.containsMatchIn(response.body());
esploraPickedUpBlock = re.containsMatchIn(response.body())
Thread.sleep(500)
}
}

class LibraryTest {
@BeforeEach
fun setup() {
runCommandAndWait("docker", "exec", "lib-bitcoin-1", "bitcoin-cli", "-regtest", "-rpcuser=user", "-rpcpassword=pass", "createwallet", "ldk_node_test")
runCommandAndWait("docker", "exec", "lib-bitcoin-1", "bitcoin-cli", "-regtest", "-rpcuser=user", "-rpcpassword=pass", "loadwallet", "ldk_node_test", "true")
mine(101u)
Thread.sleep(5_000)
}

@Test fun fullCycle() {
val esploraEndpoint = "http://127.0.0.1:3002"
setup()

val tmpDir1 = createTempDirectory("ldk_node").toString()
println("Random dir 1: $tmpDir1")
Expand Down Expand Up @@ -172,7 +168,7 @@ class LibraryTest {

val fundingTxid = when (channelPendingEvent1) {
is Event.ChannelPending -> channelPendingEvent1.fundingTxo.txid
else -> return
else -> return
}

waitForTx(esploraEndpoint, fundingTxid)
Expand Down Expand Up @@ -202,7 +198,7 @@ class LibraryTest {

val channelId = when (channelReadyEvent2) {
is Event.ChannelReady -> channelReadyEvent2.channelId
else -> return
else -> return
}

val invoice = node2.receivePayment(2500000u, "asdf", 9217u)
Expand Down
51 changes: 51 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
version: '3'

services:
bitcoin:
image: ruimarinho/bitcoin-core:latest
platform: linux/amd64
command:
[
"-printtoconsole",
"-regtest=1",
"-rpcallowip=0.0.0.0/0",
"-rpcbind=0.0.0.0",
"-rpcuser=user",
"-rpcpassword=pass",
]
ports:
- "18443:18443" # Regtest RPC port
- "18444:18444" # Regtest P2P port
networks:
- bitcoin-electrs
healthcheck:
test: ["CMD", "bitcoin-cli", "-regtest", "-rpcuser=user", "-rpcpassword=pass", "getblockchaininfo"]
interval: 5s
timeout: 10s
retries: 5

electrs:
image: blockstream/esplora:electrs-latest
platform: linux/amd64
depends_on:
bitcoin:
condition: service_healthy
command:
[
"/app/electrs_bitcoin/bin/electrs",
"-vvvv",
"--timestamp",
"--jsonrpc-import",
"--cookie=user:pass",
"--network=regtest",
"--daemon-rpc-addr=bitcoin:18443",
]
ports:
- "3002:3002"
- "3000:3000"
networks:
- bitcoin-electrs

networks:
bitcoin-electrs:
driver: bridge
15 changes: 15 additions & 0 deletions scripts/format_kotlin.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#!/bin/bash
LDK_NODE_ANDROID_DIR="bindings/kotlin/ldk-node-android"
LDK_NODE_JVM_DIR="bindings/kotlin/ldk-node-jvm"

# Run ktlintFormat in ldk-node-android
(
cd $LDK_NODE_ANDROID_DIR || exit 1
./gradlew ktlintFormat
)

# Run ktlintFormat in ldk-node-jvm
(
cd $LDK_NODE_JVM_DIR || exit 1
./gradlew ktlintFormat
)

0 comments on commit a58f4f6

Please sign in to comment.