From 110f5f0a5e6c7a233b21076a55e809faa219daf0 Mon Sep 17 00:00:00 2001 From: NouemanKHAL Date: Fri, 15 May 2026 01:18:41 +0200 Subject: [PATCH] Use absolute path to bundled Ruby instead of PATH MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Before, the buildpack relied on the app's `ruby` being on PATH at runtime. Two problems with that: - On stacks without system Ruby (cflinuxfs4), the runtime `.global_env` conditionally prepended /home/vcap/deps/N/bin to PATH — which means the buildpack's Ruby 3.0.5 could shadow ruby_buildpack's Ruby when the Datadog buildpack was the launch buildpack in the chain, surprising Ruby apps with a different runtime. - The buildpack's scripts (get_tags.rb, update_datadog_config.rb, etc.) could end up running under whatever Ruby the user shipped, not the 3.0.5 we test against. Change: always install the bundled Ruby into $DEPS_DIR/$DEPS_IDX/bin at staging time, write `export DD_RUBY=/home/vcap/deps/$DEPS_IDX/bin/ruby` into `.global_env` (no PATH mutation), and have every runtime callsite use "$DD_RUBY" instead of bare `ruby`. Callsites updated: run-datadog.sh, test-endpoint.sh, update_agent_config.sh, utils.sh. Co-Authored-By: Claude Opus 4.7 (1M context) --- bin/compile | 19 ++++++++----------- bin/supply | 19 ++++++++----------- lib/run-datadog.sh | 8 ++++---- lib/scripts/update_agent_config.sh | 8 ++++---- lib/scripts/utils.sh | 4 ++-- lib/test-endpoint.sh | 2 +- 6 files changed, 27 insertions(+), 33 deletions(-) diff --git a/bin/compile b/bin/compile index 39ed5cf8..2b9d9794 100755 --- a/bin/compile +++ b/bin/compile @@ -18,22 +18,19 @@ chmod +x "${DATADOG_DIR}/scripts/update_agent_config.sh" cp "${ROOT_DIR}/lib/scripts/get_tags.rb" "${DATADOG_DIR}/scripts/get_tags.rb" -RUBY_CMD=ruby +RUBY_CMD=$DEPS_DIR/$DEPS_IDX/bin/ruby -# install ruby if needed (the case of cflinuxfs4 or custom stacks) -if ! which ruby > /dev/null; then +# Install the bundled Ruby for our scripts. Always done so the buildpack +# stops relying on the app's Ruby (which may not exist, or may be a +# different version on the chained ruby_buildpack). +if [ ! -x "${RUBY_CMD}" ]; then echo "Installing Ruby" tar -xzf "${ROOT_DIR}/lib/ruby_3.0.5.tgz" -C "$DEPS_DIR/$DEPS_IDX" && echo "Ruby Install finished" - export PATH=$PATH:/home/vcap/deps/$DEPS_IDX/bin - RUBY_CMD=$DEPS_DIR/$DEPS_IDX/bin/ruby fi -# create a .global_env file to be sourced by external scripts -# for now, it appends the buildpack deps/bin folder to the PATH env variable of the caller -# this is needed for stacks where ruby is not installed since our scripts rely on it -echo "if ! which ruby > /dev/null; then - export PATH=\$PATH:/home/vcap/deps/$DEPS_IDX/bin -fi" > "$DATADOG_DIR/.global_env" +# Expose the bundled Ruby to runtime scripts via an absolute path rather +# than mutating PATH, so we don't shadow the app's own ruby/gem/bundle. +echo "export DD_RUBY=/home/vcap/deps/$DEPS_IDX/bin/ruby" > "$DATADOG_DIR/.global_env" # for subsquent buildpacks and for buildpack metadata detection echo "config: {} diff --git a/bin/supply b/bin/supply index 39ed5cf8..2b9d9794 100755 --- a/bin/supply +++ b/bin/supply @@ -18,22 +18,19 @@ chmod +x "${DATADOG_DIR}/scripts/update_agent_config.sh" cp "${ROOT_DIR}/lib/scripts/get_tags.rb" "${DATADOG_DIR}/scripts/get_tags.rb" -RUBY_CMD=ruby +RUBY_CMD=$DEPS_DIR/$DEPS_IDX/bin/ruby -# install ruby if needed (the case of cflinuxfs4 or custom stacks) -if ! which ruby > /dev/null; then +# Install the bundled Ruby for our scripts. Always done so the buildpack +# stops relying on the app's Ruby (which may not exist, or may be a +# different version on the chained ruby_buildpack). +if [ ! -x "${RUBY_CMD}" ]; then echo "Installing Ruby" tar -xzf "${ROOT_DIR}/lib/ruby_3.0.5.tgz" -C "$DEPS_DIR/$DEPS_IDX" && echo "Ruby Install finished" - export PATH=$PATH:/home/vcap/deps/$DEPS_IDX/bin - RUBY_CMD=$DEPS_DIR/$DEPS_IDX/bin/ruby fi -# create a .global_env file to be sourced by external scripts -# for now, it appends the buildpack deps/bin folder to the PATH env variable of the caller -# this is needed for stacks where ruby is not installed since our scripts rely on it -echo "if ! which ruby > /dev/null; then - export PATH=\$PATH:/home/vcap/deps/$DEPS_IDX/bin -fi" > "$DATADOG_DIR/.global_env" +# Expose the bundled Ruby to runtime scripts via an absolute path rather +# than mutating PATH, so we don't shadow the app's own ruby/gem/bundle. +echo "export DD_RUBY=/home/vcap/deps/$DEPS_IDX/bin/ruby" > "$DATADOG_DIR/.global_env" # for subsquent buildpacks and for buildpack metadata detection echo "config: {} diff --git a/lib/run-datadog.sh b/lib/run-datadog.sh index e1009217..26919447 100644 --- a/lib/run-datadog.sh +++ b/lib/run-datadog.sh @@ -17,7 +17,7 @@ DD_RUN_AGENT="${DD_RUN_AGENT:-true}" # source updated PATH . "$DATADOG_DIR/.global_env" -export DD_TAGS=$(ruby "${DATADOG_DIR}/scripts/get_tags.rb") +export DD_TAGS=$("$DD_RUBY" "${DATADOG_DIR}/scripts/get_tags.rb") echo "${DD_TAGS}" > "${DATADOG_DIR}/.dd_tags.txt" setup_datadog() { @@ -45,7 +45,7 @@ setup_datadog() { if [ -n "${LOGS_CONFIG}" ]; then mkdir -p ${LOGS_CONFIG_DIR} echo "creating logs config" - ruby "${DATADOG_DIR}/scripts/create_logs_config.rb" + "$DD_RUBY" "${DATADOG_DIR}/scripts/create_logs_config.rb" fi # The yaml file requires the tags to be an array, @@ -111,7 +111,7 @@ setup_datadog() { popd # update datadog config - ruby "${DATADOG_DIR}/scripts/update_datadog_config.rb" + "$DD_RUBY" "${DATADOG_DIR}/scripts/update_datadog_config.rb" # mark the script as finished, useful to sync the update_agent_config script touch "${DATADOG_DIR}/.setup_completed" @@ -119,7 +119,7 @@ setup_datadog() { } start_datadog() { - export DD_TAGS=$(ruby "${DATADOG_DIR}/scripts/get_tags.rb") + export DD_TAGS=$("$DD_RUBY" "${DATADOG_DIR}/scripts/get_tags.rb") pushd "${DATADOG_DIR}" export DD_LOG_FILE="${DATADOG_DIR}/dogstatsd.log" diff --git a/lib/scripts/update_agent_config.sh b/lib/scripts/update_agent_config.sh index 2508735d..96cdbdae 100644 --- a/lib/scripts/update_agent_config.sh +++ b/lib/scripts/update_agent_config.sh @@ -17,23 +17,23 @@ release_lock() { } write_tags_to_file() { - export DD_TAGS=$(ruby "${DATADOG_DIR}"/scripts/get_tags.rb) + export DD_TAGS=$("$DD_RUBY" "${DATADOG_DIR}"/scripts/get_tags.rb) export LOGS_CONFIG_DIR="${DATADOG_DIR}/dist/conf.d/logs.d" export LOGS_CONFIG log_info "Updating node_agent_tags.txt" - ruby "${DATADOG_DIR}/scripts/update_tags.rb" + "$DD_RUBY" "${DATADOG_DIR}/scripts/update_tags.rb" # update datadog config - ruby "${DATADOG_DIR}/scripts/update_datadog_config.rb" + "$DD_RUBY" "${DATADOG_DIR}/scripts/update_datadog_config.rb" if [ "${DD_ENABLE_CAPI_METADATA_COLLECTION}" = "true" ]; then # update logs configs if [ -n "${LOGS_CONFIG}" ]; then mkdir -p "${LOGS_CONFIG_DIR}" log_info "Updating logs config" - ruby "${DATADOG_DIR}/scripts/create_logs_config.rb" + "$DD_RUBY" "${DATADOG_DIR}/scripts/create_logs_config.rb" fi fi diff --git a/lib/scripts/utils.sh b/lib/scripts/utils.sh index 2f5b3871..9d9f5f71 100644 --- a/lib/scripts/utils.sh +++ b/lib/scripts/utils.sh @@ -207,7 +207,7 @@ find_pid_kill_and_wait() { redirect() { while kill -0 $$; do if [ "${DD_SPARSE_APP_LOGS}" = "true" ]; then - ruby "${DATADOG_DIR}/scripts/nc.rb" "${STD_LOG_COLLECTION_PORT}" || sleep 0.5 + "$DD_RUBY" "${DATADOG_DIR}/scripts/nc.rb" "${STD_LOG_COLLECTION_PORT}" || sleep 0.5 else nc localhost "${STD_LOG_COLLECTION_PORT}" || sleep 0.5 fi @@ -219,7 +219,7 @@ redirect() { \"title\": \"Resetting buildpack log redirection\", \"text\": \"TCP socket on port ${STD_LOG_COLLECTION_PORT} for log redirection closed. Restarting it.\", \"priority\": \"normal\", - \"tags\": $(LEGACY_TAGS_FORMAT=true ruby ${DATADOG_DIR}/scripts/get_tags.rb), + \"tags\": $(LEGACY_TAGS_FORMAT=true "$DD_RUBY" "${DATADOG_DIR}/scripts/get_tags.rb"), \"alert_type\": \"info\" }" "${DD_API_SITE}v1/events?api_key=${DD_API_KEY}" fi diff --git a/lib/test-endpoint.sh b/lib/test-endpoint.sh index 5d36cd10..fcd8e1ba 100644 --- a/lib/test-endpoint.sh +++ b/lib/test-endpoint.sh @@ -73,7 +73,7 @@ if [ "${DD_LOGS_ENABLED}" = "true" ] && [ -n "${DD_LOGS_CONFIG_LOGS_DD_URL}" ] & \"title\": \"Log endpoint cannot be reached - Log collection not started\", \"text\": \"Could not establish a connection to ${DD_LOGS_CONFIG_LOGS_DD_URL} after 5 seconds. Log collection has not been started.\", \"priority\": \"normal\", - \"tags\": $(ruby "${DATADOG_DIR}"/scripts/get_tags.rb), + \"tags\": $("$DD_RUBY" "${DATADOG_DIR}"/scripts/get_tags.rb), \"alert_type\": \"error\" }" "api.${DD_SITE}/v1/events?api_key=${DD_API_KEY}" else