Skip to content

Commit

Permalink
#66 - Converting to a Gradle multi-module project, though currently o…
Browse files Browse the repository at this point in the history
…nly with a single module, that being the existing project as-is
  • Loading branch information
bobbylight committed Mar 18, 2021
1 parent 212dc6c commit 06d22d3
Show file tree
Hide file tree
Showing 278 changed files with 300 additions and 266 deletions.
84 changes: 5 additions & 79 deletions README.md
100755 → 100644
Original file line number Diff line number Diff line change
@@ -1,85 +1,11 @@
# Random Acts of Kinase

[![Build Status](https://travis-ci.org/bobbylight/random-acts-of-kinase.svg?branch=master)](https://travis-ci.org/bobbylight/random-acts-of-kinase)
[![Coverage Status](https://coveralls.io/repos/github/bobbylight/random-acts-of-kinase/badge.svg?branch=master)](https://coveralls.io/github/bobbylight/random-acts-of-kinase?branch=master)

A web frontend for SGC kinase information.

A Spring Boot application exposes the data via a REST API. The frontend is written in Vue.

Note: The actual kinase data is not included in this repository, for obvious reasons.
You can still test the application without this data by running it with the `dev` Spring profile.

## Hacking
You can omit the `-xcreateSmileSvgs` options if you actually have openbabel installed
and configured properly in your environment. If you don't, you need to use this option to
omit that build task to prevent a build failure:

```sh
git clone https://github.com/bobbylight/random-acts-of-kinase.git
./gradlew build -xwebpack --warning-mode all -xcreateSmileSvgs
./gradlew bootRun -xwebpack -xcreateSmileSvgs # Starts application at localhost:8080
./gradlew webpackWatch # In another window, run webpack watch for UI updates
./gradlew copyStaticResourcesToBuildWatch # Copy webpack build into build/ for hot deploys
```

Unfortunately you need to start three processes to develop - annoying. I couldn't get
webpack to build directly into `build/` without Spring Boot getting cranky and clearing
out the contents of `build/resources/main/static` on restarts.

*Note:* Ctrl+C may not propagate the SIGKILL to the child npm tasks for `webpackWatch`
and `copyStaticResourcesToBuildWatch`, which can cause race conditions on file copies
and in turn weird behavior (stale static resources). If you see this happening, you
might consider running the wrapped npm tasks directly. See
[here](https://github.com/srs/gradle-node-plugin/issues/143) for more information.

If you have data to develop against in a local postgres instance, you can run against
via `./gradlew bootRun -Dspring.profiles.active=dev-postgres`.

The server is a simple Spring Boot application exposing a REST API and a little
static content. The client is Vue/JS/TypeScript.

The application will be hosted at [http://localhost:8080]().

To run tests:
```sh
./gradlew test -xwebpack # Service tests
npm test # Client tests
npm run coverage # Client tests + coverage report
```

The coverage report for the client-side tests lives here:
```sh
open reports/coverage/index.html
```

To deploy to AWS (we build a zip containing just the jar and a Procfile to launch
it, as configured in `.elasticbeanstalk/config.yml`):
```sh
./gradlew clean build --warning-mode all # Be sure to perform a production build
./gradlew makeAwsArchive
eb deploy --label "something"
```

## Utilities

The `util` folder contains shell scripts to do mundane tasks. For these scripts
to run you'll need to create a file named `env.sh` from the `env.sh.orig` template
file with connection info for a database containing the SGC data.

### Creating SVG images for compounds from SMILES strings
The SVG images of compounds used by the application are generated from their
SMILES strings. Generate them by running `./create-smiles-svgs.sh`. You'll
need to have `psql` on your `PATH` or this script will fail silently. This
script is run as part of `./gradlew build` so you typically don't need to
run it directly.

### Exporting data from our database into CSV files
To back up the database into CSV files, you can run `./export-to-csv.sh`.
This projectr contains two modules:

* `service/` contains a Spring Boot application that exposes the data via a
REST API
* `ui/` contains the static content. It's a built and minified Vue application

## Updating the AWS database
We won't have to keep doing this once we have the data exported in a format we like...
```sh
psql --host=<host-name> --username=<user> --dbname=<db> -f create-db.ddl
```
See the `README.md` in each module for instructions on how to run locally.
192 changes: 6 additions & 186 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -1,211 +1,31 @@
buildscript {
repositories {
mavenCentral()
jcenter()
}
dependencies {
classpath 'org.springframework.boot:spring-boot-gradle-plugin:2.4.3'
}
}
plugins {
id 'com.github.node-gradle.node' version '3.0.1'
id 'jacoco'
id 'com.github.kt3k.coveralls' version '2.10.2'
id 'com.github.spotbugs' version '4.6.2'
}
apply plugin: 'java'
apply plugin: 'idea'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'
apply plugin: 'com.github.node-gradle.node'
apply plugin: 'com.github.spotbugs'
apply plugin: 'checkstyle'

import static org.gradle.api.JavaVersion.*

// We require building with JDK 14 or later, but there is no 14 check yet
assert current().isJava12Compatible()

group = 'org.sgc'
version = '1.4.0-SNAPSHOT'

repositories {
mavenCentral()
}

node {
version = '14.16.0'
npmVersion = '6.14.11'
download = true

// Node and npm should work in our 'frontend' folder
workDir = file("${project.buildDir}/nodejs")
npmWorkDir = file("${project.buildDir}/npm")
yarnWorkDir = file("${project.buildDir}/yarn")

// Where node_modules should be located
nodeModulesDir = file("${project.projectDir}/src/main/frontend")
}

dependencies {

implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-validation'
implementation 'org.springframework.boot:spring-boot-devtools'
implementation 'org.springframework.boot:spring-boot-starter-actuator'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-security'

implementation 'org.slf4j:slf4j-api'
implementation 'ch.qos.logback:logback-classic'
implementation 'ch.qos.logback:logback-core'

implementation 'com.fasterxml.jackson.dataformat:jackson-dataformat-csv'
implementation 'org.apache.commons:commons-lang3:3.12.0'
implementation 'org.postgresql:postgresql'
implementation 'org.apache.xmlgraphics:batik-transcoder:1.14'
implementation 'org.apache.xmlgraphics:batik-codec:1.14'
implementation 'com.h2database:h2'

testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'org.springframework.security:spring-security-test'
// TODO: Remove and update tests to JUnit 5 syntax
testImplementation('org.junit.vintage:junit-vintage-engine') {
exclude group: 'org.hamcrest', module: 'hamcrest-core'
}
}
group 'org.sgc'
// NOTE: Local Java 8: /Library/Java/JavaVirtualMachines/jdk1.8.0_25.jdk/Contents/Home

wrapper {
gradleVersion = '6.8.3'
}

checkstyle {
toolVersion '8.41'
configDirectory = file("${project.projectDir}/config/checkstyle")
}

idea {
module {
downloadSources = true
}
}

compileJava {
sourceCompatibility javaVersion
targetCompatibility javaVersion
options.debug = true
options.debugOptions.debugLevel = 'source,vars,lines'
options.compilerArgs << '-Xlint:deprecation' << '-Xlint:unchecked'
}

compileTestJava {
sourceCompatibility javaVersion
targetCompatibility javaVersion
options.debug = true
options.debugOptions.debugLevel = 'source,vars,lines'
options.compilerArgs << '-Xlint:deprecation' << '-Xlint:unchecked'
}

sourceSets {
integrationTest {
java.srcDirs = [ 'src/integration-test/java' ]
resources.srcDirs = [ 'src/integration-test/resources' ]
compileClasspath += main.output + test.output
runtimeClasspath += main.output + test.output
}
}

configurations {
integrationTestCompile.extendsFrom testImplementation
integrationTestRuntime.extendsFrom testRuntime
}

task integration(type: Test, description: 'Runs the integration tests.', group: 'Verification') {
testClassesDirs = sourceSets.integrationTest.output.classesDirs
classpath = sourceSets.integrationTest.runtimeClasspath
}

clean.doLast {
// Must disambiguate with project.delete since we're doing this in clean's doLast
project.delete "${rootDir}/aws-archive.zip"
}

task webpack(type: NpmTask, dependsOn: 'npmInstall') {
execOverrides {
it.workingDir = "${project.projectDir}/src/main/frontend/"
}
args = [ 'run', 'build' ]
}

processResources.dependsOn 'webpack'

// Generate SVG files for each compound in the local database. This
// assumes openbabel (obabel) is on your PATH. If you don't have openbabel
// set up, the app will be built but without images for compounds.
task createSmileSvgs(type: Exec) {
workingDir "${rootDir}"
if (System.getProperty('os.name').toLowerCase(Locale.ROOT).contains('windows')) {
def dir = rootDir.absolutePath.replace('\\', '/')
commandLine 'cmd', '/c', "C:\\Progra~1\\Git\\bin\\sh.exe --login -c '${dir}/util/create-smiles-svgs.sh'"
}
else {
commandLine '/bin/sh', '-c', './util/create-smiles-svgs.sh'
}
}
processResources.dependsOn 'createSmileSvgs'
createSmileSvgs.onlyIf { !file('src/main/resources/static/img/smiles').exists() }
createSmileSvgs.dependsOn 'webpack' // Ensure smiles generation occurs after webpack build

task webpackWatch(type: NpmTask) {
args = [ 'run', 'watch' ]
}

task copyStaticResourcesToBuildWatch(type: NpmTask) {
args = [ 'run', 'watch-static-into-build' ]
}

task makeAwsArchive(type: Zip) {
from "${rootDir}/build/libs/"
include 'random-acts-of-kinase*.jar'
from '.'
include 'Procfile'
include '.ebextensions/**'
archiveFileName = 'aws-archive.zip'
destinationDirectory = file(rootDir)
}

spotbugs {
includeFilter = file('spotbugs-exclude.xml')
}

spotbugsMain {
reports {
xml.enabled = false
html.enabled = true
}
}
spotbugsTest {
reports {
xml.enabled = false
html.enabled = true
}
}

bootRun {

jvmArgs = [ '-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=10356' ]
allprojects {

if (System.getProperty('spring.profiles.active') == null) {
println 'Defaulting to dev Spring profile'
System.setProperty('spring.profiles.active', 'dev')
repositories {
mavenCentral()
}
// Forward -D properties to the Spring Boot app
systemProperties = System.properties
}

jacocoTestReport {
reports {
xml.enabled = true // coveralls plugin depends on xml format report
html.enabled = true
}
subprojects {
}
File renamed without changes.
85 changes: 85 additions & 0 deletions service/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
# Random Acts of Kinase

[![Build Status](https://travis-ci.org/bobbylight/random-acts-of-kinase.svg?branch=master)](https://travis-ci.org/bobbylight/random-acts-of-kinase)
[![Coverage Status](https://coveralls.io/repos/github/bobbylight/random-acts-of-kinase/badge.svg?branch=master)](https://coveralls.io/github/bobbylight/random-acts-of-kinase?branch=master)

A web frontend for SGC kinase information.

A Spring Boot application exposes the data via a REST API. The frontend is written in Vue.

Note: The actual kinase data is not included in this repository, for obvious reasons.
You can still test the application without this data by running it with the `dev` Spring profile.

## Hacking
You can omit the `-xcreateSmileSvgs` options if you actually have openbabel installed
and configured properly in your environment. If you don't, you need to use this option to
omit that build task to prevent a build failure:

```sh
git clone https://github.com/bobbylight/random-acts-of-kinase.git
./gradlew build -xwebpack --warning-mode all -xcreateSmileSvgs
./gradlew bootRun -xwebpack -xcreateSmileSvgs # Starts application at localhost:8080
./gradlew webpackWatch # In another window, run webpack watch for UI updates
./gradlew copyStaticResourcesToBuildWatch # Copy webpack build into build/ for hot deploys
```

Unfortunately you need to start three processes to develop - annoying. I couldn't get
webpack to build directly into `build/` without Spring Boot getting cranky and clearing
out the contents of `build/resources/main/static` on restarts.

*Note:* Ctrl+C may not propagate the SIGKILL to the child npm tasks for `webpackWatch`
and `copyStaticResourcesToBuildWatch`, which can cause race conditions on file copies
and in turn weird behavior (stale static resources). If you see this happening, you
might consider running the wrapped npm tasks directly. See
[here](https://github.com/srs/gradle-node-plugin/issues/143) for more information.

If you have data to develop against in a local postgres instance, you can run against
via `./gradlew bootRun -Dspring.profiles.active=dev-postgres`.

The server is a simple Spring Boot application exposing a REST API and a little
static content. The client is Vue/JS/TypeScript.

The application will be hosted at [http://localhost:8080]().

To run tests:
```sh
./gradlew test -xwebpack # Service tests
npm test # Client tests
npm run coverage # Client tests + coverage report
```

The coverage report for the client-side tests lives here:
```sh
open reports/coverage/index.html
```

To deploy to AWS (we build a zip containing just the jar and a Procfile to launch
it, as configured in `.elasticbeanstalk/config.yml`):
```sh
./gradlew clean build --warning-mode all # Be sure to perform a production build
./gradlew makeAwsArchive
eb deploy --label "something"
```

## Utilities

The `util` folder contains shell scripts to do mundane tasks. For these scripts
to run you'll need to create a file named `env.sh` from the `env.sh.orig` template
file with connection info for a database containing the SGC data.

### Creating SVG images for compounds from SMILES strings
The SVG images of compounds used by the application are generated from their
SMILES strings. Generate them by running `./create-smiles-svgs.sh`. You'll
need to have `psql` on your `PATH` or this script will fail silently. This
script is run as part of `./gradlew build` so you typically don't need to
run it directly.

### Exporting data from our database into CSV files
To back up the database into CSV files, you can run `./export-to-csv.sh`.


## Updating the AWS database
We won't have to keep doing this once we have the data exported in a format we like...
```sh
psql --host=<host-name> --username=<user> --dbname=<db> -f create-db.ddl
```
Loading

0 comments on commit 06d22d3

Please sign in to comment.