Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Publishing changes #24

Merged
merged 6 commits into from
Oct 28, 2020
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
24 changes: 24 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# This line tells Docker to base an image on a pre-built image with Alpine Linux. You can use other images from OpenJDK
# registry. Alpine Linux benefit is that the image is pretty small. We also select JRE-only image since we don't need
# to compile code on the image, only run precompiled classes.
FROM openjdk:8-jre-alpine

ENV APPLICATION_USER ktor
RUN adduser -D -g '' $APPLICATION_USER

RUN mkdir /app
RUN chown -R $APPLICATION_USER /app

USER $APPLICATION_USER

# These lines copy the packaged application into the Docker image and sets the working directory to where it was copied.
COPY ./build/libs/validator-wrapper-jvm-0.0.1.jar /app/validator-wrapper.jar
WORKDIR /app

# Environment vars here
ENV ENVIRONMENT prod

EXPOSE 3500

# The last line instructs Docker to run java with G10s GC, 4G of memory and the packaged application.
CMD ["java", "-server", "-XX:+UnlockExperimentalVMOptions", "-XX:+UseCGroupMemoryLimitForHeap", "-XX:InitialRAMFraction=2", "-XX:MinRAMFraction=2", "-XX:MaxRAMFraction=2", "-XX:+UseG1GC", "-XX:MaxGCPauseMillis=100", "-XX:+UseStringDeduplication", "-jar", "validator-wrapper.jar", "-startServer"]
8 changes: 8 additions & 0 deletions RELEASE_NOTES.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
* Added gradle task to provide release version to pipelines
* Cleaned up Application boot methods
* Added default dev deployment with option to set environment variable to deploy different configs
* Cleaned up documentation in Ktor files
* Changed prod deployment port and host name
* Add Dockerfile for container deployments
* Default deployment for Docker set to prod settings
* Fixed typo on landing page
34 changes: 24 additions & 10 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@ import org.jetbrains.kotlin.gradle.targets.js.webpack.KotlinWebpack
plugins {
kotlin("multiplatform") version "1.4.0"
kotlin("plugin.serialization") version "1.4.0"
id ("org.openjfx.javafxplugin") version "0.0.8"
id("org.hidetake.ssh") version "2.10.1"
id("org.openjfx.javafxplugin") version "0.0.8"
application
}
group = "org.hl7.fhir"
version = "1.0-SNAPSHOT"
version = "0.0.1"

repositories {
google()
Expand Down Expand Up @@ -36,12 +37,14 @@ repositories {

kotlin {
jvm {
compilations.all {
kotlinOptions.jvmTarget = "1.8"
compilations {
all {
kotlinOptions.jvmTarget = "1.8"
}
}
withJava()
}
js(){
js() {
useCommonJs()
browser {
binaries.executable()
Expand All @@ -65,8 +68,8 @@ kotlin {
implementation(kotlin("stdlib-common"))
implementation("com.fasterxml.jackson.core:jackson-databind:${property("jacksonVersion")}")

implementation ("org.jetbrains.kotlinx:kotlinx-serialization-core:${property("serializationVersion")}")
implementation ("org.jetbrains.kotlinx:kotlinx-serialization-protobuf:${property("serializationVersion")}")
implementation("org.jetbrains.kotlinx:kotlinx-serialization-core:${property("serializationVersion")}")
implementation("org.jetbrains.kotlinx:kotlinx-serialization-protobuf:${property("serializationVersion")}")
implementation("ca.uhn.hapi.fhir:org.hl7.fhir.validation:${property("fhirCoreVersion")}")
implementation("ca.uhn.hapi.fhir:org.hl7.fhir.utilities:${property("fhirCoreVersion")}")
}
Expand Down Expand Up @@ -132,16 +135,20 @@ kotlin {
}
}
}

javafx {
version = "14"//"11.0.2"
version = "14"
modules("javafx.controls", "javafx.graphics", "javafx.web")
}

application {
mainClassName = "ServerKt"
}

tasks.getByName<KotlinWebpack>("jsBrowserProductionWebpack") {
outputFileName = "output.js"
}

tasks.getByName<Jar>("jvmJar") {
manifest {
attributes["Main-Class"] = "ServerKt"
Expand All @@ -150,10 +157,12 @@ tasks.getByName<Jar>("jvmJar") {
val jsBrowserProductionWebpack = tasks.getByName<KotlinWebpack>("jsBrowserProductionWebpack")
from(File(jsBrowserProductionWebpack.destinationDirectory, jsBrowserProductionWebpack.outputFileName))
}

tasks.getByName<JavaExec>("run") {
dependsOn(tasks.getByName<Jar>("jvmJar"))
classpath(tasks.getByName<Jar>("jvmJar"))
}

tasks.withType<Jar> {
manifest {
attributes["Main-Class"] = "ServerKt"
Expand All @@ -168,6 +177,11 @@ tasks.withType<Jar> {
})
}

tasks.withType<JavaCompile>().configureEach {
options.compilerArgs = listOf("-Xmx2g", "-XX:MaxMetaspaceSize=512m")
/**
* Utility function to retrieve the current version number.
*/
task("printVersion") {
doLast {
println(project.version)
}
}
4 changes: 2 additions & 2 deletions src/commonMain/kotlin/constants/MIMETypes.kt
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package constants

enum class MIMEType(val code: String, val image: String, val fhirType: String) {
JSON("text/xml", "images/xml_icon.svg", "xml"),
XML("application/json", "images/json_icon.svg", "json");
JSON("text/xml", "static/images/xml_icon.svg", "xml"),
XML("application/json", "static/images/json_icon.svg", "json");

companion object {
// Reverse-lookup map for getting a day from an abbreviation
Expand Down
2 changes: 1 addition & 1 deletion src/jsMain/kotlin/App.kt
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ class App : RComponent<AppProps, AppState>() {
AppScreen.VALIDATOR -> {
sectionTitle {
majorText = "Validate Resources"
minorText = "Manually enter, up upload resources for validation."
minorText = "Manually enter, or upload resources for validation."
}
tabLayout {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import css.text.TextStyle
import css.widget.CheckboxStyle
import kotlinx.coroutines.launch
import kotlinx.css.*
import kotlinx.html.id
import kotlinx.html.js.onClickFunction
import mainScope
import model.CliContext
Expand Down
2 changes: 0 additions & 2 deletions src/jsMain/kotlin/ui/components/FileUpload.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,7 @@ package ui.components
import css.component.FileUploadStyle
import css.widget.FABStyle
import kotlinx.browser.document
import kotlinx.coroutines.launch
import kotlinx.html.js.onClickFunction
import mainScope
import org.w3c.dom.HTMLInputElement
import react.*
import reactredux.containers.uploadFilesButton
Expand Down
8 changes: 0 additions & 8 deletions src/jsMain/kotlin/ui/components/generic/OptionEntryField.kt
Original file line number Diff line number Diff line change
@@ -1,19 +1,11 @@
package ui.components.generic

import css.component.OptionEntryFieldStyle
import css.const.GRAY_100
import css.const.ICON_SMALL_DIM
import css.const.SHADOW
import css.text.TextStyle
import css.widget.Spinner
import kotlinx.browser.document
import kotlinx.css.*
import kotlinx.css.properties.boxShadow
import kotlinx.html.id
import kotlinx.html.js.onClickFunction
import org.w3c.dom.HTMLTextAreaElement
import react.*
import react.dom.textArea
import styled.*

external interface OptionEntryFieldProps : RProps {
Expand Down
28 changes: 28 additions & 0 deletions src/jvmMain/kotlin/HtmlIndex.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import kotlinx.html.*

/**
* We use kotlinx to create this HTML index file which contains the reference to `/static/output.js`, the location
* of our generated JS code from KotlinJS. This is also where we load in our external fonts and set the main 'root' div.
*/
fun HTML.index() {
head {
meta {
charset = "UTF-8"
}
title("Validator GUI")
link(
href = "https://fonts.googleapis.com/css2?family=Montserrat:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap",
rel = "stylesheet"
)
link(
href = "https://fonts.googleapis.com/css2?family=Source+Code+Pro:ital,wght@0,200;0,300;0,400;0,500;0,600;0,700;0,900;1,200;1,300;1,400;1,500;1,600;1,700;1,900&display=swap",
rel = "stylesheet"
)
}
body {
div {
id = "root"
}
script(src = "/static/output.js") {}
}
}
99 changes: 99 additions & 0 deletions src/jvmMain/kotlin/Module.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
import com.fasterxml.jackson.databind.DeserializationFeature
import com.fasterxml.jackson.databind.SerializationFeature
import desktop.launchLocalApp
import io.ktor.application.*
import io.ktor.features.*
import io.ktor.html.*
import io.ktor.http.*
import io.ktor.http.content.*
import io.ktor.jackson.*
import io.ktor.routing.*
import kotlinx.html.*
import org.slf4j.event.Level
import routes.debugRoutes
import routes.igRoutes
import routes.validationRoutes
import routes.versionRoutes

/**
* Entry point of the application.
*/
fun Application.module() {
// Any DB initialization will go here.
val starting: (Application) -> Unit = { log.info("Application starting: $it") }
val started: (Application) -> Unit = {
log.info("Application started: $it")
if (runningAsDesktopStandalone) {
launchLocalApp()
}
}
val stopping: (Application) -> Unit = { log.info("Application stopping: $it") }
var stopped: (Application) -> Unit = {}

stopped = {
log.info("Application stopped: $it")
environment.monitor.unsubscribe(ApplicationStarting, starting)
environment.monitor.unsubscribe(ApplicationStarted, started)
environment.monitor.unsubscribe(ApplicationStopping, stopping)
environment.monitor.unsubscribe(ApplicationStopped, stopped)
}

environment.monitor.subscribe(ApplicationStarted, starting)
environment.monitor.subscribe(ApplicationStarted, started)
environment.monitor.subscribe(ApplicationStopping, stopping)
environment.monitor.subscribe(ApplicationStopped, stopped)

// Now we call to a main with the dependencies as arguments.
// Separating this function with its dependencies allows us to provide several modules with
// the same code and different data-sources living in the same application,
// and to provide mocked instances for doing integration tests.
setup()
}

/**
* Application extension function where we configure Ktor application with features, interceptors and routing.
*/
fun Application.setup() {

install(CallLogging) {
level = Level.DEBUG
}

install(CORS) {
method(HttpMethod.Get)
method(HttpMethod.Post)
method(HttpMethod.Delete)
anyHost()
}

install(Compression) {
gzip()
}

install(ContentNegotiation) {
jackson {
enable(SerializationFeature.INDENT_OUTPUT)
/*
* Right now we need to ignore unknown fields because we take a very simplified version of many of the fhir
* model classes, and map them to classes across JVM/Common/JS.
*/
configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
}
}

install(Routing) {
get("/") {
call.respondHtml(HttpStatusCode.OK, HTML::index)
}

static("/static") {
resources()
}
resources()
validationRoutes()
versionRoutes()
igRoutes()
// Only enable if things have gone horribly, and you need to add a debug logging endpoint.
//debugRoutes()
}
}
Loading