From cba345025c6254e75fb45947989ac511309da085 Mon Sep 17 00:00:00 2001 From: Jose Diaz-Gonzalez Date: Mon, 8 Sep 2025 04:28:05 -0400 Subject: [PATCH 01/15] feat: add a Railpack builder to Dokku Closes #7615 --- Dockerfile | 5 + docker/etc/sudoers.d/dokku-docker | 2 +- docker/usr/local/bin/railpack | 20 +++ docs/appendices/file-formats/railpack-json.md | 3 + docs/deployment/builders/railpack.md | 163 ++++++++++++++++++ docs/template.html | 1 + plugins/builder-railpack/builder-build | 67 +++++++ plugins/builder-railpack/builder-detect | 17 ++ plugins/builder-railpack/builder-release | 30 ++++ plugins/builder-railpack/commands | 15 ++ plugins/builder-railpack/core-post-extract | 30 ++++ .../dockerfiles/builder-build.Dockerfile | 7 + .../dockerfiles/builder-release.Dockerfile | 2 + plugins/builder-railpack/help-functions | 33 ++++ plugins/builder-railpack/install | 16 ++ plugins/builder-railpack/internal-functions | 116 +++++++++++++ plugins/builder-railpack/plugin.toml | 4 + plugins/builder-railpack/post-app-clone-setup | 14 ++ .../builder-railpack/post-app-rename-setup | 15 ++ plugins/builder-railpack/post-delete | 15 ++ plugins/builder-railpack/report | 6 + plugins/builder-railpack/subcommands/default | 6 + plugins/builder-railpack/subcommands/report | 6 + plugins/builder-railpack/subcommands/set | 30 ++++ plugins/docker-options/docker-args-deploy | 2 +- tests/unit/builder-railpack.bats | 52 ++++++ tests/unit/report.bats | 1 + tests/unit/test_helper.bash | 6 + 28 files changed, 682 insertions(+), 2 deletions(-) create mode 100644 docker/usr/local/bin/railpack create mode 100644 docs/appendices/file-formats/railpack-json.md create mode 100644 docs/deployment/builders/railpack.md create mode 100755 plugins/builder-railpack/builder-build create mode 100755 plugins/builder-railpack/builder-detect create mode 100755 plugins/builder-railpack/builder-release create mode 100755 plugins/builder-railpack/commands create mode 100755 plugins/builder-railpack/core-post-extract create mode 100644 plugins/builder-railpack/dockerfiles/builder-build.Dockerfile create mode 100644 plugins/builder-railpack/dockerfiles/builder-release.Dockerfile create mode 100755 plugins/builder-railpack/help-functions create mode 100755 plugins/builder-railpack/install create mode 100755 plugins/builder-railpack/internal-functions create mode 100644 plugins/builder-railpack/plugin.toml create mode 100755 plugins/builder-railpack/post-app-clone-setup create mode 100755 plugins/builder-railpack/post-app-rename-setup create mode 100755 plugins/builder-railpack/post-delete create mode 100755 plugins/builder-railpack/report create mode 100755 plugins/builder-railpack/subcommands/default create mode 100755 plugins/builder-railpack/subcommands/report create mode 100755 plugins/builder-railpack/subcommands/set create mode 100644 tests/unit/builder-railpack.bats diff --git a/Dockerfile b/Dockerfile index f598c5230..f0b5b79a8 100644 --- a/Dockerfile +++ b/Dockerfile @@ -33,6 +33,11 @@ RUN mkdir -p /etc/apt/keyrings \ && NIXPACKS_BIN_DIR=/usr/bin BIN_DIR=/usr/bin /tmp/nixpacks.bash \ && test -x /usr/bin/nixpacks \ && rm -rf /tmp/nixpacks.bash \ + && curl -o /tmp/railpack.bash -sSL https://railpack.com/install.sh \ + && chmod +x /tmp/railpack.bash \ + && RAILPACK_BIN_DIR=/usr/bin /tmp/railpack.bash \ + && test -x /usr/bin/railpack \ + && rm -rf /tmp/railpack.bash \ && echo "dokku dokku/hostname string $DOKKU_HOSTNAME" | debconf-set-selections \ && echo "dokku dokku/skip_key_file boolean $DOKKU_SKIP_KEY_FILE" | debconf-set-selections \ && echo "dokku dokku/vhost_enable boolean $DOKKU_VHOST_ENABLE" | debconf-set-selections \ diff --git a/docker/etc/sudoers.d/dokku-docker b/docker/etc/sudoers.d/dokku-docker index bebd88538..f3dc76faa 100644 --- a/docker/etc/sudoers.d/dokku-docker +++ b/docker/etc/sudoers.d/dokku-docker @@ -1 +1 @@ -dokku ALL=NOPASSWD:SETENV:/usr/bin/docker,/usr/bin/docker-container-healthchecker,/usr/bin/docker-image-labeler,/usr/bin/lambda-builder,/usr/bin/nixpacks,/usr/bin/pack +dokku ALL=NOPASSWD:SETENV:/usr/bin/docker,/usr/bin/docker-container-healthchecker,/usr/bin/docker-image-labeler,/usr/bin/lambda-builder,/usr/bin/nixpacks,/usr/bin/railpack,/usr/bin/pack diff --git a/docker/usr/local/bin/railpack b/docker/usr/local/bin/railpack new file mode 100644 index 000000000..35bee71d2 --- /dev/null +++ b/docker/usr/local/bin/railpack @@ -0,0 +1,20 @@ +#!/usr/bin/env bash +set -eo pipefail +[[ $TRACE ]] && set -x + +main() { + declare desc="re-runs railpack commands as sudo" + local RAILPACK_BIN="" + if [[ -x "/usr/bin/railpack" ]]; then + RAILPACK_BIN="/usr/bin/railpack" + fi + + if [[ -z "$RAILPACK_BIN" ]]; then + echo "! No railpack binary found" 1>&2 + exit 1 + fi + + sudo -E "$RAILPACK_BIN" "$@" +} + +main "$@" diff --git a/docs/appendices/file-formats/railpack-json.md b/docs/appendices/file-formats/railpack-json.md new file mode 100644 index 000000000..d6e390fb4 --- /dev/null +++ b/docs/appendices/file-formats/railpack-json.md @@ -0,0 +1,3 @@ +# railpack.json + +The `railpack.json` file is used to configure an application when built with the `railpack` builder. Please refer to the [railpack.json documentation](https://railpack.com/config/file) for more information. diff --git a/docs/deployment/builders/railpack.md b/docs/deployment/builders/railpack.md new file mode 100644 index 000000000..3483c7d72 --- /dev/null +++ b/docs/deployment/builders/railpack.md @@ -0,0 +1,163 @@ +# Railpack + +> [!IMPORTANT] +> New as of 0.32.0 + +The `railpack` builder builds apps via [Railpack](https://railpack.com/), a buildpack alternative. + +## Usage + +### Requirements + +The `railpack` cli tool is not included by default with Dokku or as a dependency. It must also be installed as shown on [this page](https://railpack.com/installation). + +Builds will proceed with the `railpack` cli for the app from then on. + +### Detection + +This builder will be auto-detected in the following case: + +- A `railpack.json` exists in the root of the app repository. + +The builder may also be selected via the `builder:set` command + +```shell +dokku builder:set node-js-app selected railpack +``` + +### Supported languages + +See the [upstream railpack documentation](https://railpack.com/) for further information on what languages and frameworks are supported. + +### Build-time configuration variables + +For security reasons - and as per [Docker recommendations](https://github.com/docker/docker/issues/13490) - railpack-based deploys have variables available only during runtime. + +For users that require customization in the `build` phase, you may use build arguments via the [docker-options plugin](/docs/advanced-usage/docker-options.md). All environment variables set by the `config` plugin are automatically exported within the railpack build environment, and thus `--env` only requires setting a key without a value. + +```shell +dokku docker-options:add node-js-app build '--env NODE_ENV' +``` + +Alternatively, a full value may be provided in the form of `--env KEY=VALUE`: + +```shell +dokku docker-options:add node-js-app build '--env NODE_ENV=production' +``` + +### Changing the `railpack.json` location + +The `railpack.json` is expected to be found in a specific directory, depending on the deploy approach: + +- The `WORKDIR` of the Docker image for deploys resulting from `git:from-image` and `git:load-image` commands. +- The root of the source code tree for all other deploys (git push, `git:from-archive`, `git:sync`). + +Sometimes it may be desirable to set a different path for a given app, e.g. when deploying from a monorepo. This can be done via the `railpackjson-path` property: + +```shell +dokku builder-railpack:set node-js-app railpackjson-path .dokku/railpack.json +``` + +The value is the path to the desired file *relative* to the base search directory, and will never be treated as absolute paths in any context. If that file does not exist within the repository, the build will fail. + +The default value may be set by passing an empty value for the option: + +```shell +dokku builder-railpack:set node-js-app railpackjson-path +``` + +The `railpackjson-path` property can also be set globally. The global default is `railpack.json`, and the global value is used when no app-specific value is set. + +```shell +dokku builder-railpack:set --global railpackjson-path railpack2.json +``` + +The default value may be set by passing an empty value for the option. + +```shell +dokku builder-railpack:set --global railpackjson-path +``` + +### Disabling cache + +Cache is enabled by default, but can be disabled by setting the `no-cache` property to `true`: + +```shell +dokku builder-railpack:set node-js-app no-cache true +``` + +The default value may be set by passing an empty value for the option: + +```shell +dokku builder-railpack:set node-js-app no-cache +``` + +The `no-cache` property can also be set globally. The global default is `false`, and the global value is used when no app-specific value is set. + +```shell +dokku builder-railpack:set --global no-cache true +``` + +The default value may be set by passing an empty value for the option. + +```shell +dokku builder-railpack:set --global no-cache +``` + +### Displaying builder-railpack reports for an app + +You can get a report about the app's storage status using the `builder-railpack:report` command: + +```shell +dokku builder-railpack:report +``` + +``` +=====> node-js-app builder-railpack information + Builder-railpack computed railpackjson path: railpack2.json + Builder-railpack global railpackjson path: railpack.json + Builder-railpack railpackjson path: railpack2.json + Builder-railpack computed no cache: true + Builder-railpack global no cache: false + Builder-railpack no cache: true +=====> python-sample builder-railpack information + Builder-railpack computed railpackjson path: railpack.json + Builder-railpack global railpackjson path: railpack.json + Builder-railpack railpackjson path: + Builder-railpack computed no cache: false + Builder-railpack global no cache: false + Builder-railpack no cache: +=====> ruby-sample builder-railpack information + Builder-railpack computed railpackjson path: railpack.json + Builder-railpack global railpackjson path: railpack.json + Builder-railpack railpackjson path: + Builder-railpack computed no cache: false + Builder-railpack global no cache: false + Builder-railpack no cache: +``` + +You can run the command for a specific app also. + +```shell +dokku builder-railpack:report node-js-app +``` + +``` +=====> node-js-app builder-railpack information + Builder-railpack computed railpackjson path: railpack2.json + Builder-railpack global railpackjson path: railpack.json + Builder-railpack railpackjson path: railpack2.json + Builder-railpack computed no cache: true + Builder-railpack global no cache: false + Builder-railpack no cache: true +``` + +You can pass flags which will output only the value of the specific information you want. For example: + +```shell +dokku builder-railpack:report node-js-app --builder-railpack-no-cache +``` + +``` +true +``` diff --git a/docs/template.html b/docs/template.html index d81802c40..9e26b3759 100644 --- a/docs/template.html +++ b/docs/template.html @@ -150,6 +150,7 @@ Lambda Builder Nixpacks Builder Null Builder + Railpack Builder Deployment Methods Git Deployment diff --git a/plugins/builder-railpack/builder-build b/plugins/builder-railpack/builder-build new file mode 100755 index 000000000..c1664fcac --- /dev/null +++ b/plugins/builder-railpack/builder-build @@ -0,0 +1,67 @@ +#!/usr/bin/env bash +source "$PLUGIN_CORE_AVAILABLE_PATH/common/functions" +source "$PLUGIN_AVAILABLE_PATH/builder-railpack/internal-functions" +source "$PLUGIN_AVAILABLE_PATH/config/functions" +set -eo pipefail +[[ $DOKKU_TRACE ]] && set -x + +trigger-builder-railpack-builder-build() { + declare desc="builder-railpack builder-build plugin trigger" + declare trigger="builder-build" + declare BUILDER_TYPE="$1" APP="$2" SOURCECODE_WORK_DIR="$3" + + if [[ "$BUILDER_TYPE" != "railpack" ]]; then + return + fi + + dokku_log_info1 "Building $APP from railpack" + + if ! command -v "railpack" &>/dev/null; then + dokku_log_fail "Missing railpack, install it" + fi + + local IMAGE=$(get_app_image_name "$APP") + local DOCKER_BUILD_LABEL_ARGS=("--label=dokku" "--label=org.label-schema.schema-version=1.0" "--label=org.label-schema.vendor=dokku" "--label=com.dokku.image-stage=build" "--label=com.dokku.builder-type=railpack" "--label=com.dokku.app-name=$APP") + + pushd "$SOURCECODE_WORK_DIR" &>/dev/null + + plugn trigger pre-build "$BUILDER_TYPE" "$APP" "$SOURCECODE_WORK_DIR" + + no_cache="$(fn-builder-railpack-computed-no-cache "$APP")" + RAILPACK_ARGS="" + if [[ "$no_cache" == "true" ]]; then + RAILPACK_ARGS="$RAILPACK_ARGS --no-cache" + fi + + local DOCKER_ARGS=$(: | plugn trigger docker-args-build "$APP" "$BUILDER_TYPE") + DOCKER_ARGS+=$(: | plugn trigger docker-args-process-build "$APP" "$BUILDER_TYPE") + + # strip --link, --volume and -v args from DOCKER_ARGS + local DOCKER_ARGS=$(sed -e "s/^--link=[[:graph:]]\+[[:blank:]]\?//g" -e "s/^--link[[:blank:]]\?[[:graph:]]\+[[:blank:]]\?//g" -e "s/^--volume=[[:graph:]]\+[[:blank:]]\?//g" -e "s/^--volume[[:blank:]]\?[[:graph:]]\+[[:blank:]]\?//g" -e "s/^-v[[:blank:]]\?[[:graph:]]\+[[:blank:]]\?//g" <<<"$DOCKER_ARGS") + declare -a ARG_ARRAY + eval "ARG_ARRAY=($DOCKER_ARGS)" + + eval "$(config_export app "$APP" --merged)" + + if [[ -f "$SOURCECODE_WORK_DIR/Procfile" ]]; then + if procfile-util exists --process-type release; then + procfile-util delete --process-type release + fi + fi + + # shellcheck disable=SC2086 + if ! railpack build "${DOCKER_BUILD_LABEL_ARGS[@]}" $DOKKU_GLOBAL_BUILD_ARGS "${ARG_ARRAY[@]}" $RAILPACK_ARGS --name "$IMAGE" "$SOURCECODE_WORK_DIR"; then + dokku_log_warn "Failure building image" + return 1 + fi + + if ! suppress_output "$DOCKER_BIN" image build -f "$PLUGIN_AVAILABLE_PATH/builder-railpack/dockerfiles/builder-build.Dockerfile" --build-arg APP_IMAGE="$IMAGE" -t "$IMAGE" "$SOURCECODE_WORK_DIR"; then + dokku_log_warn "Failure injecting docker labels and custom entrypoint on image" + return 1 + fi + + plugn trigger post-build "$BUILDER_TYPE" "$APP" "$SOURCECODE_WORK_DIR" + popd &>/dev/null || pushd "/tmp" >/dev/null +} + +trigger-builder-railpack-builder-build "$@" diff --git a/plugins/builder-railpack/builder-detect b/plugins/builder-railpack/builder-detect new file mode 100755 index 000000000..1ba0b89ba --- /dev/null +++ b/plugins/builder-railpack/builder-detect @@ -0,0 +1,17 @@ +#!/usr/bin/env bash +source "$PLUGIN_AVAILABLE_PATH/config/functions" +set -eo pipefail +[[ $DOKKU_TRACE ]] && set -x + +trigger-builder-railpack-builder-detect() { + declare desc="builder-railpack builder-detect plugin trigger" + declare trigger="builder-detect" + declare APP="$1" SOURCECODE_WORK_DIR="$2" + + if [[ -f "$SOURCECODE_WORK_DIR/railpack.json" ]]; then + echo "railpack" + return + fi +} + +trigger-builder-railpack-builder-detect "$@" diff --git a/plugins/builder-railpack/builder-release b/plugins/builder-railpack/builder-release new file mode 100755 index 000000000..7c3650421 --- /dev/null +++ b/plugins/builder-railpack/builder-release @@ -0,0 +1,30 @@ +#!/usr/bin/env bash +source "$PLUGIN_CORE_AVAILABLE_PATH/common/functions" +set -eo pipefail +[[ $DOKKU_TRACE ]] && set -x + +trigger-builder-railpack-builder-release() { + declare desc="builder-railpack builder-release plugin trigger" + declare trigger="builder-release" + declare BUILDER_TYPE="$1" APP="$2" IMAGE_TAG="$3" + + if [[ "$BUILDER_TYPE" != "railpack" ]]; then + return + fi + + local IMAGE=$(get_app_image_name "$APP" "$IMAGE_TAG") + plugn trigger pre-release-builder "$BUILDER_TYPE" "$APP" "$IMAGE" + + TMP_WORK_DIR="$(mktemp -d "/tmp/dokku-${DOKKU_PID}-${FUNCNAME[0]}.XXXXXX")" + trap "rm -rf '$TMP_WORK_DIR' >/dev/null" RETURN INT TERM EXIT + + local DOCKER_BUILD_LABEL_ARGS="--label=org.label-schema.schema-version=1.0 --label=org.label-schema.vendor=dokku --label=com.dokku.app-name=$APP --label=com.dokku.image-stage=release --label=dokku" + if ! suppress_output "$DOCKER_BIN" image build "${DOCKER_BUILD_LABEL_ARGS[@]}" $DOKKU_GLOBAL_BUILD_ARGS -f "$PLUGIN_AVAILABLE_PATH/builder-railpack/dockerfiles/builder-release.Dockerfile" --build-arg APP_IMAGE="$IMAGE" -t "$IMAGE" "$TMP_WORK_DIR"; then + dokku_log_warn "Failure injecting docker labels on image" + return 1 + fi + + plugn trigger post-release-builder "$BUILDER_TYPE" "$APP" "$IMAGE" +} + +trigger-builder-railpack-builder-release "$@" diff --git a/plugins/builder-railpack/commands b/plugins/builder-railpack/commands new file mode 100755 index 000000000..db753d311 --- /dev/null +++ b/plugins/builder-railpack/commands @@ -0,0 +1,15 @@ +#!/usr/bin/env bash +set -eo pipefail +[[ $DOKKU_TRACE ]] && set -x +source "$PLUGIN_AVAILABLE_PATH/builder-railpack/help-functions" + +case "$1" in + help | builder-railpack:help) + cmd-builder-railpack-help "$@" + ;; + + *) + exit "$DOKKU_NOT_IMPLEMENTED_EXIT" + ;; + +esac diff --git a/plugins/builder-railpack/core-post-extract b/plugins/builder-railpack/core-post-extract new file mode 100755 index 000000000..ad863c076 --- /dev/null +++ b/plugins/builder-railpack/core-post-extract @@ -0,0 +1,30 @@ +#!/usr/bin/env bash +source "$PLUGIN_CORE_AVAILABLE_PATH/common/functions" +source "$PLUGIN_AVAILABLE_PATH/builder-railpack/internal-functions" +set -eo pipefail +[[ $DOKKU_TRACE ]] && set -x + +trigger-builder-railpack-core-post-extract() { + declare desc="builder-railpack post-extract plugin trigger" + declare trigger="post-extract" + declare APP="$1" SOURCECODE_WORK_DIR="$2" + local NEW_RAILPACK_JSON="$(fn-builder-railpack-computed-railpackjson-path "$APP")" + + pushd "$TMP_WORK_DIR" >/dev/null + + if [[ -z "$NEW_RAILPACK_JSON" ]]; then + return + fi + + if [[ ! -f "$NEW_RAILPACK_JSON" ]]; then + rm -f railpack.json + return + fi + + if [[ "$NEW_RAILPACK_JSON" != "railpack.json" ]]; then + mv "$NEW_RAILPACK_JSON" railpack.json + fi + popd &>/dev/null || pushd "/tmp" >/dev/null +} + +trigger-builder-railpack-core-post-extract "$@" diff --git a/plugins/builder-railpack/dockerfiles/builder-build.Dockerfile b/plugins/builder-railpack/dockerfiles/builder-build.Dockerfile new file mode 100644 index 000000000..57aa80d1c --- /dev/null +++ b/plugins/builder-railpack/dockerfiles/builder-build.Dockerfile @@ -0,0 +1,7 @@ +ARG APP_IMAGE +FROM $APP_IMAGE + +RUN printf '#!/usr/bin/env bash\nexec bash -l -c -- \"$*\"\n' > /usr/local/bin/entrypoint && \ + chmod +x /usr/local/bin/entrypoint + +ENTRYPOINT ["/usr/local/bin/entrypoint"] diff --git a/plugins/builder-railpack/dockerfiles/builder-release.Dockerfile b/plugins/builder-railpack/dockerfiles/builder-release.Dockerfile new file mode 100644 index 000000000..cca256f21 --- /dev/null +++ b/plugins/builder-railpack/dockerfiles/builder-release.Dockerfile @@ -0,0 +1,2 @@ +ARG APP_IMAGE +FROM $APP_IMAGE diff --git a/plugins/builder-railpack/help-functions b/plugins/builder-railpack/help-functions new file mode 100755 index 000000000..ef1811401 --- /dev/null +++ b/plugins/builder-railpack/help-functions @@ -0,0 +1,33 @@ +#!/usr/bin/env bash +set -eo pipefail +[[ $DOKKU_TRACE ]] && set -x + +cmd-builder-railpack-help() { + declare desc="help command" + declare CMD="$1" + local plugin_name="builder-railpack" + local plugin_description="Manage the railpack builder integration for an app" + + if [[ "$CMD" == "${plugin_name}:help" ]]; then + echo -e "Usage: dokku ${plugin_name}[:COMMAND]" + echo '' + echo "$plugin_description" + echo '' + echo 'Additional commands:' + fn-help-content | sort | column -c2 -t -s, + elif [[ $(ps -o command= $PPID) == *"--all"* ]]; then + fn-help-content + else + cat <] [], Displays a builder-railpack report for one or more apps + builder-railpack:set (), Set or clear a builder-railpack property for an app +help_content +} diff --git a/plugins/builder-railpack/install b/plugins/builder-railpack/install new file mode 100755 index 000000000..283188a33 --- /dev/null +++ b/plugins/builder-railpack/install @@ -0,0 +1,16 @@ +#!/usr/bin/env bash +source "$PLUGIN_CORE_AVAILABLE_PATH/common/property-functions" +set -eo pipefail +[[ $DOKKU_TRACE ]] && set -x + +trigger-builder-railpack-install() { + declare desc="installs the builder-railpack plugin" + declare trigger="install" + + fn-plugin-property-setup "builder-railpack" + + mkdir -p "${DOKKU_LIB_ROOT}/data/builder-railpack" + chown -R "${DOKKU_SYSTEM_USER}:${DOKKU_SYSTEM_GROUP}" "${DOKKU_LIB_ROOT}/data/builder-railpack" +} + +trigger-builder-railpack-install "$@" diff --git a/plugins/builder-railpack/internal-functions b/plugins/builder-railpack/internal-functions new file mode 100755 index 000000000..a405b2ed0 --- /dev/null +++ b/plugins/builder-railpack/internal-functions @@ -0,0 +1,116 @@ +#!/usr/bin/env bash +source "$PLUGIN_CORE_AVAILABLE_PATH/common/functions" +source "$PLUGIN_CORE_AVAILABLE_PATH/common/property-functions" +set -eo pipefail +[[ $DOKKU_TRACE ]] && set -x + +cmd-builder-railpack-report() { + declare desc="displays a builder-railpack report for one or more apps" + declare cmd="builder-railpack:report" + [[ "$1" == "$cmd" ]] && shift 1 + declare APP="$1" INFO_FLAG="$2" + + if [[ -n "$APP" ]] && [[ "$APP" == --* ]]; then + INFO_FLAG="$APP" + APP="" + fi + + if [[ -z "$APP" ]] && [[ -z "$INFO_FLAG" ]]; then + INFO_FLAG="true" + fi + + if [[ -z "$APP" ]]; then + for app in $(dokku_apps); do + cmd-builder-railpack-report-single "$app" "$INFO_FLAG" | tee || true + done + else + cmd-builder-railpack-report-single "$APP" "$INFO_FLAG" + fi +} + +cmd-builder-railpack-report-single() { + declare APP="$1" INFO_FLAG="$2" + if [[ "$INFO_FLAG" == "true" ]]; then + INFO_FLAG="" + fi + verify_app_name "$APP" + local flag_map=( + "--builder-railpack-computed-railpackjson-path: $(fn-builder-railpack-computed-railpackjson-path "$APP")" + "--builder-railpack-global-railpackjson-path: $(fn-builder-railpack-global-railpackjson-path "$APP")" + "--builder-railpack-railpackjson-path: $(fn-builder-railpack-railpackjson-path "$APP")" + "--builder-railpack-computed-no-cache: $(fn-builder-railpack-computed-no-cache "$APP")" + "--builder-railpack-global-no-cache: $(fn-builder-railpack-global-no-cache "$APP")" + "--builder-railpack-no-cache: $(fn-builder-railpack-no-cache "$APP")" + ) + + if [[ -z "$INFO_FLAG" ]]; then + dokku_log_info2_quiet "${APP} builder-railpack information" + for flag in "${flag_map[@]}"; do + key="$(echo "${flag#--}" | cut -f1 -d' ' | tr - ' ')" + dokku_log_verbose "$(printf "%-30s %-25s" "${key^}" "${flag#*: }")" + done + else + local match=false + local value_exists=false + for flag in "${flag_map[@]}"; do + valid_flags="${valid_flags} $(echo "$flag" | cut -d':' -f1)" + if [[ "$flag" == "${INFO_FLAG}:"* ]]; then + value=${flag#*: } + size="${#value}" + if [[ "$size" -ne 0 ]]; then + echo "$value" && match=true && value_exists=true + else + match=true + fi + fi + done + [[ "$match" == "true" ]] || dokku_log_fail "Invalid flag passed, valid flags:${valid_flags}" + [[ "$value_exists" == "true" ]] || dokku_log_fail "not deployed" + fi +} + +fn-builder-railpack-computed-railpackjson-path() { + declare APP="$1" + + file="$(fn-builder-railpack-railpackjson-path "$APP")" + if [[ "$file" == "" ]]; then + file="$(fn-builder-railpack-global-railpackjson-path "$APP")" + fi + + echo "$file" +} + +fn-builder-railpack-global-railpackjson-path() { + declare APP="$1" + + fn-plugin-property-get "builder-railpack" "--global" "railpackjson-path" "railpack.json" +} + +fn-builder-railpack-railpackjson-path() { + declare APP="$1" + + fn-plugin-property-get "builder-railpack" "$APP" "railpackjson-path" "" +} + +fn-builder-railpack-computed-no-cache() { + declare APP="$1" + + file="$(fn-builder-railpack-no-cache "$APP")" + if [[ "$file" == "" ]]; then + file="$(fn-builder-railpack-global-no-cache "$APP")" + fi + + echo "$file" +} + +fn-builder-railpack-global-no-cache() { + declare APP="$1" + + fn-plugin-property-get "builder-railpack" "--global" "no-cache" "false" +} + +fn-builder-railpack-no-cache() { + declare APP="$1" + + fn-plugin-property-get "builder-railpack" "$APP" "no-cache" "" +} diff --git a/plugins/builder-railpack/plugin.toml b/plugins/builder-railpack/plugin.toml new file mode 100644 index 000000000..d7eceec7d --- /dev/null +++ b/plugins/builder-railpack/plugin.toml @@ -0,0 +1,4 @@ +[plugin] +description = "dokku core builder-railpack plugin" +version = "0.36.5" +[plugin.config] diff --git a/plugins/builder-railpack/post-app-clone-setup b/plugins/builder-railpack/post-app-clone-setup new file mode 100755 index 000000000..0ff83fc92 --- /dev/null +++ b/plugins/builder-railpack/post-app-clone-setup @@ -0,0 +1,14 @@ +#!/usr/bin/env bash +source "$PLUGIN_CORE_AVAILABLE_PATH/common/property-functions" +set -eo pipefail +[[ $DOKKU_TRACE ]] && set -x + +trigger-builder-railpack-post-app-clone-setup() { + declare desc="sets up properties for new app" + declare trigger="post-app-clone-setup" + declare OLD_APP="$1" NEW_APP="$2" + + fn-plugin-property-clone "builder-railpack" "$OLD_APP" "$NEW_APP" +} + +trigger-builder-railpack-post-app-clone-setup "$@" diff --git a/plugins/builder-railpack/post-app-rename-setup b/plugins/builder-railpack/post-app-rename-setup new file mode 100755 index 000000000..10effd4e5 --- /dev/null +++ b/plugins/builder-railpack/post-app-rename-setup @@ -0,0 +1,15 @@ +#!/usr/bin/env bash +source "$PLUGIN_CORE_AVAILABLE_PATH/common/property-functions" +set -eo pipefail +[[ $DOKKU_TRACE ]] && set -x + +trigger-builder-railpack-post-app-rename-setup() { + declare desc="updates settings for new app" + declare trigger="post-app-rename-setup" + declare OLD_APP="$1" NEW_APP="$2" + + fn-plugin-property-clone "builder-railpack" "$OLD_APP" "$NEW_APP" + fn-plugin-property-destroy "builder-railpack" "$OLD_APP" +} + +trigger-builder-railpack-post-app-rename-setup "$@" diff --git a/plugins/builder-railpack/post-delete b/plugins/builder-railpack/post-delete new file mode 100755 index 000000000..5879fc046 --- /dev/null +++ b/plugins/builder-railpack/post-delete @@ -0,0 +1,15 @@ +#!/usr/bin/env bash +source "$PLUGIN_CORE_AVAILABLE_PATH/common/property-functions" +set -eo pipefail +[[ $DOKKU_TRACE ]] && set -x + +trigger-builder-railpack-post-delete() { + declare desc="destroys the builder-railpack properties for a given app" + declare trigger="post-delete" + declare APP="$1" + + fn-plugin-property-destroy "builder-railpack" "$APP" + rm -rf "${DOKKU_LIB_ROOT}/data/builder-railpack/$APP" +} + +trigger-builder-railpack-post-delete "$@" diff --git a/plugins/builder-railpack/report b/plugins/builder-railpack/report new file mode 100755 index 000000000..6fbd0d855 --- /dev/null +++ b/plugins/builder-railpack/report @@ -0,0 +1,6 @@ +#!/usr/bin/env bash +source "$PLUGIN_AVAILABLE_PATH/builder-railpack/internal-functions" +set -eo pipefail +[[ $DOKKU_TRACE ]] && set -x + +cmd-builder-railpack-report-single "$@" diff --git a/plugins/builder-railpack/subcommands/default b/plugins/builder-railpack/subcommands/default new file mode 100755 index 000000000..cc0e6748a --- /dev/null +++ b/plugins/builder-railpack/subcommands/default @@ -0,0 +1,6 @@ +#!/usr/bin/env bash +source "$PLUGIN_AVAILABLE_PATH/builder-railpack/help-functions" +set -eo pipefail +[[ $DOKKU_TRACE ]] && set -x + +cmd-builder-railpack-help "builder-railpack:help" diff --git a/plugins/builder-railpack/subcommands/report b/plugins/builder-railpack/subcommands/report new file mode 100755 index 000000000..9801d5f29 --- /dev/null +++ b/plugins/builder-railpack/subcommands/report @@ -0,0 +1,6 @@ +#!/usr/bin/env bash +source "$PLUGIN_AVAILABLE_PATH/builder-railpack/internal-functions" +set -eo pipefail +[[ $DOKKU_TRACE ]] && set -x + +cmd-builder-railpack-report "$@" diff --git a/plugins/builder-railpack/subcommands/set b/plugins/builder-railpack/subcommands/set new file mode 100755 index 000000000..6001f0c6f --- /dev/null +++ b/plugins/builder-railpack/subcommands/set @@ -0,0 +1,30 @@ +#!/usr/bin/env bash +source "$PLUGIN_CORE_AVAILABLE_PATH/common/functions" +source "$PLUGIN_CORE_AVAILABLE_PATH/common/property-functions" +set -eo pipefail +[[ $DOKKU_TRACE ]] && set -x + +cmd-builder-railpack-set() { + declare desc="set or clear a builder-railpack property for an app" + declare cmd="builder-railpack:set" + [[ "$1" == "$cmd" ]] && shift 1 + declare APP="$1" KEY="$2" VALUE="$3" + local VALID_KEYS=("railpackjson-path" "no-cache") + [[ "$APP" == "--global" ]] || verify_app_name "$APP" + + [[ -z "$KEY" ]] && dokku_log_fail "No key specified" + + if ! fn-in-array "$KEY" "${VALID_KEYS[@]}"; then + dokku_log_fail "Invalid key specified, valid keys include: railpackjson-path, no-cache" + fi + + if [[ -n "$VALUE" ]]; then + dokku_log_info2_quiet "Setting ${KEY} to ${VALUE}" + fn-plugin-property-write "builder-railpack" "$APP" "$KEY" "$VALUE" + else + dokku_log_info2_quiet "Unsetting ${KEY}" + fn-plugin-property-delete "builder-railpack" "$APP" "$KEY" + fi +} + +cmd-builder-railpack-set "$@" diff --git a/plugins/docker-options/docker-args-deploy b/plugins/docker-options/docker-args-deploy index fc768a0cf..35ea4bc97 100755 --- a/plugins/docker-options/docker-args-deploy +++ b/plugins/docker-options/docker-args-deploy @@ -47,7 +47,7 @@ trigger-docker-options-docker-args() { *) case "$IMAGE_SOURCE_TYPE" in - dockerfile | nixpacks) + dockerfile | nixpacks | railpack) case "$line" in --link* | -v* | --volume*) continue diff --git a/tests/unit/builder-railpack.bats b/tests/unit/builder-railpack.bats new file mode 100644 index 000000000..017123f0c --- /dev/null +++ b/tests/unit/builder-railpack.bats @@ -0,0 +1,52 @@ +#!/usr/bin/env bats + +load test_helper + +setup_file() { + install_railpack +} + +setup() { + create_app +} + +teardown() { + destroy_app +} + +@test "(builder-railpack:set)" { + run /bin/bash -c "dokku config:set $TEST_APP SECRET_KEY=fjdkslafjdk" + echo "output: $output" + echo "status: $status" + assert_success + + run /bin/bash -c "dokku builder:set $TEST_APP selected railpack" + echo "output: $output" + echo "status: $status" + assert_success + + run deploy_app python dokku@$DOKKU_DOMAIN:$TEST_APP inject_requirements_txt + echo "output: $output" + echo "status: $status" + assert_success + assert_output_contains 'load build definition from Dockerfile' + assert_output_contains "SECRET_KEY: fjdkslafjdk" + + run /bin/bash -c "dokku builder-railpack:set $TEST_APP railpackjson-path nonexistent.json" + echo "output: $output" + echo "status: $status" + assert_success + + run /bin/bash -c "dokku ps:rebuild $TEST_APP" + echo "output: $output" + echo "status: $status" + assert_success + assert_output_contains 'load build definition from Dockerfile' +} + +inject_requirements_txt() { + local APP="$1" + local APP_REPO_DIR="$2" + [[ -z "$APP" ]] && local APP="$TEST_APP" + echo "flask" >>"$APP_REPO_DIR/requirements.txt" +} diff --git a/tests/unit/report.bats b/tests/unit/report.bats index a5f7271b6..719af8c80 100644 --- a/tests/unit/report.bats +++ b/tests/unit/report.bats @@ -103,6 +103,7 @@ teardown() { builder-herokuish builder-lambda builder-nixpacks + builder-railpack builder-pack buildpacks caddy diff --git a/tests/unit/test_helper.bash b/tests/unit/test_helper.bash index 34ce53bcb..c53880f24 100644 --- a/tests/unit/test_helper.bash +++ b/tests/unit/test_helper.bash @@ -660,6 +660,12 @@ install_nixpacks() { fi } +install_railpack() { + if ! command -v "railpack" &>/dev/null; then + curl -sSL https://railpack.com/install.sh | FORCE=1 bash + fi +} + install_k3s() { run /bin/bash -c "dokku proxy:set --global k3s" echo "output: $output" From ee467e679357f0c6474d41e15d2fccd062bf92df Mon Sep 17 00:00:00 2001 From: Jose Diaz-Gonzalez Date: Sun, 14 Sep 2025 21:11:59 -0400 Subject: [PATCH 02/15] fix: inject labels after the image is built by railpack Railpack doesn't support the --label flag. --- plugins/builder-railpack/builder-build | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/builder-railpack/builder-build b/plugins/builder-railpack/builder-build index c1664fcac..52bffedd4 100755 --- a/plugins/builder-railpack/builder-build +++ b/plugins/builder-railpack/builder-build @@ -50,12 +50,12 @@ trigger-builder-railpack-builder-build() { fi # shellcheck disable=SC2086 - if ! railpack build "${DOCKER_BUILD_LABEL_ARGS[@]}" $DOKKU_GLOBAL_BUILD_ARGS "${ARG_ARRAY[@]}" $RAILPACK_ARGS --name "$IMAGE" "$SOURCECODE_WORK_DIR"; then + if ! railpack build "${ARG_ARRAY[@]}" $RAILPACK_ARGS --name "$IMAGE" "$SOURCECODE_WORK_DIR"; then dokku_log_warn "Failure building image" return 1 fi - if ! suppress_output "$DOCKER_BIN" image build -f "$PLUGIN_AVAILABLE_PATH/builder-railpack/dockerfiles/builder-build.Dockerfile" --build-arg APP_IMAGE="$IMAGE" -t "$IMAGE" "$SOURCECODE_WORK_DIR"; then + if ! suppress_output "$DOCKER_BIN" image build -f "$PLUGIN_AVAILABLE_PATH/builder-railpack/dockerfiles/builder-build.Dockerfile" --build-arg APP_IMAGE="$IMAGE" "${DOCKER_BUILD_LABEL_ARGS[@]}" $DOKKU_GLOBAL_BUILD_ARGS -t "$IMAGE" "$SOURCECODE_WORK_DIR"; then dokku_log_warn "Failure injecting docker labels and custom entrypoint on image" return 1 fi From 9f334592661eb269b2b43ebbf8d0aac848abe3ca Mon Sep 17 00:00:00 2001 From: Jose Diaz-Gonzalez Date: Sun, 14 Sep 2025 21:43:33 -0400 Subject: [PATCH 03/15] fix: set BIN_DIR --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index f0b5b79a8..dead75810 100644 --- a/Dockerfile +++ b/Dockerfile @@ -35,7 +35,7 @@ RUN mkdir -p /etc/apt/keyrings \ && rm -rf /tmp/nixpacks.bash \ && curl -o /tmp/railpack.bash -sSL https://railpack.com/install.sh \ && chmod +x /tmp/railpack.bash \ - && RAILPACK_BIN_DIR=/usr/bin /tmp/railpack.bash \ + && RAILPACK_BIN_DIR=/usr/bin BIN_DIR=/usr/bin /tmp/railpack.bash \ && test -x /usr/bin/railpack \ && rm -rf /tmp/railpack.bash \ && echo "dokku dokku/hostname string $DOKKU_HOSTNAME" | debconf-set-selections \ From 6b27f424db4784643816727cbb68e6c1b6c57b00 Mon Sep 17 00:00:00 2001 From: Jose Diaz-Gonzalez Date: Sun, 14 Sep 2025 21:43:39 -0400 Subject: [PATCH 04/15] fix: remove extra space --- plugins/builder-railpack/builder-build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/builder-railpack/builder-build b/plugins/builder-railpack/builder-build index 52bffedd4..b64dce3a6 100755 --- a/plugins/builder-railpack/builder-build +++ b/plugins/builder-railpack/builder-build @@ -55,7 +55,7 @@ trigger-builder-railpack-builder-build() { return 1 fi - if ! suppress_output "$DOCKER_BIN" image build -f "$PLUGIN_AVAILABLE_PATH/builder-railpack/dockerfiles/builder-build.Dockerfile" --build-arg APP_IMAGE="$IMAGE" "${DOCKER_BUILD_LABEL_ARGS[@]}" $DOKKU_GLOBAL_BUILD_ARGS -t "$IMAGE" "$SOURCECODE_WORK_DIR"; then + if ! suppress_output "$DOCKER_BIN" image build -f "$PLUGIN_AVAILABLE_PATH/builder-railpack/dockerfiles/builder-build.Dockerfile" --build-arg APP_IMAGE="$IMAGE" "${DOCKER_BUILD_LABEL_ARGS[@]}" $DOKKU_GLOBAL_BUILD_ARGS -t "$IMAGE" "$SOURCECODE_WORK_DIR"; then dokku_log_warn "Failure injecting docker labels and custom entrypoint on image" return 1 fi From 300a276ed0d43aa1e72059b2c156c4ecd221c718 Mon Sep 17 00:00:00 2001 From: Jose Diaz-Gonzalez Date: Sun, 14 Sep 2025 21:44:19 -0400 Subject: [PATCH 05/15] chore: bump version in plugin.toml --- plugins/builder-railpack/plugin.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/builder-railpack/plugin.toml b/plugins/builder-railpack/plugin.toml index d7eceec7d..6fa72020b 100644 --- a/plugins/builder-railpack/plugin.toml +++ b/plugins/builder-railpack/plugin.toml @@ -1,4 +1,4 @@ [plugin] description = "dokku core builder-railpack plugin" -version = "0.36.5" +version = "0.36.7" [plugin.config] From 084097626557502de98775403741f057ebb91eea Mon Sep 17 00:00:00 2001 From: Jose Diaz-Gonzalez Date: Mon, 15 Sep 2025 00:21:50 -0400 Subject: [PATCH 06/15] fix: add references to BUILDKIT_HOST for setup and fix tests --- docs/deployment/builders/railpack.md | 13 +++++++++++-- tests/unit/builder-railpack.bats | 8 ++++++++ 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/docs/deployment/builders/railpack.md b/docs/deployment/builders/railpack.md index 3483c7d72..dc0d634fb 100644 --- a/docs/deployment/builders/railpack.md +++ b/docs/deployment/builders/railpack.md @@ -9,9 +9,18 @@ The `railpack` builder builds apps via [Railpack](https://railpack.com/), a buil ### Requirements -The `railpack` cli tool is not included by default with Dokku or as a dependency. It must also be installed as shown on [this page](https://railpack.com/installation). +Before using Railpacks, the following steps must be taken: -Builds will proceed with the `railpack` cli for the app from then on. +- Install the `railpack` cli: The `railpack` cli tool is not included by default with Dokku or as a dependency. It must also be installed as shown on [this page](https://railpack.com/installation). +- Create a `buildkit` builder: Railpack uses buildkit. + ```shell + docker run --rm --privileged -d --name buildkit moby/buildkit + ``` +- Set the buildkit builder: Update the `/etc/default/dokku` file to set `BUILDKIT_HOST`: + ```shell + touch /etc/default/dokku + echo "export BUILDKIT_HOST='docker-container://buildkit'" >> /etc/default/dokku + ```` ### Detection diff --git a/tests/unit/builder-railpack.bats b/tests/unit/builder-railpack.bats index 017123f0c..069960a07 100644 --- a/tests/unit/builder-railpack.bats +++ b/tests/unit/builder-railpack.bats @@ -4,6 +4,14 @@ load test_helper setup_file() { install_railpack + docker run --rm --privileged -d --name buildkit moby/buildkit:latest + touch /etc/default/dokku + sudo tee -a /etc/default/dokku <<<"export BUILDKIT_HOST='docker-container://buildkit'" +} + +teardown_file() { + docker container stop buildkit || true + docker container rm buildkit || true } setup() { From b21b58ed3850dad34a1777b3ec43a945a8180302 Mon Sep 17 00:00:00 2001 From: Jose Diaz-Gonzalez Date: Mon, 15 Sep 2025 00:21:58 -0400 Subject: [PATCH 07/15] fix: remove extra _ --- tests/unit/scheduler-k3s-1.bats | 2 +- tests/unit/scheduler-k3s-2.bats | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/unit/scheduler-k3s-1.bats b/tests/unit/scheduler-k3s-1.bats index f9fbcd455..b89be6d0e 100644 --- a/tests/unit/scheduler-k3s-1.bats +++ b/tests/unit/scheduler-k3s-1.bats @@ -11,7 +11,7 @@ setup() { export KUBECONFIG="/etc/rancher/k3s/k3s.yaml" } -teardown_() { +teardown() { global_teardown dokku nginx:start uninstall_k3s || true diff --git a/tests/unit/scheduler-k3s-2.bats b/tests/unit/scheduler-k3s-2.bats index b1c47e881..978bfa531 100644 --- a/tests/unit/scheduler-k3s-2.bats +++ b/tests/unit/scheduler-k3s-2.bats @@ -11,7 +11,7 @@ setup() { export KUBECONFIG="/etc/rancher/k3s/k3s.yaml" } -teardown_() { +teardown() { global_teardown dokku nginx:start uninstall_k3s || true From 795e4f0f34be60fc2e1c6afc81f602810baddc5a Mon Sep 17 00:00:00 2001 From: Jose Diaz-Gonzalez Date: Tue, 16 Sep 2025 22:09:07 -0400 Subject: [PATCH 08/15] fix: cleanup build image in railpack builder Without this, it is possible to keep an old build image around in the case of failed builds, and due to missing label support, the image will never be cleaned up. --- plugins/builder-railpack/builder-build | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/plugins/builder-railpack/builder-build b/plugins/builder-railpack/builder-build index b64dce3a6..e0716522d 100755 --- a/plugins/builder-railpack/builder-build +++ b/plugins/builder-railpack/builder-build @@ -50,16 +50,19 @@ trigger-builder-railpack-builder-build() { fi # shellcheck disable=SC2086 - if ! railpack build "${ARG_ARRAY[@]}" $RAILPACK_ARGS --name "$IMAGE" "$SOURCECODE_WORK_DIR"; then + if ! railpack build "${ARG_ARRAY[@]}" $RAILPACK_ARGS --name "$IMAGE-build" "$SOURCECODE_WORK_DIR"; then dokku_log_warn "Failure building image" return 1 fi - if ! suppress_output "$DOCKER_BIN" image build -f "$PLUGIN_AVAILABLE_PATH/builder-railpack/dockerfiles/builder-build.Dockerfile" --build-arg APP_IMAGE="$IMAGE" "${DOCKER_BUILD_LABEL_ARGS[@]}" $DOKKU_GLOBAL_BUILD_ARGS -t "$IMAGE" "$SOURCECODE_WORK_DIR"; then + if ! suppress_output "$DOCKER_BIN" image build -f "$PLUGIN_AVAILABLE_PATH/builder-railpack/dockerfiles/builder-build.Dockerfile" --build-arg APP_IMAGE="$IMAGE-build" "${DOCKER_BUILD_LABEL_ARGS[@]}" $DOKKU_GLOBAL_BUILD_ARGS -t "$IMAGE" "$SOURCECODE_WORK_DIR"; then + "$DOCKER_BIN" image remove "$IMAGE-build" dokku_log_warn "Failure injecting docker labels and custom entrypoint on image" return 1 fi + "$DOCKER_BIN" image remove "$IMAGE-build" + plugn trigger post-build "$BUILDER_TYPE" "$APP" "$SOURCECODE_WORK_DIR" popd &>/dev/null || pushd "/tmp" >/dev/null } From b9025f61372a2457cf93f323846f036f7181057a Mon Sep 17 00:00:00 2001 From: Jose Diaz-Gonzalez Date: Tue, 16 Sep 2025 22:09:23 -0400 Subject: [PATCH 09/15] fix: drop unnecessary entrypoint --- .../builder-railpack/dockerfiles/builder-build.Dockerfile | 5 ----- 1 file changed, 5 deletions(-) diff --git a/plugins/builder-railpack/dockerfiles/builder-build.Dockerfile b/plugins/builder-railpack/dockerfiles/builder-build.Dockerfile index 57aa80d1c..cca256f21 100644 --- a/plugins/builder-railpack/dockerfiles/builder-build.Dockerfile +++ b/plugins/builder-railpack/dockerfiles/builder-build.Dockerfile @@ -1,7 +1,2 @@ ARG APP_IMAGE FROM $APP_IMAGE - -RUN printf '#!/usr/bin/env bash\nexec bash -l -c -- \"$*\"\n' > /usr/local/bin/entrypoint && \ - chmod +x /usr/local/bin/entrypoint - -ENTRYPOINT ["/usr/local/bin/entrypoint"] From 5e85038d9c6fd92667bc94e93c023242753e1056 Mon Sep 17 00:00:00 2001 From: Jose Diaz-Gonzalez Date: Tue, 16 Sep 2025 22:14:12 -0400 Subject: [PATCH 10/15] feat: add PrintCommand support to all task executors --- plugins/common/exec.go | 5 ++++- plugins/common/plugn.go | 5 ++++- plugins/common/sftp.go | 2 +- plugins/common/ssh.go | 3 ++- 4 files changed, 11 insertions(+), 4 deletions(-) diff --git a/plugins/common/exec.go b/plugins/common/exec.go index c5790ba6e..367449b8b 100644 --- a/plugins/common/exec.go +++ b/plugins/common/exec.go @@ -29,6 +29,9 @@ type ExecCommandInput struct { // Env is the environment variables to pass to the command Env map[string]string + // PrintCommand prints the command before executing + PrintCommand bool + // Stdin is the stdin of the command Stdin io.Reader @@ -141,7 +144,7 @@ func CallExecCommandWithContext(ctx context.Context, input ExecCommandInput) (Ex cmd.Cwd = input.WorkingDirectory } - if os.Getenv("DOKKU_TRACE") == "1" { + if input.PrintCommand || os.Getenv("DOKKU_TRACE") == "1" { argsSt := "" if len(cmd.Args) > 0 { argsSt = strings.Join(cmd.Args, " ") diff --git a/plugins/common/plugn.go b/plugins/common/plugn.go index 8ce905ac5..4acf58a21 100644 --- a/plugins/common/plugn.go +++ b/plugins/common/plugn.go @@ -19,6 +19,9 @@ type PlugnTriggerInput struct { // Env is the environment variables to pass to the trigger Env map[string]string + // PrintCommand prints the command before executing + PrintCommand bool + // Stdin is the stdin of the command Stdin io.Reader @@ -55,7 +58,7 @@ func CallPlugnTriggerWithContext(ctx context.Context, input PlugnTriggerInput) ( StreamStderr: input.StreamStderr, }) - if os.Getenv("DOKKU_TRACE") == "1" { + if input.PrintCommand || os.Getenv("DOKKU_TRACE") == "1" { for _, line := range strings.Split(result.Stderr, "\n") { LogDebug(fmt.Sprintf("plugn trigger %s stderr: %s", input.Trigger, line)) } diff --git a/plugins/common/sftp.go b/plugins/common/sftp.go index 1d8ade339..2758ff4e3 100644 --- a/plugins/common/sftp.go +++ b/plugins/common/sftp.go @@ -219,7 +219,7 @@ func (task SftpCopyTask) Execute(ctx context.Context) (SftpCopyResult, error) { }, ctx.Err() } - if task.PrintCommand { + if task.PrintCommand || os.Getenv("DOKKU_TRACE") == "1" { LogDebug(fmt.Sprintf("ssh %s@%s cp %s %v", task.Username, task.Hostname, task.SourcePath, task.DestinationPath)) } diff --git a/plugins/common/ssh.go b/plugins/common/ssh.go index c23f63bc9..f823c75c3 100644 --- a/plugins/common/ssh.go +++ b/plugins/common/ssh.go @@ -203,6 +203,7 @@ type SshTask struct { // PrintCommand prints the command before executing PrintCommand bool + // StreamStdio prints stdout and stderr directly to os.Stdout/err as // the command runs. StreamStdio bool @@ -334,7 +335,7 @@ func (task SshTask) Execute(ctx context.Context) (SshResult, error) { command = "sudo" } - if task.PrintCommand { + if task.PrintCommand || os.Getenv("DOKKU_TRACE") == "1" { LogDebug(fmt.Sprintf("ssh %s@%s %s %v", task.Username, task.Hostname, command, commandArgs)) } From 9af8ec2accc934e58c583b3cb22762d3013bcaff Mon Sep 17 00:00:00 2001 From: Jose Diaz-Gonzalez Date: Tue, 16 Sep 2025 23:07:14 -0400 Subject: [PATCH 11/15] fix: re-add entrypoint It is broken but we still want something like this... --- .../builder-railpack/dockerfiles/builder-build.Dockerfile | 5 +++++ plugins/builder-railpack/dockerfiles/entrypoint | 6 ++++++ 2 files changed, 11 insertions(+) create mode 100755 plugins/builder-railpack/dockerfiles/entrypoint diff --git a/plugins/builder-railpack/dockerfiles/builder-build.Dockerfile b/plugins/builder-railpack/dockerfiles/builder-build.Dockerfile index cca256f21..540af37c5 100644 --- a/plugins/builder-railpack/dockerfiles/builder-build.Dockerfile +++ b/plugins/builder-railpack/dockerfiles/builder-build.Dockerfile @@ -1,2 +1,7 @@ ARG APP_IMAGE FROM $APP_IMAGE + +RUN printf '#!/usr/bin/env bash\nset -x\nexec bash -l -c -- \"$*\"\n' > /usr/local/bin/entrypoint && \ + chmod +x /usr/local/bin/entrypoint + +ENTRYPOINT ["/usr/local/bin/entrypoint"] diff --git a/plugins/builder-railpack/dockerfiles/entrypoint b/plugins/builder-railpack/dockerfiles/entrypoint new file mode 100755 index 000000000..f457dd278 --- /dev/null +++ b/plugins/builder-railpack/dockerfiles/entrypoint @@ -0,0 +1,6 @@ +#!/usr/bin/env bash + +echo "#!/usr/bin/env bash" > /tmp/cmd +echo "" >> /tmp/cmd +echo "$@" >> /tmp/cmd +exec bash "$@" From b4fbf7189e1469c32e6b6aea964a045e38d0624b Mon Sep 17 00:00:00 2001 From: Jose Diaz-Gonzalez Date: Tue, 16 Sep 2025 23:39:36 -0400 Subject: [PATCH 12/15] fix: update tests --- tests/unit/builder-railpack.bats | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/unit/builder-railpack.bats b/tests/unit/builder-railpack.bats index 069960a07..d92916ef7 100644 --- a/tests/unit/builder-railpack.bats +++ b/tests/unit/builder-railpack.bats @@ -37,7 +37,7 @@ teardown() { echo "output: $output" echo "status: $status" assert_success - assert_output_contains 'load build definition from Dockerfile' + assert_output_contains 'Successfully built image in' assert_output_contains "SECRET_KEY: fjdkslafjdk" run /bin/bash -c "dokku builder-railpack:set $TEST_APP railpackjson-path nonexistent.json" @@ -49,7 +49,7 @@ teardown() { echo "output: $output" echo "status: $status" assert_success - assert_output_contains 'load build definition from Dockerfile' + assert_output_contains 'Successfully built image in' } inject_requirements_txt() { From 3c6ace7d68740e018e8aeaea39eb5c8c8c08f835 Mon Sep 17 00:00:00 2001 From: Jose Diaz-Gonzalez Date: Tue, 16 Sep 2025 23:39:47 -0400 Subject: [PATCH 13/15] tests: add global setup/teardown --- tests/unit/builder-railpack.bats | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/unit/builder-railpack.bats b/tests/unit/builder-railpack.bats index d92916ef7..e0dcc5f6c 100644 --- a/tests/unit/builder-railpack.bats +++ b/tests/unit/builder-railpack.bats @@ -3,6 +3,7 @@ load test_helper setup_file() { + global_setup install_railpack docker run --rm --privileged -d --name buildkit moby/buildkit:latest touch /etc/default/dokku @@ -20,6 +21,7 @@ setup() { teardown() { destroy_app + global_teardown } @test "(builder-railpack:set)" { From e5196a2f0365536ffb577295ab2febfd5a73d200 Mon Sep 17 00:00:00 2001 From: Jose Diaz-Gonzalez Date: Tue, 16 Sep 2025 23:40:10 -0400 Subject: [PATCH 14/15] fix: remove entrypoint to ensure we can pass commands as arrays instead of quoted strings --- .../builder-railpack/dockerfiles/builder-build.Dockerfile | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/plugins/builder-railpack/dockerfiles/builder-build.Dockerfile b/plugins/builder-railpack/dockerfiles/builder-build.Dockerfile index 540af37c5..185c7e950 100644 --- a/plugins/builder-railpack/dockerfiles/builder-build.Dockerfile +++ b/plugins/builder-railpack/dockerfiles/builder-build.Dockerfile @@ -1,7 +1,4 @@ ARG APP_IMAGE FROM $APP_IMAGE -RUN printf '#!/usr/bin/env bash\nset -x\nexec bash -l -c -- \"$*\"\n' > /usr/local/bin/entrypoint && \ - chmod +x /usr/local/bin/entrypoint - -ENTRYPOINT ["/usr/local/bin/entrypoint"] +ENTRYPOINT [] From f2abbad5b793a6d762bbd0ce5d958fc702f8a81d Mon Sep 17 00:00:00 2001 From: Jose Diaz-Gonzalez Date: Tue, 16 Sep 2025 23:51:58 -0400 Subject: [PATCH 15/15] chore: remove unused entrypoint file --- plugins/builder-railpack/dockerfiles/entrypoint | 6 ------ 1 file changed, 6 deletions(-) delete mode 100755 plugins/builder-railpack/dockerfiles/entrypoint diff --git a/plugins/builder-railpack/dockerfiles/entrypoint b/plugins/builder-railpack/dockerfiles/entrypoint deleted file mode 100755 index f457dd278..000000000 --- a/plugins/builder-railpack/dockerfiles/entrypoint +++ /dev/null @@ -1,6 +0,0 @@ -#!/usr/bin/env bash - -echo "#!/usr/bin/env bash" > /tmp/cmd -echo "" >> /tmp/cmd -echo "$@" >> /tmp/cmd -exec bash "$@"