import org.gradle.plugins.ide.eclipse.model.Library
import java.security.MessageDigest
import java.util.regex.Matcher
+import java.util.concurrent.Executors
+import java.util.concurrent.Future
+import java.util.concurrent.ScheduledExecutorService
+import java.util.concurrent.TimeUnit
import groovy.transform.ExternalizeMethods
import groovy.util.XmlParser
import groovy.xml.XmlUtil
dependencies {
classpath "com.vladsch.flexmark:flexmark-all:0.62.0"
classpath "org.jsoup:jsoup:1.14.3"
- classpath "com.eowise:gradle-imagemagick:0.5.1"
+ classpath 'ru.vyarus:gradle-use-python-plugin:4.0.0'
}
}
id 'application'
id 'eclipse'
id "com.diffplug.gradle.spotless" version "3.28.0"
- id 'com.github.johnrengelman.shadow' version '4.0.3'
- id 'com.install4j.gradle' version '10.0.3'
+ id 'com.github.johnrengelman.shadow' version '6.0.0'
+ id 'com.install4j.gradle' version '10.0.8'
id 'com.dorongold.task-tree' version '2.1.1' // only needed to display task dependency tree with gradle task1 [task2 ...] taskTree
id 'com.palantir.git-version' version '0.13.0' apply false
+ id 'ru.vyarus.use-python' version '4.0.0'
}
repositories {
- jcenter()
mavenCentral()
mavenLocal()
}
jvlChannelName = CHANNEL.toLowerCase()
install4jSuffix = CHANNEL.substring(0, 1).toUpperCase() + CHANNEL.substring(1).toLowerCase(); // BUILD -> Build
install4jDMGDSStore = "${install4j_images_dir}/${install4j_dmg_ds_store}"
+ install4jDMGDSStoreJSON = "${install4j_images_dir}/${install4j_dmg_ds_store_json}"
install4jDMGBackgroundImageDir = "${install4j_images_dir}"
install4jDMGBackgroundImageBuildDir = "build/imagemagick/install4j"
install4jDMGBackgroundImageFile = "${install4j_dmg_background}"
- install4jInstallerName = "${jalview_name} Non-Release Installer"
+ install4jmacOSArchiveName = "${jalview_name} Non-Release ${JALVIEW_VERSION} Installer"
install4jExecutableName = install4j_executable_name
- install4jExtraScheme = "jalviewx"
- install4jMacIconsFile = string("${install4j_images_dir}/${install4j_mac_icons_file}")
- install4jWindowsIconsFile = string("${install4j_images_dir}/${install4j_windows_icons_file}")
- install4jPngIconFile = string("${install4j_images_dir}/${install4j_png_icon_file}")
+ install4jExtraScheme = "jalviewextra"
install4jBackground = string("${install4j_images_dir}/${install4j_background}")
install4jBuildDir = "${install4j_build_dir}/${JAVA_VERSION}"
+ install4jDMGFixedDSStoreX64 = "build/macos_dmg/${install4j_dmg_ds_store}-x64"
+ install4jDMGFixedDSStoreAarch64 = "build/macos_dmg/${install4j_dmg_ds_store}-aarch64"
+ install4jDMGVolumeIcon = string("${install4j_images_dir}/${install4j_dmg_volume_icon}")
install4jCheckSums = true
applicationName = "${jalview_name}"
case "BUILD":
// TODO: get bamboo build artifact URL for getdown artifacts
- getdown_channel_base = bamboo_channelbase
getdownChannelName = string("${bamboo_planKey}/${JAVA_VERSION}")
- getdownAppBase = string("${bamboo_channelbase}/${bamboo_planKey}${bamboo_getdown_channel_suffix}/${JAVA_VERSION}")
+
+ /**
+ * This URL doesn't work
+ * if (bamboo_buildResultsUrl && bamboo_buildResultsKey) {
+ * getdownAppBase = "${bamboo_buildResultsKey}/${bamboo_buildResultsArtifactPath}"
+ * } else {
+ */
+ getdownAppBase = "${bamboo_channelbase}/${bamboo_planKey}/${bamboo_getdown_channel_suffix}"
+ /* } */
jvlChannelName += "_${getdownChannelName}"
// automatically add the test group Not-bamboo for exclusion
if ("".equals(testng_excluded_groups)) {
getdownSetAppBaseProperty = true
reportRsyncCommand = true
install4jSuffix = ""
- install4jInstallerName = "${jalview_name} Installer"
+ install4jmacOSArchiveName = "Install ${jalview_name} ${JALVIEW_VERSION}"
+ install4jExtraScheme = (CHANNEL=="RELEASE")?"jalviewx":"jalviewjs"
break
case "ARCHIVE":
JALVIEW_VERSION=JALVIEW_VERSION+"-d${suffix}-${buildDate}"
install4jSuffix = "Develop ${suffix}"
install4jExtraScheme = "jalviewd"
- install4jInstallerName = "${jalview_name} Develop ${suffix} Installer"
+ install4jmacOSArchiveName = "Install ${jalview_name} Develop ${suffix} ${JALVIEW_VERSION}"
getdownChannelName = string("develop-${suffix}")
getdownChannelDir = string("${getdown_website_dir}/${getdownChannelName}")
getdownAppBaseDir = string("${jalviewDir}/${getdownChannelDir}/${JAVA_VERSION}")
install4jSuffix = "Develop"
install4jExtraScheme = "jalviewd"
- install4jInstallerName = "${jalview_name} Develop Installer"
+ install4jmacOSArchiveName = "Install ${jalview_name} Develop ${JALVIEW_VERSION}"
backgroundImageText = true
break
JALVIEW_VERSION = JALVIEW_VERSION+"-test"
install4jSuffix = "Test"
install4jExtraScheme = "jalviewt"
- install4jInstallerName = "${jalview_name} Test Installer"
+ install4jmacOSArchiveName = "Install ${jalview_name} Test ${JALVIEW_VERSION}"
backgroundImageText = true
break
JALVIEW_VERSION = "TEST"
install4jSuffix = "Test-Local"
install4jExtraScheme = "jalviewt"
- install4jInstallerName = "${jalview_name} Test Installer"
+ install4jmacOSArchiveName = "Install ${jalview_name} Test ${JALVIEW_VERSION}"
backgroundImageText = true
break
.replaceAll("_+", "_") // collapse __
.replaceAll("_*-_*", "-") // collapse _-_
.toLowerCase()
+ install4jmacOSArchiveX64Name = "${install4jmacOSArchiveName} (Intel)"
+ install4jmacOSArchiveAarch64Name = "${install4jmacOSArchiveName} (Apple Silicon)"
getdownWrapperLink = install4jUnixApplicationFolder // e.g. "jalview_local"
getdownAppDir = string("${getdownAppBaseDir}/${getdownAppDistDir}")
if (install4jHomeDir.startsWith("~/")) {
install4jHomeDir = System.getProperty("user.home") + install4jHomeDir.substring(1)
}
+ install4jmacOSArchiveX64DMGFilename = "${install4jApplicationFolder}-${JALVIEW_VERSION}-macos-x64-java_${JAVA_INTEGER_VERSION}"
+ install4jmacOSArchiveAarch64DMGFilename = "${install4jApplicationFolder}-${JALVIEW_VERSION}-macos-aarch64-java_${JAVA_INTEGER_VERSION}"
+
resourceBuildDir = string("${buildDir}/resources")
resourcesBuildDir = string("${resourceBuildDir}/resources_build")
jalviewjsJ2sAltSettingsFileName = string("${jalviewDir}/${jalviewjs_j2s_alt_settings}")
jalviewjsJ2sProps = null
jalviewjsJ2sPlugin = jalviewjs_j2s_plugin
+ jalviewjsStderrLaunchFilename = "${jalviewjsSiteDir}/"+(file(jalviewjs_stderr_launch).getName())
eclipseWorkspace = null
eclipseBinary = string("")
eclipseVersion = string("")
eclipseDebug = false
+
+ jalviewjsChromiumUserDir = "${jalviewjsBuildDir}/${jalviewjs_chromium_user_dir}"
+ jalviewjsChromiumProfileDir = "${ext.jalviewjsChromiumUserDir}/${jalviewjs_chromium_profile_name}"
+
// ENDEXT
}
return dateOnly ? map["date"] : [map, content]
}
+def setReleaseAndWhatsNew(File whatsnewMdFile, File releaseMdFile) {
+ if (CHANNEL != "") {
+ // we may have a version string that has additional bits vs the actual release version
+ if (CHANNEL != "RELEASE")
+ {
+ var nearestVersion = "${JALVIEW_VERSION_UNDERSCORES}"
+ println "Stripping rc/test/etc for ${nearestVersion}"
+ nearestVersion = nearestVersion.replaceAll(~/-?(d|rc|test|develop|dev).*/,"")
+ var nearestMd = file("${jalviewDir}/${whatsnew_dir}/whatsnew-${nearestVersion}.md")
+ println "Looking in ${nearestMd}"
+ if (nearestMd.exists()) {
+ whatsnewMdFile = nearestMd
+ releaseMdFile = file("${jalviewDir}/${releases_dir}/release-${nearestVersion}.md")
+ }
+ }
+ }
+ return [whatsnewMdFile,releaseMdFile]
+}
+
task hugoTemplates {
group "website"
description "Create partially populated md pages for hugo website build"
def givenDate = null
def givenChannel = null
def givenVersion = null
- if (CHANNEL == "RELEASE") {
+
+ if (CHANNEL!="") {
+ (whatsnewMdFile, releaseMdFile) = setReleaseAndWhatsNew(whatsnewMdFile, releaseMdFile)
+
def (map, content) = mdFileComponents(releaseMdFile)
givenDate = map.date
givenChannel = map.channel
givenVersion = map.version
changes = content
- if (givenVersion != null && givenVersion != JALVIEW_VERSION) {
+ if (CHANNEL=="RELEASE" && givenVersion != null && givenVersion != JALVIEW_VERSION) {
throw new GradleException("'version' header (${givenVersion}) found in ${releaseMdFile} does not match JALVIEW_VERSION (${JALVIEW_VERSION})")
}
-
if (whatsnewMdFile.exists())
whatsnew = whatsnewMdFile.text
}
def releaseMdFile = file("${releasesMdDir}/release-${JALVIEW_VERSION_UNDERSCORES}.md")
def whatsnewMdFile = file("${whatsnewMdDir}/whatsnew-${JALVIEW_VERSION_UNDERSCORES}.md")
+ (whatsnewMdFile,releaseMdFile) = setReleaseAndWhatsNew(whatsnewMdFile, releaseMdFile)
+
if (CHANNEL == "RELEASE") {
if (!releaseMdFile.exists()) {
throw new GradleException("File ${releaseMdFile} must be created for RELEASE")
compileTestJava.dependsOn compileJava
+
+test {
+ group = "Verification"
+ description = "Runs all testTaskN tasks)"
+
+ if (useClover) {
+ dependsOn cloverClasses
+ } else { //?
+ dependsOn testClasses
+ }
+
+ // not running tests in this task
+ exclude "**/*"
+}
/* testTask0 is the main test task */
task testTask0(type: Test) {
group = "Verification"
preserveOrder true
useDefaultListeners=true
}
+ timeout = Duration.ofMinutes(15)
}
/* separated tests */
preserveOrder true
useDefaultListeners=true
}
+ timeout = Duration.ofMinutes(5)
+}
+
+task testTask2(type: Test) {
+ group = "Verification"
+ description = "Tests that need to be isolated from the main test run"
+ useTestNG() {
+ includeGroups name
+ excludeGroups testng_excluded_groups.split(",")
+ preserveOrder true
+ useDefaultListeners=true
+ }
+ timeout = Duration.ofMinutes(5)
+}
+task testTask3(type: Test) {
+ group = "Verification"
+ description = "Tests that need to be isolated from the main test run"
+ useTestNG() {
+ includeGroups name
+ excludeGroups testng_excluded_groups.split(",")
+ preserveOrder true
+ useDefaultListeners=true
+ }
+ timeout = Duration.ofMinutes(5)
}
+/* insert more testTaskNs here -- change N to next digit or other string */
+/*
+task testTaskN(type: Test) {
+ group = "Verification"
+ description = "Tests that need to be isolated from the main test run"
+ useTestNG() {
+ includeGroups name
+ excludeGroups testng_excluded_groups.split(",")
+ preserveOrder true
+ useDefaultListeners=true
+ }
+}
+*/
+
+
/*
* adapted from https://medium.com/@wasyl/pretty-tests-summary-in-gradle-744804dd676c
* to summarise test results from all Test tasks
testTask.mustRunAfter "testTask0"
testTask.testLogging { logging ->
- events TestLogEvent.FAILED,
- TestLogEvent.SKIPPED,
- TestLogEvent.STANDARD_OUT,
- TestLogEvent.STANDARD_ERROR
+ events TestLogEvent.FAILED
+// TestLogEvent.SKIPPED,
+// TestLogEvent.STANDARD_OUT,
+// TestLogEvent.STANDARD_ERROR
exceptionFormat TestExceptionFormat.FULL
showExceptions true
showCauses true
showStackTraces true
+ if (test_output) {
+ showStandardStreams true
+ }
+ info.events = [ TestLogEvent.FAILED ]
+ }
+
+ if (OperatingSystem.current().isMacOsX()) {
+ testTask.systemProperty "apple.awt.UIElement", "true"
+ testTask.environment "JAVA_TOOL_OPTIONS", "-Dapple.awt.UIElement=true"
}
+
ignoreFailures = true // Always try to run all tests for all modules
afterSuite { desc, result ->
-
- if (desc.parent) return // Only summarize results for whole modules
+ if (desc.parent)
+ return // Only summarize results for whole modules
def resultsInfo = [testTask.project.name, testTask.name, result, TimeCategory.minus(new Date(result.endTime), new Date(result.startTime)), testTask.reports.html.entryPoint]
jvmArgs += additional_compiler_args
doFirst {
+ // this is not perfect yet -- we should only add the commandLineIncludePatterns to the
+ // testTasks that include the tests, and exclude all from the others.
+ // get --test argument
+ filter.commandLineIncludePatterns = test.filter.commandLineIncludePatterns
+ // do something with testTask.getCandidateClassFiles() to see if the test should silently finish because of the
+ // commandLineIncludePatterns not matching anything. Instead we are doing setFailOnNoMatchingTests(false) below
+
+
if (useClover) {
println("Running tests " + (useClover?"WITH":"WITHOUT") + " clover")
}
}
+
+ /* don't fail on no matching tests (so --tests will run across all testTasks) */
+ testTask.filter.setFailOnNoMatchingTests(false)
+
+ /* ensure the "test" task dependsOn all the testTasks */
+ test.dependsOn testTask
}
gradle.buildFinished {
private static String getSummaryLine(s, pn, tn, rt, rc, rs, rf, rsk, t, col) {
def colour = 'black'
+ def text = rt
def nocol = false
- switch(rt) {
- case TestResult.ResultType.SUCCESS:
- colour = 'green'
- break;
- case TestResult.ResultType.FAILURE:
- colour = 'red'
- break;
- default:
- nocol = true
- break;
+ if (rc == 0) {
+ text = "-----"
+ nocol = true
+ } else {
+ switch(rt) {
+ case TestResult.ResultType.SUCCESS:
+ colour = 'green'
+ break;
+ case TestResult.ResultType.FAILURE:
+ colour = 'red'
+ break;
+ default:
+ nocol = true
+ break;
+ }
}
StringBuilder sb = new StringBuilder()
sb.append("${pn}")
if (tn != null)
sb.append(":${tn}")
sb.append(" results: ")
- sb.append(colString(s, col && !nocol, colour, rt))
+ sb.append(colString(s, col && !nocol, colour, text))
sb.append(" (")
sb.append("${rc} tests, ")
sb.append(colString(s, col && rs > 0, 'green', rs))
}
/* END of test tasks results summary */
-test {
- // from original test task
- if (useClover) {
- dependsOn cloverClasses
- } else { //?
- dependsOn testClasses
- }
- dependsOn tasks.withType(Test).matching {t -> t.getName().startsWith("testTask")}
-
- // not running tests in this task
- exclude "**/*"
-}
-
task compileLinkCheck(type: JavaCompile) {
options.fork = true
}
+task launcherJar(type: Jar) {
+ manifest {
+ attributes (
+ "Main-Class": shadow_jar_main_class,
+ "Implementation-Version": JALVIEW_VERSION,
+ "Application-Name": applicationName
+ )
+ }
+}
+
shadowJar {
group = "distribution"
description = "Create a single jar file with all dependency libraries merged. Can be run with java -jar"
if (buildDist) {
dependsOn makeDist
}
- from ("${jalviewDir}/${libDistDir}") {
- include("*.jar")
- }
+
+ def jarFiles = fileTree(dir: "${jalviewDir}/${libDistDir}", include: "*.jar", exclude: "regex.jar").getFiles()
+ def groovyJars = jarFiles.findAll {it1 -> file(it1).getName().startsWith("groovy-swing")}
+ def otherJars = jarFiles.findAll {it2 -> !file(it2).getName().startsWith("groovy-swing")}
+ from groovyJars
+ from otherJars
+
manifest {
- attributes "Implementation-Version": JALVIEW_VERSION,
- "Application-Name": applicationName
+ // shadowJar manifest must inheritFrom another Jar task. Can't set attributes here.
+ inheritFrom(project.tasks.launcherJar.manifest)
+ }
+ // we need to include the groovy-swing Include-Package for it to run in the shadowJar
+ doFirst {
+ def jarFileManifests = []
+ groovyJars.each { jarFile ->
+ def mf = zipTree(jarFile).getFiles().find { it.getName().equals("MANIFEST.MF") }
+ if (mf != null) {
+ jarFileManifests += mf
+ }
+ }
+ manifest {
+ from (jarFileManifests) {
+ eachEntry { details ->
+ if (!details.key.equals("Import-Package")) {
+ details.exclude()
+ }
+ }
+ }
+ }
}
duplicatesStrategy "INCLUDE"
+ // this mainClassName is mandatory but gets ignored due to manifest created in doFirst{}. Set the Main-Class as an attribute in launcherJar instead
mainClassName = shadow_jar_main_class
mergeServiceFiles()
classifier = "all-"+JALVIEW_VERSION+"-j"+JAVA_VERSION
dependsOn getdownImagesProcess
}
-task getdownWebsite() {
+task getdownWebsiteBuild() {
group = "distribution"
- description = "Create the getdown minimal app folder, and website folder for this version of jalview. Website folder also used for offline app installer"
+ description = "Create the getdown minimal app folder, and website folder for this version of jalview. Website folder also used for offline app installer. No digest is created."
dependsOn getdownImages
if (buildDist) {
}
def getdownWebsiteResourceFilenames = []
+ def getdownWebsitePResourceFilenames = []
def getdownResourceDir = getdownResourceDir
def getdownResourceFilenames = []
}
getdownWebsiteResourceFilenames += file(channelPropsFile).getName()
- // set some getdownTxt_ properties then go through all properties looking for getdownTxt_...
+ // set some getdownTxt_ properties then go through all properties looking for getdown_txt_...
def props = project.properties.sort { it.key }
if (getdownAltJavaMinVersion != null && getdownAltJavaMinVersion.length() > 0) {
props.put("getdown_txt_java_min_version", getdownAltJavaMinVersion)
props.put("getdown_txt_ui.instant_background_image", "${getdownImagesBuildDir}/${getdown_instant_background_image}")
props.put("getdown_txt_ui.error_background", "${getdownImagesBuildDir}/${getdown_error_background}")
props.put("getdown_txt_ui.progress_image", "${getdownImagesBuildDir}/${getdown_progress_image}")
- props.put("getdown_txt_ui.icon", "${getdownImagesBuildDir}/${getdown_icon}")
- props.put("getdown_txt_ui.mac_dock_icon", "${getdownImagesBuildDir}/${getdown_mac_dock_icon}")
+ props.put("getdown_txt_ui.icon", "${getdownImagesDir}/${getdown_icon}")
+ props.put("getdown_txt_ui.mac_dock_icon", "${getdownImagesDir}/${getdown_mac_dock_icon}")
}
props.put("getdown_txt_title", jalview_name)
}
if (r.exists()) {
val = "${getdown_resource_dir}/" + r.getName()
- getdownWebsiteResourceFilenames += val
+ if (prop.startsWith("getdown_txt_ui.")) {
+ getdownWebsitePResourceFilenames += val
+ } else {
+ getdownWebsiteResourceFilenames += val
+ }
getdownResourceFilenames += r.getPath()
}
}
}
}
+ getdownWebsitePResourceFilenames.each{ filename ->
+ getdownTextLines += "presource = ${filename}"
+ }
getdownWebsiteResourceFilenames.each{ filename ->
getdownTextLines += "resource = ${filename}"
}
into getdownResourceDir
}
}
-
- def getdownWrapperScripts = [ getdown_bash_wrapper_script, getdown_powershell_wrapper_script, getdown_batch_wrapper_script ]
+
+ def getdownWrapperScripts = [
+ getdown_bash_wrapper_script,
+ getdown_powershell_wrapper_script,
+ getdown_bash_update_script,
+ getdown_powershell_update_script,
+ ]
+ def run_powershell = file( "${jalviewDir}/utils/getdown/${getdown_wrapper_script_dir}/${getdown_run_powershell}" )
+ def run_other_script = file( "${jalviewDir}/utils/getdown/${getdown_wrapper_script_dir}/${getdown_run_other_script}" )
getdownWrapperScripts.each{ script ->
def s = file( "${jalviewDir}/utils/getdown/${getdown_wrapper_script_dir}/${script}" )
if (s.exists()) {
from s
into "${getdownAppBaseDir}/${getdown_wrapper_script_dir}"
}
- getdownTextLines += "resource = ${getdown_wrapper_script_dir}/${script}"
+ getdownTextLines += "xresource = ${getdown_wrapper_script_dir}/${script}"
+ }
+ def ext = script.toLowerCase(Locale.ROOT).substring(script.lastIndexOf(".") + 1)
+ if ("ps1".equals(ext)) {
+ def base = script.take(script.lastIndexOf("."))
+ def newbase = "update".equals(base) ? "${install4jUnixApplicationFolder}_update" : install4jUnixApplicationFolder
+ if (!newbase.equals(base)) {
+ copy {
+ from run_other_script
+ rename(run_other_script.getName(), "${newbase}.${ext}")
+ into "${getdownAppBaseDir}/${getdown_wrapper_script_dir}"
+ getdownTextLines += "xresource = ${getdown_wrapper_script_dir}/${newbase}.${ext}"
+ filter(ReplaceTokens,
+ beginToken: '__',
+ endToken: '__',
+ tokens: [
+ 'OTHERSCRIPT': script
+ ]
+ ) }
+ }
+ copy {
+ from run_powershell
+ rename(run_powershell.getName(), "${newbase}.bat")
+ into "${getdownAppBaseDir}/${getdown_wrapper_script_dir}"
+ getdownTextLines += "xresource = ${getdown_wrapper_script_dir}/${newbase}.bat"
+ }
}
}
getdownTextLines += "class = ${main_class}"
// Not setting these properties in general so that getdownappbase and getdowndistdir will default to release version in jalview.bin.Cache
if (getdownSetAppBaseProperty) {
- getdownTextLines += "jvmarg = -Dgetdowndistdir=${getdownAppDistDir}"
- getdownTextLines += "jvmarg = -Dgetdownappbase=${getdownAppBase}"
+ getdownTextLines += "jvmarg = -Dlauncher.distdir=${getdownAppDistDir}"
}
def getdownTxt = file("${getdownAppBaseDir}/getdown.txt")
getdownLaunchJvl = getdown_launch_jvl_name + ( (jvlChannelName != null && jvlChannelName.length() > 0)?"-${jvlChannelName}":"" ) + ".jvl"
def launchJvl = file("${getdownAppBaseDir}/${getdownLaunchJvl}")
- launchJvl.write("appbase=${getdownAppBase}")
+ def launch_lines = []
+ launch_lines.add("appbase = ${getdownAppBase}")
+ launch_lines.add("jvl_replace = true")
+ launchJvl.write(launch_lines.join("\n"))
// files going into the getdown website dir: getdown-launcher.jar
copy {
task getdownDigest(type: JavaExec) {
group = "distribution"
description = "Digest the getdown website folder"
- dependsOn getdownWebsite
+
+ dependsOn getdownWebsiteBuild
+
doFirst {
classpath = files(getdownLauncher)
}
}
}
+task getdownWebsite {
+ group = "distribution"
+ description = "A task to create the whole getdown channel website dir including digest file"
+
+ dependsOn getdownWebsiteBuild
+ dependsOn getdownDigest
+}
task getdownArchiveBuild() {
group = "distribution"
description = "Put files in the archive dir to go on the website"
- dependsOn getdownWebsite
+ dependsOn getdownWebsiteBuild
def v = "v${JALVIEW_VERSION_UNDERSCORES}"
def vDir = "${getdownArchiveDir}/${v}"
}
}
+ // the wrapper scripts dir
+ if ( file("${getdownAppBaseDir}/${getdown_wrapper_script_dir}").exists() ) {
+ copy {
+ from "${getdownAppBaseDir}/${getdown_wrapper_script_dir}"
+ into "${getdownFullArchiveDir}/${getdown_wrapper_script_dir}"
+ }
+ }
+
getdownArchiveTxt.write(getdownArchiveTextLines.join("\n"))
def vLaunchJvl = file(getdownVersionLaunchJvl)
install4jHomeDir = "/Applications/install4j.app/Contents/Resources/app"
}
installDir(file(install4jHomeDir))
-
- mediaTypes = Arrays.asList(install4j_media_types.split(","))
}
}
}
+ // delete .VolumeIcon.icns in macos DMG if there isn't one
+ if (!file(install4jDMGVolumeIcon).exists()) {
+ println("No '.VolumeIcon.icns' file found. Removing from install4j file.")
+ install4jConfigXml.'**'.macosArchive.topLevelFiles.each { topLevelFiles ->
+ topLevelFiles.file.each() { file ->
+ if (file.attribute("name") && file.attribute("name").equals(".VolumeIcon.icns")) {
+ println("Removing "+file.toString())
+ topLevelFiles.remove(file)
+ }
+ }
+ }
+ } else {
+ println("Using '.VolumeIcon.icns' file '${install4jDMGVolumeIcon}'")
+ }
+
// disable install screen for OSX dmg (for 2.11.2.0)
install4jConfigXml.'**'.macosArchive.each { macosArchive ->
macosArchive.attributes().remove('executeSetupApp')
}
}
-task install4jDMGBackgroundImage {
+
+python {
+ pip 'ds_store:1.3.0'
+}
+
+task install4jCustomiseDS_StoreX64(type: PythonTask) {
+ inputs.file(install4jDMGDSStore)
+ outputs.file(install4jDMGFixedDSStoreX64)
+ def command_args = [ jalview_customise_ds_store,
+ '--input', install4jDMGDSStore,
+ '--output', install4jDMGFixedDSStoreX64,
+ '--volumename', install4jmacOSArchiveX64Name,
+ '--backgroundfile', install4j_dmg_background_filename,
+ '--dmg', install4jmacOSArchiveX64DMGFilename + ".dmg",
+ '--appname', "${applicationName}.app",
+ ]
+ if (file(install4jDMGDSStoreJSON).exists()) {
+ command_args += [ '--config', install4jDMGDSStoreJSON ]
+ inputs.file(install4jDMGDSStoreJSON)
+ }
+ command = command_args
+ doFirst {
+ println("Running command '${command_args.join(' ')}'")
+ }
+}
+
+task install4jCustomiseDS_StoreAarch64(type: PythonTask) {
+ inputs.file(install4jDMGDSStore)
+ outputs.file(install4jDMGFixedDSStoreAarch64)
+ def command_args = [ jalview_customise_ds_store,
+ '--input', install4jDMGDSStore,
+ '--output', install4jDMGFixedDSStoreAarch64,
+ '--volumename', install4jmacOSArchiveAarch64Name,
+ '--backgroundfile', install4j_dmg_background_filename,
+ '--dmg', install4jmacOSArchiveAarch64DMGFilename + ".dmg",
+ '--appname', "${applicationName}.app",
+ ]
+ if (file(install4jDMGDSStoreJSON).exists()) {
+ command_args += [ '--config', install4jDMGDSStoreJSON ]
+ inputs.file(install4jDMGDSStoreJSON)
+ }
+ command = command_args
+ doFirst {
+ def print_args = []
+ for (int i = 0; i < command_args.size(); i++) {
+ def arg = command_args[i]
+ print_args += (i > 0 && !arg.startsWith("-")) ? "\"${arg}\"" : arg
+ }
+ println("Running command '${print_args.join(' ')}'")
+ }
+}
+
+task install4jCustomiseDS_Store {
+ dependsOn install4jCustomiseDS_StoreX64
+ dependsOn install4jCustomiseDS_StoreAarch64
+}
+
+task install4jDMGVmoptionsFile(type: Copy) {
+ def inputDir = "${jalviewDir}/${install4j_utils_dir}"
+ def outputDir = "${jalviewDir}/${install4j_build_dir}/tmp"
+
+ def installDateTime = getDate("yyyy-MM-dd HH:mm:ss") + " (build time)"
+
+ from(inputDir) {
+ include(string("${install4j_default_vmoptions}"))
+ rename(string("${install4j_default_vmoptions}"), string("${install4j_default_vmoptions}.X64"))
+
+ filter(ReplaceTokens,
+ beginToken: '__',
+ endToken: '__',
+ tokens: [
+ 'INSTALLERFILENAME': string("${install4jmacOSArchiveX64DMGFilename}.dmg"),
+ 'INSTALLDATETIME': installDateTime
+ ]
+ )
+
+ }
+
+ from(inputDir) {
+ include(string("${install4j_default_vmoptions}"))
+ rename(string("${install4j_default_vmoptions}"), string("${install4j_default_vmoptions}.AARCH64"))
+
+ filter(ReplaceTokens,
+ beginToken: '__',
+ endToken: '__',
+ tokens: [
+ 'INSTALLERFILENAME': string("${install4jmacOSArchiveAarch64DMGFilename}.dmg"),
+ 'INSTALLDATETIME': installDateTime
+ ]
+ )
+ }
+
+ into outputDir
+
+ inputs.file("${inputDir}/${install4j_default_vmoptions}")
+ outputs.file("${outputDir}/${install4j_default_vmoptions}.X64")
+ outputs.file("${outputDir}/${install4j_default_vmoptions}.AARCH64")
+}
+
+task install4jDMGProcesses {
dependsOn install4jDMGBackgroundImageProcess
+ dependsOn install4jCustomiseDS_Store
+ dependsOn install4jDMGVmoptionsFile
}
task installerFiles(type: com.install4j.gradle.Install4jTask) {
dependsOn getdown
dependsOn copyInstall4jTemplate
dependsOn cleanInstallersDataFiles
- dependsOn install4jDMGBackgroundImage
+ dependsOn install4jDMGProcesses
projectFile = install4jConfFile
+ // run install4j with 4g
+ vmParameters = ["-Xmx4294967296"]
+
// create an md5 for the input files to use as version for install4j conf file
def digest = MessageDigest.getInstance("MD5")
digest.update(
'BUNDLE_ID': install4jBundleId,
'INTERNAL_ID': install4jInternalId,
'WINDOWS_APPLICATION_ID': install4jWinApplicationId,
- 'MACOS_DMG_DS_STORE': install4jDMGDSStore,
+ 'MACOS_X64_DMG_DS_STORE': install4jDMGFixedDSStoreX64,
+ 'MACOS_AARCH64_DMG_DS_STORE': install4jDMGFixedDSStoreAarch64,
'MACOS_DMG_BG_IMAGE': "${install4jDMGBackgroundImageBuildDir}/${install4jDMGBackgroundImageFile}",
+ 'MACOS_DMG_BG_FILENAME': install4j_dmg_background_filename,
'WRAPPER_LINK': getdownWrapperLink,
'BASH_WRAPPER_SCRIPT': getdown_bash_wrapper_script,
'POWERSHELL_WRAPPER_SCRIPT': getdown_powershell_wrapper_script,
+ 'BASH_UPDATE_SCRIPT': getdown_bash_update_script,
+ 'POWERSHELL_UPDATE_SCRIPT': getdown_powershell_update_script,
'WRAPPER_SCRIPT_BIN_DIR': getdown_wrapper_script_dir,
- 'INSTALLER_NAME': install4jInstallerName,
+ 'MACOSARCHIVE_X64_NAME': install4jmacOSArchiveX64Name,
+ 'MACOSARCHIVE_AARCH64_NAME': install4jmacOSArchiveAarch64Name,
'INSTALL4J_UTILS_DIR': install4j_utils_dir,
'GETDOWN_CHANNEL_DIR': getdownChannelDir,
'GETDOWN_FILES_DIR': getdown_files_dir,
'GETDOWN_ALT_DIR': getdown_app_dir_alt,
'GETDOWN_INSTALL_DIR': getdown_install_dir,
'INFO_PLIST_FILE_ASSOCIATIONS_FILE': install4j_info_plist_file_associations,
- 'BUILD_DIR': install4jBuildDir,
+ 'BUILD_DIR': install4j_build_dir,
'APPLICATION_CATEGORIES': install4j_application_categories,
'APPLICATION_FOLDER': install4jApplicationFolder,
'UNIX_APPLICATION_FOLDER': install4jUnixApplicationFolder,
'EXECUTABLE_NAME': install4jExecutableName,
'EXTRA_SCHEME': install4jExtraScheme,
- 'MAC_ICONS_FILE': install4jMacIconsFile,
- 'WINDOWS_ICONS_FILE': install4jWindowsIconsFile,
- 'PNG_ICON_FILE': install4jPngIconFile,
+ 'ICONS_DIR': install4j_images_dir,
+ 'MAC_ICONS_FILE': install4j_mac_icons_file,
+ 'WINDOWS_ICONS_FILE': install4j_windows_icons_file,
+ 'PNG_ICON_FILE': install4j_png_icon_file,
'BACKGROUND': install4jBackground,
+ 'MACOSARCHIVE_X64_DMG_FILENAME': install4jmacOSArchiveX64DMGFilename,
+ 'MACOSARCHIVE_AARCH64_DMG_FILENAME': install4jmacOSArchiveAarch64DMGFilename,
+ 'MACOSARCHIVE_VOLUMEICON': install4jDMGVolumeIcon,
+ 'INSTALLER_ICON': "${getdownImagesDir}/${install4j_installer_icon}",
+ 'INSTALLER_MAC_ICON': "${getdownImagesDir}/${install4j_installer_mac_icon}",
+ 'INSTALLER_WINDOWS_ICON': "${getdownImagesDir}/${install4j_installer_windows_icon}",
+ 'TITLE_ICON': "${getdownImagesDir}/${install4j_title_icon}",
+ 'LOG_FILE': "${install4jUnixApplicationFolder}.log",
]
+ if (project.hasProperty("install4j_build_ids")) {
+ buildIds = Arrays.asList(install4j_build_ids.split(","))
+ } else if (project.hasProperty("install4j_media_types")) {
+ buildSelected = true
+ mediaTypes = Arrays.asList(install4j_media_types.split(","))
+ }
+
def varNameMap = [
'mac': 'MACOS',
'windows': 'WINDOWS',
//variables.each{k,v->println("${k}=${v}")}
destination = "${jalviewDir}/${install4jBuildDir}"
- buildSelected = true
if (install4j_faster.equals("true") || CHANNEL.startsWith("LOCAL")) {
faster = true
into project.name
def EXCLUDE_FILES=[
+ "dist/*",
"build/*",
"bin/*",
"test-output/",
}
+task jalviewjsCopyStderrLaunchFile(type: Copy) {
+ from file(jalviewjs_stderr_launch)
+ into jalviewjsSiteDir
+
+ inputs.file jalviewjs_stderr_launch
+ outputs.file jalviewjsStderrLaunchFilename
+}
+
+task cleanJalviewjsChromiumUserDir {
+ doFirst {
+ delete jalviewjsChromiumUserDir
+ }
+ outputs.dir jalviewjsChromiumUserDir
+ // always run when depended on
+ outputs.upToDateWhen { !file(jalviewjsChromiumUserDir).exists() }
+}
+
+task jalviewjsChromiumProfile {
+ dependsOn cleanJalviewjsChromiumUserDir
+ mustRunAfter cleanJalviewjsChromiumUserDir
+
+ def firstRun = file("${jalviewjsChromiumUserDir}/First Run")
+
+ doFirst {
+ mkdir jalviewjsChromiumProfileDir
+ firstRun.text = ""
+ }
+ outputs.file firstRun
+}
+
+task jalviewjsLaunchTest {
+ group "Test"
+ description "Check JalviewJS opens in a browser"
+ dependsOn jalviewjsBuildSite
+ dependsOn jalviewjsCopyStderrLaunchFile
+ dependsOn jalviewjsChromiumProfile
+
+ def macOS = OperatingSystem.current().isMacOsX()
+ def chromiumBinary = macOS ? jalviewjs_macos_chromium_binary : jalviewjs_chromium_binary
+ if (chromiumBinary.startsWith("~/")) {
+ chromiumBinary = System.getProperty("user.home") + chromiumBinary.substring(1)
+ }
+
+ def stdout
+ def stderr
+ doFirst {
+ def timeoutms = Integer.valueOf(jalviewjs_chromium_overall_timeout) * 1000
+
+ def binary = file(chromiumBinary)
+ if (!binary.exists()) {
+ throw new StopExecutionException("Could not find chromium binary '${chromiumBinary}'. Cannot run task ${name}.")
+ }
+ stdout = new ByteArrayOutputStream()
+ stderr = new ByteArrayOutputStream()
+ def execStdout
+ def execStderr
+ if (jalviewjs_j2s_to_console.equals("true")) {
+ execStdout = new org.apache.tools.ant.util.TeeOutputStream(
+ stdout,
+ System.out)
+ execStderr = new org.apache.tools.ant.util.TeeOutputStream(
+ stderr,
+ System.err)
+ } else {
+ execStdout = stdout
+ execStderr = stderr
+ }
+ def execArgs = [
+ "--no-sandbox", // --no-sandbox IS USED BY THE THORIUM APPIMAGE ON THE BUILDSERVER
+ "--headless=new",
+ "--disable-gpu",
+ "--timeout=${timeoutms}",
+ "--virtual-time-budget=${timeoutms}",
+ "--user-data-dir=${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_chromium_user_dir}",
+ "--profile-directory=${jalviewjs_chromium_profile_name}",
+ "--allow-file-access-from-files",
+ "--enable-logging=stderr",
+ "file://${jalviewDirAbsolutePath}/${jalviewjsStderrLaunchFilename}"
+ ]
+
+ if (true || macOS) {
+ ScheduledExecutorService executor = Executors.newScheduledThreadPool(3);
+ Future f1 = executor.submit(
+ () -> {
+ exec {
+ standardOutput = execStdout
+ errorOutput = execStderr
+ executable(chromiumBinary)
+ args(execArgs)
+ println "COMMAND: '"+commandLine.join(" ")+"'"
+ }
+ executor.shutdownNow()
+ }
+ )
+
+ def noChangeBytes = 0
+ def noChangeIterations = 0
+ executor.scheduleAtFixedRate(
+ () -> {
+ String stderrString = stderr.toString()
+ // shutdown the task if we have a success string
+ if (stderrString.contains(jalviewjs_desktop_init_string)) {
+ f1.cancel()
+ Thread.sleep(1000)
+ executor.shutdownNow()
+ }
+ // if no change in stderr for 10s then also end
+ if (noChangeIterations >= jalviewjs_chromium_idle_timeout) {
+ executor.shutdownNow()
+ }
+ if (stderrString.length() == noChangeBytes) {
+ noChangeIterations++
+ } else {
+ noChangeBytes = stderrString.length()
+ noChangeIterations = 0
+ }
+ },
+ 1, 1, TimeUnit.SECONDS)
+
+ executor.schedule(new Runnable(){
+ public void run(){
+ f1.cancel()
+ executor.shutdownNow()
+ }
+ }, timeoutms, TimeUnit.MILLISECONDS)
+
+ executor.awaitTermination(timeoutms+10000, TimeUnit.MILLISECONDS)
+ executor.shutdownNow()
+ }
+
+ }
+
+ doLast {
+ def found = false
+ stderr.toString().eachLine { line ->
+ if (line.contains(jalviewjs_desktop_init_string)) {
+ println("Found line '"+line+"'")
+ found = true
+ return
+ }
+ }
+ if (!found) {
+ throw new GradleException("Could not find evidence of Desktop launch in JalviewJS.")
+ }
+ }
+}
+
+
task jalviewjs {
group "JalviewJS"
- description "Build the site"
+ description "Build the JalviewJS site and run the launch test"
dependsOn jalviewjsBuildSite
+ dependsOn jalviewjsLaunchTest
}
-