I ended up spending some hours looking into this which resulted in the following script that I now run as part of my built script:
#!/bin/bash
CACHE_DIR=$NETLIFY_BUILD_BASE/cache
JAVA_DOWNLOAD_URL="https://download.java.net/java/GA/jdk17.0.2/dfd4a8d0985749f896bed50d7138ee7f/8/GPL/openjdk-17.0.2_linux-x64_bin.tar.gz"
JAVA_RELEASE=jdk-17.0.2 # Must match directory inside archive in JAVA_DOWNLOAD_URL
currentver="$(java -version 2>&1 |head -n1 | cut -d'"' -f2 |cut -d'.' -f1)"
requiredver="11" # Shadow-cljs requires a minimum of Java 11
# Version check shamelessly copied from StackOverflow:
# https://unix.stackexchange.com/a/285928
if [ ! "$(printf '%s\n' "$requiredver" "$currentver" | sort -V | head -n1)" = "$requiredver" ]; then
echo "Java version 11 is required as minimum by Shadow-cljs (found Java version $currentver)"
if [ ! -d "$CACHE_DIR/$JAVA_RELEASE" ]; then
echo "Downloading $JAVA_RELEASE since it isn't available in cache"
wget --quiet -O openjdk.tar.gz $JAVA_DOWNLOAD_URL
tar xf openjdk.tar.gz --directory $CACHE_DIR
fi
echo "Enabling $JAVA_RELEASE from cache, by making it available on PATH"
export PATH=$CACHE_DIR/$JAVA_RELEASE/bin:$PATH
fi
Whenever a “new enough” version of Java is missing Java 17 is downloaded and the PATH is updated to make use of this Java version, otherwise, nothing happens. This way I can run the same built-scripts locally (where my Java version is good) and on Netlify where it isn’t. The download is also cached causing only the PATH to be updated most times (adding next to zero additional built-time).
Notice: the script needs to be “sourced” (with a preceding dot) like so in package.json:
{
"scripts": {
"release": ". ./ensure_newish_java.sh && run-s frontend:release css:release",
...
This is required for the updated PATH environment variable to be passed along to the next script(s) in line (in the above example run-s frontend:release css:release).