diff --git a/.circleci/config.yml b/.circleci/config.yml deleted file mode 100644 index 1f04d3758..000000000 --- a/.circleci/config.yml +++ /dev/null @@ -1,28 +0,0 @@ -version: 2 -jobs: - build: - working_directory: ~/container-service - docker: - - image: circleci/openjdk:8 - steps: - - checkout - - restore_cache: - key: cache-{{ .Branch }}-{{ checksum "build.gradle" }} - - run: - name: Refresh dependencies - command: ./gradlew --refresh-dependencies dependencies - - run: - name: Compile - command: ./gradlew compileJava compileTestJava - - save_cache: - key: cache-{{ .Branch }}-{{ checksum "build.gradle" }} - paths: - - ~/.gradle - - setup_remote_docker - - run: - name: Run tests - command: ./gradlew test - - store_test_results: - path: build/test-results/ - - store_artifacts: - path: build/reports/tests/ diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 000000000..b13910c8f --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,8 @@ +version: 2 +updates: + - package-ecosystem: "gradle" + directory: "/" + schedule: + interval: "weekly" + assignees: + - "johnflavin" diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml new file mode 100644 index 000000000..8c0f5b465 --- /dev/null +++ b/.github/workflows/gradle.yml @@ -0,0 +1,89 @@ +# This workflow uses actions that are not certified by GitHub. +# They are provided by a third-party and are governed by +# separate terms of service, privacy policy, and support +# documentation. +# This workflow will build a Java project with Gradle and cache/restore any dependencies to improve the workflow execution time +# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-java-with-gradle + +name: Java CI with Gradle + +on: + push: + branches: [ "main", "develop" ] + pull_request: + branches: [ "main", "develop" ] + +jobs: + build: + + runs-on: ubuntu-latest + permissions: + contents: read + + steps: + - uses: actions/checkout@v4 + - name: Set up JDK + uses: actions/setup-java@v4 + with: + java-version: '8' + distribution: 'corretto' + + # Configure Gradle for optimal use in GitHub Actions, including caching of downloaded dependencies. + # See: https://github.com/gradle/actions/blob/main/setup-gradle/README.md + - name: Setup Gradle + uses: gradle/actions/setup-gradle@417ae3ccd767c252f5661f1ace9f835f9654f2b5 # v3.1.0 + + - name: Build with Gradle Wrapper + run: ./gradlew fatJar + - uses: actions/upload-artifact@v4 + with: + name: Package + path: build/libs + + test: + + runs-on: ubuntu-latest + permissions: + contents: read + + steps: + - uses: actions/checkout@v4 + - name: Set up JDK + uses: actions/setup-java@v4 + with: + java-version: '8' + distribution: 'corretto' + + # Configure Gradle for optimal use in GitHub Actions, including caching of downloaded dependencies. + # See: https://github.com/gradle/actions/blob/main/setup-gradle/README.md + - name: Setup Gradle + uses: gradle/actions/setup-gradle@417ae3ccd767c252f5661f1ace9f835f9654f2b5 # v3.1.0 + + - name: Build with Gradle Wrapper + run: ./gradlew test + + - name: Upload test artifacts + run: mkdir staging && cp -r build/reports staging/ && cp -r build/test-results staging/ + - uses: actions/upload-artifact@v4 + with: + name: Test Results + path: staging + + dependency-submission: + + runs-on: ubuntu-latest + permissions: + contents: write + + steps: + - uses: actions/checkout@v4 + - name: Set up JDK + uses: actions/setup-java@v4 + with: + java-version: '8' + distribution: 'corretto' + + # Generates and submits a dependency graph, enabling Dependabot Alerts for all project dependencies. + # See: https://github.com/gradle/actions/blob/main/dependency-submission/README.md + - name: Generate and submit dependency graph + uses: gradle/actions/dependency-submission@417ae3ccd767c252f5661f1ace9f835f9654f2b5 # v3.1.0 diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml deleted file mode 100644 index 18a7c8cc7..000000000 --- a/.gitlab-ci.yml +++ /dev/null @@ -1,21 +0,0 @@ ---- -include: - - project: flywheel-io/infrastructure/ci-templates - ref: master - file: security-scans.yml - - template: Jobs/SAST.gitlab-ci.yml - -gemnasium-maven-dependency_scanning: - variables: - DS_JAVA_VERSION: 8 - -variables: - SAST_EXCLUDED_PATHS: "spec, test, tests, tmp, swagger.json" - -sast: - variables: - SAST_EXCLUDED_PATHS: "$SAST_EXCLUDED_PATHS" - stage: test - - - diff --git a/build.gradle b/build.gradle index 2e28ddb67..781b3cadd 100644 --- a/build.gradle +++ b/build.gradle @@ -8,11 +8,9 @@ buildscript { plugins { id "idea" id "java" - id "maven-publish" - id "com.palantir.git-version" version "0.12.1" + id "com.palantir.git-version" version "3.1.0" id "io.spring.dependency-management" version "1.0.9.RELEASE" id "io.franzbecker.gradle-lombok" version "4.0.0" - id "net.linguica.maven-settings" version "0.5" } group "org.nrg.xnatx.plugins" @@ -26,7 +24,6 @@ def vJavassist = "3.21.0-GA" def vAwaitility = "2.0.0" repositories { - mavenLocal() maven { url "https://nrgxnat.jfrog.io/nrgxnat/libs-release" } maven { url "https://nrgxnat.jfrog.io/nrgxnat/libs-snapshot" } mavenCentral() @@ -207,42 +204,35 @@ tasks.register ( 'integrationTest', Test ) { test } -// Pulls in the Jenkins BUILD_NUMBER environment variable if available. -def buildDate = new Date() -def buildNumber = System.getenv().BUILD_NUMBER?.toInteger() ?: "Manual" -def isDirty, branchName, gitHash, gitHashFull, commitDistance, lastTag, isCleanTag - +// Build manifest from git repo information, if available +def gitDetails, isDirty try { - def gitDetails = versionDetails() + gitDetails = versionDetails() isDirty = gitVersion().endsWith ".dirty" - branchName = gitDetails.branchName ?: "Unknown" - gitHash = gitDetails.gitHash - gitHashFull = gitDetails.gitHashFull - commitDistance = gitDetails.commitDistance - lastTag = gitDetails.lastTag - isCleanTag = gitDetails.isCleanTag -} catch (IllegalArgumentException e) { +} catch (ignored) { logger.info "Got an error trying to read VCS metadata from git. It's possible this project is not under VCS control. Using placeholder values for manifest entries." + gitDetails = [ + branchName: "Unknown", + gitHash: "None", + gitHashFull: "None", + commitDistance: 0, + lastTag: "None", + isCleanTag: false + ] isDirty = true - branchName = "Unknown" - gitHash = "None" - gitHashFull = "None" - commitDistance = 0 - lastTag = "None" - isCleanTag = false } -ext.gitManifest = manifest { +def sharedManifest = java.manifest { attributes "Application-Name": pluginAppName, - "Build-Date": buildDate, - "Build-Number": buildNumber, + "Build-Date": new Date(), + "Build-Number": System.getenv().BUILD_NUMBER?.toInteger() ?: "Manual", // Pulls in the Jenkins BUILD_NUMBER environment variable if available. "Implementation-Version": project.version, - "Implementation-Sha": gitHash, - "Implementation-Sha-Full": gitHashFull, - "Implementation-Commit": commitDistance, - "Implementation-LastTag": lastTag, - "Implementation-Branch": branchName, - "Implementation-CleanTag": isCleanTag, + "Implementation-Sha": gitDetails.gitHash, + "Implementation-Sha-Full": gitDetails.gitHashFull, + "Implementation-Commit": gitDetails.commitDistance, + "Implementation-LastTag": gitDetails.lastTag, + "Implementation-Branch": gitDetails.branchName ?: "Unknown", + "Implementation-CleanTag": gitDetails.isCleanTag, "Implementation-Dirty": isDirty } @@ -257,8 +247,8 @@ task fatJar(type: Jar) { exclude "META-INF/*.RSA" } duplicatesStrategy "exclude" - manifest { - from gitManifest + manifest = java.manifest { + from sharedManifest } with jar } @@ -268,9 +258,9 @@ sourceSets.main.java { exclude "*/AutoValue.java" } -jar{ - manifest { - from gitManifest +jar { + manifest = java.manifest { + from sharedManifest } doLast { if (!gradle.taskGraph.hasTask(":fatJar")) { @@ -281,78 +271,73 @@ jar{ task sourceJar(type: Jar, dependsOn: classes) { classifier = "sources" - manifest { - from gitManifest + manifest = java.manifest { + from sharedManifest } from sourceSets.main.allSource } task javadocJar(type: Jar, dependsOn: javadoc) { classifier = "javadoc" - manifest { - from gitManifest + manifest = java.manifest { + from sharedManifest } from javadoc.destinationDir } -publishing { - publications { - mavenJava(MavenPublication) { - artifacts { - artifact sourceJar - artifact javadocJar - artifact fatJar - } - - pom.withXml { - def root = asNode() - root.appendNode("name", pluginAppName) - root.appendNode("description", "XNAT plugin for launching and managing containers.") - root.appendNode("url", "https://github.com/nrgxnat/container-service") - root.appendNode("inceptionYear", "2016") - - def scm = root.appendNode("scm") - scm.appendNode("url", "https://github.com/nrgxnat/container-service") - scm.appendNode("connection", "scm:https://github.com/nrgxnat/container-service.git") - scm.appendNode("developerConnection", "scm:git@github.com:nrgxnat/container-service") - - def license = root.appendNode("licenses").appendNode("license") - license.appendNode("name", "Simplified BSD 2-Clause License") - license.appendNode("url", "https://xnat.org/about/license.php") - license.appendNode("distribution", "repo") - - def developers = root.appendNode("developers") - def flavin = developers.appendNode("developer") - flavin.appendNode("id", "jflavin") - flavin.appendNode("name", "John Flavin") - flavin.appendNode("email", "jflavin@wustl.edu") - - def kelsey = developers.appendNode("developer") - kelsey.appendNode("id", "kelseym") - kelsey.appendNode("name", "Matt Kelsey") - kelsey.appendNode("email", "kelseym@wustl.edu") - - def will = developers.appendNode("developer") - will.appendNode("id", "hortonw") - will.appendNode("name", "Will Horton") - will.appendNode("email", "hortonw@wustl.edu") - } - } - } - repositories { - maven { - if (project.version.endsWith("-SNAPSHOT")) { - url "https://nrgxnat.jfrog.io/nrgxnat/libs-snapshot-local" - } else { - url "https://nrgxnat.jfrog.io/nrgxnat/libs-release-local" - } - // The value for name must match in ~/.m2/settings.xml - name = "XNAT_Artifactory" - } - } -} - -def propertyWithDefault(def String property, def Object value) { - hasProperty(property) ? getProperty(property) : value -} - +//publishing { +// publications { +// mavenJava(MavenPublication) { +// artifacts { +// artifact sourceJar +// artifact javadocJar +// artifact fatJar +// } +// +// pom.withXml { +// def root = asNode() +// root.appendNode("name", pluginAppName) +// root.appendNode("description", "XNAT plugin for launching and managing containers.") +// root.appendNode("url", "https://github.com/nrgxnat/container-service") +// root.appendNode("inceptionYear", "2016") +// +// def scm = root.appendNode("scm") +// scm.appendNode("url", "https://github.com/nrgxnat/container-service") +// scm.appendNode("connection", "scm:https://github.com/nrgxnat/container-service.git") +// scm.appendNode("developerConnection", "scm:git@github.com:nrgxnat/container-service") +// +// def license = root.appendNode("licenses").appendNode("license") +// license.appendNode("name", "Simplified BSD 2-Clause License") +// license.appendNode("url", "https://xnat.org/about/license.php") +// license.appendNode("distribution", "repo") +// +// def developers = root.appendNode("developers") +// def flavin = developers.appendNode("developer") +// flavin.appendNode("id", "jflavin") +// flavin.appendNode("name", "John Flavin") +// flavin.appendNode("email", "jflavin@wustl.edu") +// +// def kelsey = developers.appendNode("developer") +// kelsey.appendNode("id", "kelseym") +// kelsey.appendNode("name", "Matt Kelsey") +// kelsey.appendNode("email", "kelseym@wustl.edu") +// +// def will = developers.appendNode("developer") +// will.appendNode("id", "hortonw") +// will.appendNode("name", "Will Horton") +// will.appendNode("email", "hortonw@wustl.edu") +// } +// } +// } +// repositories { +// maven { +// if (project.version.endsWith("-SNAPSHOT")) { +// url "https://nrgxnat.jfrog.io/nrgxnat/libs-snapshot-local" +// } else { +// url "https://nrgxnat.jfrog.io/nrgxnat/libs-release-local" +// } +// // The value for name must match in ~/.m2/settings.xml +// name = "XNAT_Artifactory" +// } +// } +//} diff --git a/docs/list-of-containers-and-commands.md b/docs/list-of-containers-and-commands.md index f79f23373..9d033b227 100644 --- a/docs/list-of-containers-and-commands.md +++ b/docs/list-of-containers-and-commands.md @@ -14,6 +14,7 @@ Contributions to this page are very welcome. These can be in the form of links t | CONDR_METS lesion atlas | Misha / Flavin | | | Not published. 1. see [note on NIL Tools](#a-note-on-nil-tools). 2. This was built as a demo that relies on access to a non-public CNDA project. | | niftyreg | Flavin / Marc Modat | Image not published | [nrgxnat/docker-images/niftyreg](https://github.com/NrgXnat/docker-images/tree/master/niftyreg) | Developed during container hackathon at UCL. I was unsure whether to publish this image or not, so I did not. | | BIDS MRIQC | Flavin | N/A | [nrgxnat/docker-images/bids-mriqc](https://github.com/NrgXnat/docker-images/tree/master/bids-mriqc) | Not published as an image, only as a command. This fits the degin goal of the BIDS containers: use off-the-shelf BIDS docker images and write the command metadata to run them. | +| DICOM to DICOM JP2 compressed | jarrelscy | jarrelscy/dcm2jp2kdcm | [jarrelscy/dcm2jp2kdcm](https://github.com/jarrelscy/dcm2jp2kdcm) | Convert a session full of DICOM files to DICOM_COMPRESSED files which are jp2 encoded (Transfer syntax 1.2.840.10008.1.2.4.90). | ## Setup Containers @@ -60,4 +61,4 @@ Many of the existing tools employed in the NRG lab—often as pipelines on CNDA * The code should not be contained within a Docker image not controlled by NIL. This image would become the _de facto_ official release of the tools. If such an image were to exist, it should by all rights belong to the owner and creator of those tools: the NIL. 2. The tools often rely on the local availablity of atlas image files. Those altas images are available on the internal servers we have here, but are not generally available. If the atlases were included in a Docker image, its size would be many tens of gigabytes (typical sizes are tens to hundreds of megabytes). This would be prohibitive to install or develop against. -For this reason, any tool that is written using the NIL tools is not, in general, possible to containerize at this time. Exceptions are certainly possible; for instance, the lesion atlas image used only a few NIL tools, which could be copied directly into the Docker image itself. However, while this image can be created, is not distributable for reason 1. above. \ No newline at end of file +For this reason, any tool that is written using the NIL tools is not, in general, possible to containerize at this time. Exceptions are certainly possible; for instance, the lesion atlas image used only a few NIL tools, which could be copied directly into the Docker image itself. However, while this image can be created, is not distributable for reason 1. above.