@@ -10,8 +10,6 @@ ENV_DIR="${3}"
1010
1111# shellcheck source=lib/util.sh
1212source " ${BUILDPACK_DIR} /lib/util.sh"
13- # shellcheck source=lib/lein.sh
14- source " ${BUILDPACK_DIR} /lib/lein.sh"
1513# shellcheck source=lib/metrics.sh
1614source " ${BUILDPACK_DIR} /lib/metrics.sh"
1715# shellcheck source=lib/output.sh
@@ -24,7 +22,62 @@ util::export_env_dir "${ENV_DIR}" "." "JAVA_OPTS"
2422metrics::init " ${CACHE_DIR} " " clojure"
2523metrics::setup
2624
27- if grep -q lein-npm " ${BUILD_DIR} /project.clj" ; then
25+ # To ensure the cache created by older Clojure buildpack versions doesn't stay around indefinitely, we explicitly
26+ # delete these old directories. This will speed up subsequent app builds since it will take less time to restore
27+ # the cache before each build.
28+ #
29+ # Note: This buildpack used to install and run npm. The node_modules dir is specific to the old Clojure install
30+ # and does not overlap with the official Node.js buildpack.
31+ rm -rf \
32+ " ${CACHE_DIR} /clojure-bp-apt" \
33+ " ${CACHE_DIR} /node_modules"
34+
35+ openjdk::install_openjdk_via_jvm_common_buildpack " ${BUILD_DIR} " " ${BUILDPACK_DIR} "
36+
37+ util::cache_copy " .m2" " ${CACHE_DIR} " " ${BUILD_DIR} "
38+
39+ # Install rlwrap shim for Leiningen 1.x and clj REPLs.
40+ # rlwrap is technically a dependency for both, but it only enhances REPL functionality
41+ # with line editing and command history. This shim allows clj and lein 1.x to run without
42+ # errors, but does not provide actual readline capabilities. Most users don't use REPLs
43+ # in a Heroku context. Users can install their own rlwrap via the APT buildpack and this
44+ # shim will not interfere.
45+ mkdir -p " ${BUILD_DIR} /.heroku/bin"
46+ cp " ${BUILDPACK_DIR} /opt/rlwrap" " ${BUILD_DIR} /.heroku/bin/rlwrap"
47+
48+ # Run clojure install script (clojure / clj may be needed from leiningen for newer cli tools)
49+ CLOJURE_CLI_VERSION=" ${CLOJURE_CLI_VERSION:- 1.10.0.411} "
50+
51+ output::step " Installing Clojure ${CLOJURE_CLI_VERSION} CLI tools"
52+
53+ CLOJURE_INSTALL_SCRIPT=" $( mktemp) "
54+ curl --retry 3 --retry-connrefused --connect-timeout 5 -sSfL --max-time 60 -o " ${CLOJURE_INSTALL_SCRIPT} " " https://download.clojure.org/install/linux-install-${CLOJURE_CLI_VERSION} .sh"
55+ chmod +x " ${CLOJURE_INSTALL_SCRIPT} "
56+
57+ # Clojure CLI is non-portable as it embeds absolute paths during installation.
58+ # Create a symlink before installation to ensure those paths work at both compile and runtime.
59+ CLOJURE_CLI_DIR=" .heroku/clj"
60+ mkdir -p " ${BUILD_DIR} /${CLOJURE_CLI_DIR} "
61+ if [[ " $( realpath " ${BUILD_DIR} " ) " != " $( realpath /app) " ]]; then
62+ mkdir -p " /app/$( dirname " ${CLOJURE_CLI_DIR} " ) "
63+ ln -nsf " ${BUILD_DIR} /${CLOJURE_CLI_DIR} " " /app/${CLOJURE_CLI_DIR} "
64+ fi
65+
66+ " ${CLOJURE_INSTALL_SCRIPT} " --prefix " /app/${CLOJURE_CLI_DIR} " 2> /dev/null | output::indent
67+ chmod +x " /app/${CLOJURE_CLI_DIR} /bin/" *
68+ export PATH=" /app/${CLOJURE_CLI_DIR} /bin:${PATH} "
69+
70+ # Pre-warm Clojure CLI cache to avoid download messages for its own dependencies when its used for the first time by
71+ # the buildpack or the user at runtime.
72+ clojure -e " (println)" & > /dev/null
73+
74+ output::step " Reading Leiningen project properties"
75+
76+ lein_project_plugins=$( " ${BUILDPACK_DIR} /opt/get_project_property.clj" " ${BUILD_DIR} /project.clj" " plugins" )
77+ lein_project_uberjar_name=$( " ${BUILDPACK_DIR} /opt/get_project_property.clj" " ${BUILD_DIR} /project.clj" " uberjar-name" )
78+ lein_project_min_lein_version=$( " ${BUILDPACK_DIR} /opt/get_project_property.clj" " ${BUILD_DIR} /project.clj" " min-lein-version" )
79+
80+ if grep -q lein-npm <<< " ${lein_project_plugins}" ; then
2881 if ! command -v npm & > /dev/null; then
2982 output::error << -EOF
3083 Error: Your project.clj references lein-npm but npm is not available.
@@ -46,52 +99,31 @@ if grep -q lein-npm "${BUILD_DIR}/project.clj"; then
4699 fi
47100fi
48101
49- openjdk::install_openjdk_via_jvm_common_buildpack " ${BUILD_DIR} " " ${BUILDPACK_DIR} "
50-
51- # Install rlwrap shim for Leiningen 1.x and clj REPLs.
52- # rlwrap is technically a dependency for both, but it only enhances REPL functionality
53- # with line editing and command history. This shim allows clj and lein 1.x to run without
54- # errors, but does not provide actual readline capabilities. Most users don't use REPLs
55- # in a Heroku context. Users can install their own rlwrap via the APT buildpack and this
56- # shim will not interfere.
57- mkdir -p " ${BUILD_DIR} /.heroku/bin"
58- cp " ${BUILDPACK_DIR} /opt/rlwrap" " ${BUILD_DIR} /.heroku/bin/rlwrap"
59-
60- # To ensure the cache created by older Clojure buildpack versions doesn't stay around indefinitely, we explicitly
61- # delete these old directories. This will speed up subsequent app builds since it will take less time to restore
62- # the cache before each build.
63- #
64- # Note: This buildpack used to install and run npm. The node_modules dir is specific to the old Clojure install
65- # and does not overlap with the official Node.js buildpack.
66- rm -rf \
67- " ${CACHE_DIR} /clojure-bp-apt" \
68- " ${CACHE_DIR} /node_modules"
69-
70- # Run clojure install script (clojure / clj may be needed from leiningen for newer cli tools)
71- CLOJURE_CLI_VERSION=" ${CLOJURE_CLI_VERSION:- 1.10.0.411} "
72- output::step " Installing Clojure ${CLOJURE_CLI_VERSION} CLI tools"
73- CLOJURE_INSTALL_NAME=" linux-install-${CLOJURE_CLI_VERSION} .sh"
74- CLOJURE_INSTALL_URL=" https://download.clojure.org/install/${CLOJURE_INSTALL_NAME} "
75- curl --retry 3 --retry-connrefused --connect-timeout 5 -sSfL --max-time 60 -o " /tmp/${CLOJURE_INSTALL_NAME} " " ${CLOJURE_INSTALL_URL} "
76- chmod +x " /tmp/${CLOJURE_INSTALL_NAME} "
77- mkdir -p " ${BUILD_DIR} /.heroku/clj"
78- " /tmp/${CLOJURE_INSTALL_NAME} " --prefix " ${BUILD_DIR} /.heroku/clj" 2> /dev/null | output::indent
79- chmod +x " ${BUILD_DIR} /.heroku/clj/bin/" *
80- export PATH=" ${BUILD_DIR} /.heroku/clj/bin:${PATH} "
81-
82102# Check for vendored lein script
83103if [[ -x " ${BUILD_DIR} /bin/lein" ]]; then
84104 output::step " Using vendored Leiningen at bin/lein"
85105 LEIN_BIN_PATH=" ${BUILD_DIR} /bin/lein"
86- calculate_lein_build_task " ${BUILD_DIR} "
106+ if [[ -n " ${lein_project_uberjar_name} " ]]; then
107+ export LEIN_BUILD_TASK=" ${LEIN_BUILD_TASK:- uberjar} "
108+ export LEIN_INCLUDE_IN_SLUG=" ${LEIN_INCLUDE_IN_SLUG:- no} "
109+ else
110+ export LEIN_BUILD_TASK=" ${LEIN_BUILD_TASK:- with-profile production compile : all} "
111+ fi
87112 " ${LEIN_BIN_PATH} " version 2> /dev/null | output::indent
88113else
89114 # Determine Leiningen version
90- if is_lein_2 " ${BUILD_DIR} " ; then
115+ case " ${lein_project_min_lein_version} " in
116+ 2* )
91117 LEIN_VERSION=" 2.9.1"
92118 LEIN_BIN_SOURCE=" $( dirname " ${0} " ) /../opt/lein2"
93- calculate_lein_build_task " ${BUILD_DIR} "
94- else
119+ if [[ -n " ${lein_project_uberjar_name} " ]]; then
120+ export LEIN_BUILD_TASK=" ${LEIN_BUILD_TASK:- uberjar} "
121+ export LEIN_INCLUDE_IN_SLUG=" ${LEIN_INCLUDE_IN_SLUG:- no} "
122+ else
123+ export LEIN_BUILD_TASK=" ${LEIN_BUILD_TASK:- with-profile production compile : all} "
124+ fi
125+ ;;
126+ * )
95127 LEIN_VERSION=" 1.7.1"
96128 LEIN_BIN_SOURCE=" $( dirname " ${0} " ) /../opt/lein1"
97129 LEIN_BUILD_TASK=" ${LEIN_BUILD_TASK:- deps} "
103135 WARNING: No :min-lein-version found in project.clj; using ${LEIN_VERSION} .
104136 You probably don't want this!
105137 EOF
106- fi
138+ ;;
139+ esac
107140
108141 # install leiningen jar
109142 LEIN1_JAR_URL=" https://lang-jvm.s3.us-east-1.amazonaws.com/leiningen-${LEIN_VERSION} -standalone.jar"
@@ -153,11 +186,6 @@ if [[ ! -e "${BUILD_DIR}/.lein/profiles.clj" ]]; then
153186 echo ' {}' > " ${BUILD_DIR} /.lein/profiles.clj"
154187fi
155188
156- # unpack existing cache
157- if [[ ! -d " ${BUILD_DIR} /.m2" ]]; then
158- util::cache_copy " .m2" " ${CACHE_DIR} " " ${BUILD_DIR} "
159- fi
160-
161189output::step " Building with Leiningen"
162190
163191# Calculate build command
@@ -194,10 +222,12 @@ mkdir -p "$(dirname "${PROFILE_PATH}")"
194222 echo " export RING_ENV=\"\$ {RING_ENV:-production}\" "
195223} >> " ${PROFILE_PATH} "
196224
197- # rewrite Clojure CLI path
198- mv " ${BUILD_DIR} /.heroku/clj/bin/clojure" " ${BUILD_DIR} /.heroku/clj/bin/clojure.old"
199- sed -e " s/\/tmp\/$( basename " ${BUILD_DIR} " ) /\/app/g" " ${BUILD_DIR} /.heroku/clj/bin/clojure.old" > " ${BUILD_DIR} /.heroku/clj/bin/clojure"
200- chmod +x " ${BUILD_DIR} /.heroku/clj/bin/clojure"
225+ # Write export script for use by subsequent buildpacks. The export script sets up the environment so that other
226+ # buildpacks in the chain can access Clojure CLI and Leiningen during their build phase. This script
227+ # is sourced by the buildpack framework between buildpack executions.
228+ cat << -EOF >>"${BUILDPACK_DIR} /export"
229+ export PATH="/app/.heroku/bin:/app/${CLOJURE_CLI_DIR} /bin:/app/.lein/bin:\$ {PATH}"
230+ EOF
201231
202232# repack cache with new assets
203233mkdir -p " ${CACHE_DIR} "
0 commit comments