Compare commits

...

3 commits

Author SHA1 Message Date
506cb31127 Remove deploy step from GitHub action
The docker image will still be published to the registry, it'll just no longer auto-update my own personal server.
2023-01-03 21:39:32 -07:00
f91043d3a8 Fix GraalVM startup issues 2023-01-03 21:36:51 -07:00
73f113e33e Add support for GraalVM
Note: This doesn't actually work yet. At the time of writing I'm seeing issues with Ktor not finding the application.conf file.
2023-01-01 21:38:41 -07:00
19 changed files with 603 additions and 18 deletions

View file

@ -43,14 +43,4 @@ jobs:
platforms: linux/amd64,linux/arm64 platforms: linux/amd64,linux/arm64
push: true push: true
tags: ${{ steps.meta.outputs.tags }} tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }} labels: ${{ steps.meta.outputs.labels }}
- name: Deploy
uses: appleboy/ssh-action@master
with:
host: ${{ secrets.HOST }}
username: ${{ secrets.USERNAME }}
key: ${{ secrets.KEY }}
script: |
docker compose pull twigs
docker compose up -d --build twigs
docker image prune -f

View file

@ -1,4 +1,4 @@
FROM openjdk:17-jdk as builder FROM ghcr.io/graalvm/graalvm-ce:ol9-java17-22.3.0-b2 as builder
MAINTAINER William Brawner <me@wbrawner.com> MAINTAINER William Brawner <me@wbrawner.com>
RUN groupadd --system --gid 1000 gradle \ RUN groupadd --system --gid 1000 gradle \
@ -6,12 +6,12 @@ RUN groupadd --system --gid 1000 gradle \
COPY --chown=gradle:gradle . /home/gradle/src COPY --chown=gradle:gradle . /home/gradle/src
WORKDIR /home/gradle/src WORKDIR /home/gradle/src
RUN /home/gradle/src/gradlew --console=plain --no-daemon shadowJar RUN /home/gradle/src/gradlew --console=plain --no-daemon nativeCompile
FROM openjdk:17-slim FROM quay.io/centos/centos:stream9
EXPOSE 8080 EXPOSE 8080
RUN groupadd --system --gid 1000 twigs \ RUN groupadd --system --gid 1000 twigs \
&& useradd --system --gid twigs --uid 1000 --create-home twigs && useradd --system --gid twigs --uid 1000 --create-home twigs
COPY --from=builder --chown=twigs:twigs /home/gradle/src/app/build/libs/twigs.jar twigs.jar COPY --from=builder --chown=twigs:twigs /home/gradle/src/app/build/native/nativeCompile/twigs /usr/local/bin/twigs
USER twigs USER twigs
CMD /usr/local/openjdk-17/bin/java $JVM_ARGS -jar /twigs.jar CMD /usr/local/bin/twigs

View file

@ -0,0 +1,19 @@
[
{
"name":"java.lang.Boolean",
"methods":[{"name":"getBoolean","parameterTypes":["java.lang.String"] }]
},
{
"name":"sun.management.VMManagementImpl",
"fields":[
{"name":"compTimeMonitoringSupport"},
{"name":"currentThreadCpuTimeSupport"},
{"name":"objectMonitorUsageSupport"},
{"name":"otherThreadCpuTimeSupport"},
{"name":"remoteDiagnosticCommandsSupport"},
{"name":"synchronizerUsageSupport"},
{"name":"threadAllocatedMemorySupport"},
{"name":"threadContentionMonitoringSupport"}
]
}
]

View file

@ -0,0 +1,7 @@
[
{
"type":"agent-extracted",
"classes":[
]
}
]

View file

@ -0,0 +1,5 @@
[
{
"interfaces":["java.sql.Connection"]
}
]

View file

@ -0,0 +1,159 @@
[
{
"name":"[Lcom.zaxxer.hikari.util.ConcurrentBag$IConcurrentBagEntry;"
},
{
"name":"[Ljava.lang.String;"
},
{
"name":"[Ljava.sql.Statement;"
},
{
"name":"android.os.Build$VERSION"
},
{
"name":"com.wbrawner.twigs.EmailService"
},
{
"name":"com.wbrawner.twigs.db.MetadataRepository"
},
{
"name":"com.wbrawner.twigs.model.Session"
},
{
"name":"com.wbrawner.twigs.server.ApplicationKt",
"queryAllPublicMethods":true,
"methods":[
{"name":"main","parameterTypes":["java.lang.String[]"] },
{"name":"module","parameterTypes":["io.ktor.server.application.Application"] }
]
},
{
"name":"com.wbrawner.twigs.storage.BudgetRepository"
},
{
"name":"com.wbrawner.twigs.storage.CategoryRepository"
},
{
"name":"com.wbrawner.twigs.storage.PasswordResetRepository"
},
{
"name":"com.wbrawner.twigs.storage.PermissionRepository"
},
{
"name":"com.wbrawner.twigs.storage.RecurringTransactionRepository"
},
{
"name":"com.wbrawner.twigs.storage.SessionRepository"
},
{
"name":"com.wbrawner.twigs.storage.TransactionRepository"
},
{
"name":"com.wbrawner.twigs.storage.UserRepository"
},
{
"name":"com.zaxxer.hikari.HikariConfig",
"allDeclaredFields":true
},
{
"name":"io.ktor.server.application.Application"
},
{
"name":"java.io.FilePermission"
},
{
"name":"java.lang.RuntimePermission"
},
{
"name":"java.lang.String"
},
{
"name":"java.net.NetPermission"
},
{
"name":"java.net.SocketPermission"
},
{
"name":"java.net.StandardSocketOptions"
},
{
"name":"java.net.URLPermission",
"methods":[{"name":"<init>","parameterTypes":["java.lang.String","java.lang.String"] }]
},
{
"name":"java.security.AllPermission"
},
{
"name":"java.security.SecureRandomParameters"
},
{
"name":"java.security.SecurityPermission"
},
{
"name":"java.util.PropertyPermission"
},
{
"name":"javax.smartcardio.CardPermission"
},
{
"name":"kotlin.Array"
},
{
"name":"kotlin.Int"
},
{
"name":"kotlin.Metadata",
"queryAllDeclaredMethods":true,
"methods":[
{"name":"bv","parameterTypes":[] },
{"name":"d1","parameterTypes":[] },
{"name":"d2","parameterTypes":[] },
{"name":"k","parameterTypes":[] },
{"name":"mv","parameterTypes":[] },
{"name":"pn","parameterTypes":[] },
{"name":"xi","parameterTypes":[] },
{"name":"xs","parameterTypes":[] }
]
},
{
"name":"kotlin.String"
},
{
"name":"kotlin.Unit"
},
{
"name":"kotlin.internal.jdk8.JDK8PlatformImplementations",
"methods":[{"name":"<init>","parameterTypes":[] }]
},
{
"name":"kotlin.jvm.internal.DefaultConstructorMarker"
},
{
"name":"kotlin.reflect.jvm.internal.ReflectionFactoryImpl",
"methods":[{"name":"<init>","parameterTypes":[] }]
},
{
"name":"kotlin.reflect.jvm.internal.impl.resolve.scopes.DescriptorKindFilter",
"allPublicFields":true
},
{
"name":"org.postgresql.Driver"
},
{
"name":"sun.security.provider.DRBG",
"methods":[{"name":"<init>","parameterTypes":["java.security.SecureRandomParameters"] }]
},
{
"name":"sun.security.provider.MD5",
"methods":[{"name":"<init>","parameterTypes":[] }]
},
{
"name":"sun.security.provider.SHA",
"methods":[{"name":"<init>","parameterTypes":[] }]
},
{
"name":"sun.security.provider.SHA2$SHA256",
"methods":[{"name":"<init>","parameterTypes":[] }]
}
]

View file

@ -0,0 +1,21 @@
{
"resources":{
"includes":[
{
"pattern":"\\QMETA-INF/javamail.default.address.map\\E"
},
{
"pattern":"\\QMETA-INF/services/java.sql.Driver\\E"
},
{
"pattern":"\\QMETA-INF/services/kotlin.reflect.jvm.internal.impl.resolve.ExternalOverridabilityCondition\\E"
},
{
"pattern":"\\Qapplication.conf\\E"
},
{
"pattern":"\\Qorg/slf4j/impl/StaticLoggerBinder.class\\E"
}
]},
"bundles":[]
}

View file

@ -0,0 +1,8 @@
{
"types":[
],
"lambdaCapturingTypes":[
],
"proxies":[
]
}

View file

@ -1,11 +1,11 @@
import java.net.URI import java.net.URI
import java.util.*
plugins { plugins {
java java
kotlin("jvm") kotlin("jvm")
application application
alias(libs.plugins.shadow) alias(libs.plugins.shadow)
alias(libs.plugins.graalvm)
} }
repositories { repositories {
@ -51,3 +51,20 @@ tasks.shadowJar {
tasks.getByName<Test>("test") { tasks.getByName<Test>("test") {
useJUnitPlatform() useJUnitPlatform()
} }
graalvmNative {
binaries {
named("main") {
fallback.set(false)
verbose.set(true)
buildArgs.add("--initialize-at-build-time=io.ktor,kotlin,kotlinx.serialization,ch.qos.logback,org.slf4j")
buildArgs.add("--trace-object-instantiation=ch.qos.logback.classic.Logger")
buildArgs.add("-H:+InstallExitHandlers")
buildArgs.add("-H:+ReportUnsupportedElementsAtRuntime")
buildArgs.add("-H:+ReportExceptionStackTraces")
imageName.set("twigs")
}
}
}

View file

@ -24,6 +24,7 @@ import kotlinx.coroutines.launch
import kotlinx.serialization.json.Json import kotlinx.serialization.json.Json
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
import kotlin.system.exitProcess
fun main(args: Array<String>): Unit = io.ktor.server.cio.EngineMain.main(args) fun main(args: Array<String>): Unit = io.ktor.server.cio.EngineMain.main(args)

View file

@ -0,0 +1,42 @@
[
{
"name": "java.lang.Boolean",
"methods": [
{
"name": "getBoolean",
"parameterTypes": [
"java.lang.String"
]
}
]
},
{
"name": "sun.management.VMManagementImpl",
"fields": [
{
"name": "compTimeMonitoringSupport"
},
{
"name": "currentThreadCpuTimeSupport"
},
{
"name": "objectMonitorUsageSupport"
},
{
"name": "otherThreadCpuTimeSupport"
},
{
"name": "remoteDiagnosticCommandsSupport"
},
{
"name": "synchronizerUsageSupport"
},
{
"name": "threadAllocatedMemorySupport"
},
{
"name": "threadContentionMonitoringSupport"
}
]
}
]

View file

@ -0,0 +1,8 @@
[
{
"type": "agent-extracted",
"classes": [
]
}
]

View file

@ -0,0 +1,7 @@
[
{
"interfaces": [
"java.sql.Connection"
]
}
]

View file

@ -0,0 +1,259 @@
[
{
"name": "[Lcom.zaxxer.hikari.util.ConcurrentBag$IConcurrentBagEntry;"
},
{
"name": "[Ljava.lang.String;"
},
{
"name": "[Ljava.sql.Statement;"
},
{
"name": "android.os.Build$VERSION"
},
{
"name": "com.wbrawner.twigs.EmailService"
},
{
"name": "com.wbrawner.twigs.db.MetadataRepository"
},
{
"name": "com.wbrawner.twigs.model.Session"
},
{
"name": "com.wbrawner.twigs.server.ApplicationKt",
"queryAllPublicMethods": true,
"methods": [
{
"name": "main",
"parameterTypes": [
"java.lang.String[]"
]
},
{
"name": "module",
"parameterTypes": [
"io.ktor.server.application.Application"
]
}
]
},
{
"name": "com.wbrawner.twigs.storage.BudgetRepository"
},
{
"name": "com.wbrawner.twigs.storage.CategoryRepository"
},
{
"name": "com.wbrawner.twigs.storage.PasswordResetRepository"
},
{
"name": "com.wbrawner.twigs.storage.PermissionRepository"
},
{
"name": "com.wbrawner.twigs.storage.RecurringTransactionRepository"
},
{
"name": "com.wbrawner.twigs.storage.SessionRepository"
},
{
"name": "com.wbrawner.twigs.storage.TransactionRepository"
},
{
"name": "com.wbrawner.twigs.storage.UserRepository"
},
{
"name": "com.zaxxer.hikari.HikariConfig",
"allDeclaredFields": true
},
{
"name": "io.ktor.server.application.Application"
},
{
"name": "java.io.FilePermission"
},
{
"name": "java.lang.RuntimePermission"
},
{
"name": "java.lang.String"
},
{
"name": "java.net.NetPermission"
},
{
"name": "java.net.SocketPermission"
},
{
"name": "java.net.StandardSocketOptions"
},
{
"name": "java.net.URLPermission",
"methods": [
{
"name": "<init>",
"parameterTypes": [
"java.lang.String",
"java.lang.String"
]
}
]
},
{
"name": "java.security.AllPermission"
},
{
"name": "java.security.SecureRandomParameters"
},
{
"name": "java.security.SecurityPermission"
},
{
"name": "java.util.PropertyPermission"
},
{
"name": "javax.smartcardio.CardPermission"
},
{
"name": "kotlin.Array"
},
{
"name": "kotlin.Int"
},
{
"name": "kotlin.Metadata",
"queryAllDeclaredMethods": true,
"methods": [
{
"name": "bv",
"parameterTypes": [
]
},
{
"name": "d1",
"parameterTypes": [
]
},
{
"name": "d2",
"parameterTypes": [
]
},
{
"name": "k",
"parameterTypes": [
]
},
{
"name": "mv",
"parameterTypes": [
]
},
{
"name": "pn",
"parameterTypes": [
]
},
{
"name": "xi",
"parameterTypes": [
]
},
{
"name": "xs",
"parameterTypes": [
]
}
]
},
{
"name": "kotlin.String"
},
{
"name": "kotlin.Unit"
},
{
"name": "kotlin.internal.jdk8.JDK8PlatformImplementations",
"methods": [
{
"name": "<init>",
"parameterTypes": [
]
}
]
},
{
"name": "kotlin.jvm.internal.DefaultConstructorMarker"
},
{
"name": "kotlin.reflect.jvm.internal.ReflectionFactoryImpl",
"methods": [
{
"name": "<init>",
"parameterTypes": [
]
}
]
},
{
"name": "kotlin.reflect.jvm.internal.impl.resolve.scopes.DescriptorKindFilter",
"allPublicFields": true
},
{
"name": "org.postgresql.Driver"
},
{
"name": "sun.security.provider.DRBG",
"methods": [
{
"name": "<init>",
"parameterTypes": [
"java.security.SecureRandomParameters"
]
}
]
},
{
"name": "sun.security.provider.MD5",
"methods": [
{
"name": "<init>",
"parameterTypes": [
]
}
]
},
{
"name": "sun.security.provider.SHA",
"methods": [
{
"name": "<init>",
"parameterTypes": [
]
}
]
},
{
"name": "sun.security.provider.SHA2$SHA256",
"methods": [
{
"name": "<init>",
"parameterTypes": [
]
}
]
}
]

View file

@ -0,0 +1,27 @@
{
"resources": {
"includes": [
{
"pattern": "\\QMETA-INF/javamail.default.address.map\\E"
},
{
"pattern": "\\QMETA-INF/services/java.sql.Driver\\E"
},
{
"pattern": "\\QMETA-INF/services/kotlin.reflect.jvm.internal.impl.resolve.ExternalOverridabilityCondition\\E"
},
{
"pattern": "\\Qapplication.conf\\E"
},
{
"pattern": "\\Qorg/slf4j/impl/StaticLoggerBinder.class\\E"
},
{
"pattern":"\\Qkotlin/kotlin.kotlin_builtins\\E"
}
]
},
"bundles": [
]
}

View file

@ -0,0 +1,11 @@
{
"lambdaCapturingTypes": [
],
"types": [
],
"proxies": [
]
}

View file

@ -2,6 +2,7 @@ ktor {
deployment { deployment {
port = 8080 port = 8080
port = ${?TWIGS_PORT} port = ${?TWIGS_PORT}
shutdown.url = "/shutdown"
} }
application { application {
modules = [ com.wbrawner.twigs.server.ApplicationKt.module ] modules = [ com.wbrawner.twigs.server.ApplicationKt.module ]

View file

@ -5,6 +5,7 @@ buildscript {
repositories { repositories {
mavenLocal() mavenLocal()
mavenCentral() mavenCentral()
gradlePluginPortal()
} }
dependencies { dependencies {
@ -28,6 +29,6 @@ allprojects {
group = "com.wbrawner" group = "com.wbrawner"
version = "0.0.1-SNAPSHOT" version = "0.0.1-SNAPSHOT"
tasks.withType<KotlinCompile> { tasks.withType<KotlinCompile> {
kotlinOptions.jvmTarget = "16" kotlinOptions.jvmTarget = "17"
} }
} }

View file

@ -1,5 +1,6 @@
[versions] [versions]
bcrypt = "0.9.0" bcrypt = "0.9.0"
graalvm = "0.9.19"
hikari = "5.0.1" hikari = "5.0.1"
junit = "5.8.2" junit = "5.8.2"
kotlin = "1.6.21" kotlin = "1.6.21"
@ -42,6 +43,7 @@ ktor-server = [
] ]
[plugins] [plugins]
graalvm = { id = "org.graalvm.buildtools.native", version.ref = "graalvm" }
kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" } kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" }
kotlin-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" } kotlin-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" }
shadow = { id = "com.github.johnrengelman.shadow", version.ref = "shadow" } shadow = { id = "com.github.johnrengelman.shadow", version.ref = "shadow" }