mirror of
https://github.com/frappe/frappe_docker.git
synced 2026-06-17 13:55:08 +00:00
test(easy-docker): add bats coverage for critical flows
This commit is contained in:
parent
f88cf1d8b8
commit
0571a84648
10 changed files with 1086 additions and 6 deletions
38
.github/workflows/easy-docker.yml
vendored
Normal file
38
.github/workflows/easy-docker.yml
vendored
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
name: Easy Docker Tests
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
paths:
|
||||
- "easy-docker.sh"
|
||||
- "scripts/easy-docker/**"
|
||||
- "tests/easy-docker/**"
|
||||
- ".github/workflows/easy-docker.yml"
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
paths:
|
||||
- "easy-docker.sh"
|
||||
- "scripts/easy-docker/**"
|
||||
- "tests/easy-docker/**"
|
||||
- ".github/workflows/easy-docker.yml"
|
||||
|
||||
jobs:
|
||||
bats:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 10
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Install Bats
|
||||
run: |
|
||||
BATS_VERSION="v1.11.1"
|
||||
curl -fsSL "https://github.com/bats-core/bats-core/archive/refs/tags/${BATS_VERSION}.tar.gz" -o bats-core.tar.gz
|
||||
tar -xzf bats-core.tar.gz
|
||||
sudo "./bats-core-${BATS_VERSION#v}/install.sh" /usr/local
|
||||
|
||||
- name: Run easy-docker Bats tests
|
||||
run: bats -p --recursive tests/easy-docker
|
||||
|
|
@ -12,13 +12,13 @@ USAGE
|
|||
|
||||
parse_cli_options() {
|
||||
local result_var="${1}"
|
||||
local disable_installation_fallback=0
|
||||
local disable_installation_fallback_value=0
|
||||
shift
|
||||
|
||||
while [ "$#" -gt 0 ]; do
|
||||
case "$1" in
|
||||
--no-installation-fallback)
|
||||
disable_installation_fallback=1
|
||||
disable_installation_fallback_value=1
|
||||
;;
|
||||
-h | --help)
|
||||
print_usage
|
||||
|
|
@ -33,6 +33,6 @@ parse_cli_options() {
|
|||
shift
|
||||
done
|
||||
|
||||
printf -v "${result_var}" "%s" "${disable_installation_fallback}"
|
||||
printf -v "${result_var}" "%s" "${disable_installation_fallback_value}"
|
||||
return 0
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,12 @@
|
|||
|
||||
get_easy_docker_repo_root() {
|
||||
local app_lib_dir=""
|
||||
|
||||
if [ -n "${EASY_DOCKER_REPO_ROOT_OVERRIDE:-}" ]; then
|
||||
printf '%s\n' "${EASY_DOCKER_REPO_ROOT_OVERRIDE}"
|
||||
return 0
|
||||
fi
|
||||
|
||||
app_lib_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
# core.sh lives in scripts/easy-docker/lib/app/wizard/common
|
||||
# so we need 6 levels up to reach repository root.
|
||||
|
|
@ -55,14 +61,15 @@ create_stack_directory_with_metadata() {
|
|||
return 2
|
||||
fi
|
||||
|
||||
if [ -z "${frappe_branch}" ]; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
if ! mkdir -p "${created_stack_dir}"; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
created_at="$(get_current_utc_timestamp)"
|
||||
if [ -z "${frappe_branch}" ]; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
if ! cat >"${metadata_path}" <<EOF; then
|
||||
{
|
||||
|
|
|
|||
86
tests/easy-docker/10_cli_smoke.bats
Executable file
86
tests/easy-docker/10_cli_smoke.bats
Executable file
|
|
@ -0,0 +1,86 @@
|
|||
#!/usr/bin/env bats
|
||||
|
||||
setup() {
|
||||
ROOT_DIR="$(cd "${BATS_TEST_DIRNAME}/../.." && pwd)"
|
||||
MAIN_SCRIPT="${ROOT_DIR}/scripts/easy-docker/main.sh"
|
||||
|
||||
SYSTEM_BASH="$(command -v bash)"
|
||||
SYSTEM_CAT="$(command -v cat)"
|
||||
SYSTEM_CHMOD="$(command -v chmod)"
|
||||
SYSTEM_DIRNAME="$(command -v dirname)"
|
||||
SYSTEM_ENV="$(command -v env)"
|
||||
SYSTEM_MKDIR="$(command -v mkdir)"
|
||||
SYSTEM_MKTEMP="$(command -v mktemp)"
|
||||
SYSTEM_RM="$(command -v rm)"
|
||||
|
||||
TEST_TMPDIR="$("${SYSTEM_MKTEMP}" -d)"
|
||||
STUB_BIN="${TEST_TMPDIR}/bin"
|
||||
"${SYSTEM_MKDIR}" -p "${STUB_BIN}"
|
||||
|
||||
write_passthrough_stub cat "${SYSTEM_CAT}"
|
||||
write_passthrough_stub dirname "${SYSTEM_DIRNAME}"
|
||||
}
|
||||
|
||||
teardown() {
|
||||
if [ -n "${TEST_TMPDIR:-}" ] && [ -d "${TEST_TMPDIR}" ]; then
|
||||
"${SYSTEM_RM}" -rf "${TEST_TMPDIR}"
|
||||
fi
|
||||
}
|
||||
|
||||
write_stub() {
|
||||
local name="$1"
|
||||
shift
|
||||
|
||||
{
|
||||
printf '#!%s\n' "${SYSTEM_BASH}"
|
||||
printf '%s\n' "$@"
|
||||
} >"${STUB_BIN}/${name}"
|
||||
"${SYSTEM_CHMOD}" +x "${STUB_BIN}/${name}"
|
||||
}
|
||||
|
||||
write_passthrough_stub() {
|
||||
local name="$1"
|
||||
local target="$2"
|
||||
|
||||
{
|
||||
printf '#!%s\n' "${SYSTEM_BASH}"
|
||||
printf 'exec "%s" "$@"\n' "${target}"
|
||||
} >"${STUB_BIN}/${name}"
|
||||
"${SYSTEM_CHMOD}" +x "${STUB_BIN}/${name}"
|
||||
}
|
||||
|
||||
@test "help prints usage and exits cleanly" {
|
||||
run "${SYSTEM_ENV}" "PATH=${STUB_BIN}" "${SYSTEM_BASH}" "${MAIN_SCRIPT}" --help
|
||||
|
||||
[ "${status}" -eq 0 ]
|
||||
[[ "${output}" == *"Usage: bash easy-docker.sh [options]"* ]]
|
||||
[[ "${output}" == *"--no-installation-fallback"* ]]
|
||||
}
|
||||
|
||||
@test "unknown option is rejected before startup" {
|
||||
run "${SYSTEM_ENV}" "PATH=${STUB_BIN}" "${SYSTEM_BASH}" "${MAIN_SCRIPT}" --definitely-unknown
|
||||
|
||||
[ "${status}" -eq 1 ]
|
||||
[[ "${output}" == *"Unknown option: --definitely-unknown"* ]]
|
||||
[[ "${output}" == *"Usage: bash easy-docker.sh [options]"* ]]
|
||||
}
|
||||
|
||||
@test "missing gum fails without interactive fallback when disabled" {
|
||||
run "${SYSTEM_ENV}" "PATH=${STUB_BIN}" "${SYSTEM_BASH}" "${MAIN_SCRIPT}" --no-installation-fallback
|
||||
|
||||
[ "${status}" -eq 1 ]
|
||||
[[ "${output}" == *"gum is not installed. Trying package manager installation..."* ]]
|
||||
[[ "${output}" == *"No supported package manager was found."* ]]
|
||||
[[ "${output}" == *"Installation fallback is disabled."* ]]
|
||||
[[ "${output}" == *"Install gum manually:"* ]]
|
||||
}
|
||||
|
||||
@test "missing docker stops after gum dependency succeeds" {
|
||||
write_stub gum 'exit 0'
|
||||
|
||||
run "${SYSTEM_ENV}" "PATH=${STUB_BIN}" "${SYSTEM_BASH}" "${MAIN_SCRIPT}" --no-installation-fallback
|
||||
|
||||
[ "${status}" -eq 1 ]
|
||||
[[ "${output}" == *"docker is not installed."* ]]
|
||||
[[ "${output}" == *"Install Docker first:"* ]]
|
||||
}
|
||||
179
tests/easy-docker/20_core_render.bats
Executable file
179
tests/easy-docker/20_core_render.bats
Executable file
|
|
@ -0,0 +1,179 @@
|
|||
#!/usr/bin/env bats
|
||||
|
||||
load 'test_helper.bash'
|
||||
|
||||
setup() {
|
||||
easy_docker_test_begin
|
||||
easy_docker_test_source_core_render_modules
|
||||
unset ERPNEXT_VERSION
|
||||
unset FRAPPE_BRANCH
|
||||
}
|
||||
|
||||
teardown() {
|
||||
easy_docker_test_end
|
||||
}
|
||||
|
||||
@test "is_valid_stack_name accepts safe names" {
|
||||
local name=""
|
||||
|
||||
for name in alpha alpha-1 alpha_1 alpha.1; do
|
||||
run is_valid_stack_name "${name}"
|
||||
[ "${status}" -eq 0 ]
|
||||
done
|
||||
}
|
||||
|
||||
@test "is_valid_stack_name rejects empty and unsafe names" {
|
||||
local name=""
|
||||
|
||||
for name in "" "bad name" "bad/name" "bad:name" "bad*name"; do
|
||||
run is_valid_stack_name "${name}"
|
||||
[ "${status}" -eq 1 ]
|
||||
done
|
||||
}
|
||||
|
||||
@test "get_env_file_key_value parses exported and quoted values" {
|
||||
local sandbox_root=""
|
||||
local stack_dir=""
|
||||
local env_file=""
|
||||
|
||||
sandbox_root="$(easy_docker_test_create_repo_sandbox "env-parse")"
|
||||
easy_docker_test_override_repo_root "${sandbox_root}"
|
||||
stack_dir="$(easy_docker_test_stack_dir "env-parse")"
|
||||
mkdir -p "${stack_dir}"
|
||||
env_file="${stack_dir}/stack.env"
|
||||
|
||||
cat >"${env_file}" <<'EOF'
|
||||
# comment
|
||||
export ERPNEXT_VERSION=15.9.0-test
|
||||
STACK_NAME="My Stack"
|
||||
IGNORED=value
|
||||
EOF
|
||||
|
||||
run get_env_file_key_value "${env_file}" ERPNEXT_VERSION
|
||||
[ "${status}" -eq 0 ]
|
||||
[ "${output}" = "15.9.0-test" ]
|
||||
|
||||
run get_env_file_key_value "${env_file}" STACK_NAME
|
||||
[ "${status}" -eq 0 ]
|
||||
[ "${output}" = "My Stack" ]
|
||||
}
|
||||
|
||||
@test "get_stack_compose_project_name normalizes metadata stack names" {
|
||||
local sandbox_root=""
|
||||
local stack_dir=""
|
||||
|
||||
sandbox_root="$(easy_docker_test_create_repo_sandbox "project-name")"
|
||||
easy_docker_test_override_repo_root "${sandbox_root}"
|
||||
stack_dir="$(easy_docker_test_stack_dir "project-name")"
|
||||
mkdir -p "${stack_dir}"
|
||||
|
||||
cat >"${stack_dir}/metadata.json" <<'EOF'
|
||||
{
|
||||
"stack_name": "My Stack! 01"
|
||||
}
|
||||
EOF
|
||||
|
||||
run get_stack_compose_project_name "${stack_dir}"
|
||||
[ "${status}" -eq 0 ]
|
||||
[ "${output}" = "easydocker-my-stack-01" ]
|
||||
}
|
||||
|
||||
@test "get_metadata_compose_files_lines returns compose file entries" {
|
||||
local sandbox_root=""
|
||||
local stack_dir=""
|
||||
local expected=""
|
||||
|
||||
sandbox_root="$(easy_docker_test_create_repo_sandbox "compose-lines")"
|
||||
easy_docker_test_override_repo_root "${sandbox_root}"
|
||||
stack_dir="$(easy_docker_test_stack_dir "compose-lines")"
|
||||
mkdir -p "${stack_dir}"
|
||||
|
||||
cat >"${stack_dir}/metadata.json" <<'EOF'
|
||||
{
|
||||
"stack_name": "compose-lines",
|
||||
"compose_files": [
|
||||
"compose.yaml",
|
||||
"overrides/compose.proxy.yaml",
|
||||
"overrides/compose.redis.yaml"
|
||||
]
|
||||
}
|
||||
EOF
|
||||
|
||||
expected=$'compose.yaml\noverrides/compose.proxy.yaml\noverrides/compose.redis.yaml'
|
||||
|
||||
run get_metadata_compose_files_lines "${stack_dir}/metadata.json"
|
||||
[ "${status}" -eq 0 ]
|
||||
[ "${output}" = "${expected}" ]
|
||||
}
|
||||
|
||||
@test "render_stack_compose_from_metadata writes generated compose with stubbed docker config" {
|
||||
local sandbox_root=""
|
||||
local stack_dir=""
|
||||
local env_path=""
|
||||
local generated_compose_path=""
|
||||
local invocation_log=""
|
||||
|
||||
easy_docker_test_install_docker_stub
|
||||
|
||||
sandbox_root="$(easy_docker_test_create_repo_sandbox "render-smoke")"
|
||||
easy_docker_test_override_repo_root "${sandbox_root}"
|
||||
stack_dir="$(easy_docker_test_stack_dir "render-smoke")"
|
||||
mkdir -p "${stack_dir}"
|
||||
|
||||
cat >"${sandbox_root}/compose.yaml" <<'EOF'
|
||||
services:
|
||||
backend:
|
||||
image: frappe/backend
|
||||
EOF
|
||||
|
||||
cat >"${sandbox_root}/overrides/compose.proxy.yaml" <<'EOF'
|
||||
services:
|
||||
frontend:
|
||||
image: frappe/frontend
|
||||
EOF
|
||||
|
||||
cat >"${sandbox_root}/overrides/compose.redis.yaml" <<'EOF'
|
||||
services:
|
||||
redis-cache:
|
||||
image: redis:7
|
||||
EOF
|
||||
|
||||
cat >"${stack_dir}/metadata.json" <<'EOF'
|
||||
{
|
||||
"stack_name": "My Stack! 01",
|
||||
"compose_files": [
|
||||
"compose.yaml",
|
||||
"overrides/compose.proxy.yaml",
|
||||
"overrides/compose.redis.yaml"
|
||||
]
|
||||
}
|
||||
EOF
|
||||
|
||||
env_path="${stack_dir}/My Stack! 01.env"
|
||||
cat >"${env_path}" <<'EOF'
|
||||
DB_HOST=localhost
|
||||
EOF
|
||||
|
||||
generated_compose_path="${stack_dir}/compose.generated.yaml"
|
||||
invocation_log="${EASY_DOCKER_TEST_TMPDIR}/docker.invocations"
|
||||
|
||||
export ERPNEXT_VERSION="15.9.0-test"
|
||||
|
||||
run render_stack_compose_from_metadata "${stack_dir}"
|
||||
[ "${status}" -eq 0 ]
|
||||
[ -f "${generated_compose_path}" ]
|
||||
[ ! -f "${generated_compose_path}.tmp" ]
|
||||
|
||||
run cat "${generated_compose_path}"
|
||||
[ "${status}" -eq 0 ]
|
||||
[[ "${output}" == *"invocation=docker compose --project-name easydocker-my-stack-01 --env-file ${env_path}"* ]]
|
||||
[[ "${output}" == *"-f ${sandbox_root}/compose.yaml"* ]]
|
||||
[[ "${output}" == *"-f ${sandbox_root}/overrides/compose.proxy.yaml"* ]]
|
||||
[[ "${output}" == *"-f ${sandbox_root}/overrides/compose.redis.yaml"* ]]
|
||||
[[ "${output}" == *"erpnext=15.9.0-test"* ]]
|
||||
|
||||
run cat "${invocation_log}"
|
||||
[ "${status}" -eq 0 ]
|
||||
[[ "${output}" == *"docker compose --project-name easydocker-my-stack-01 --env-file ${env_path} -f "* ]]
|
||||
[[ "${output}" == *"config"* ]]
|
||||
}
|
||||
120
tests/easy-docker/30_gum_ensure.bats
Executable file
120
tests/easy-docker/30_gum_ensure.bats
Executable file
|
|
@ -0,0 +1,120 @@
|
|||
#!/usr/bin/env bats
|
||||
|
||||
load 'test_helper.bash'
|
||||
|
||||
setup() {
|
||||
easy_docker_test_begin
|
||||
easy_docker_test_source_gum_modules
|
||||
}
|
||||
|
||||
teardown() {
|
||||
easy_docker_test_end
|
||||
}
|
||||
|
||||
@test "should_use_github_fallback rejects non-interactive terminals" {
|
||||
local script_path=""
|
||||
local repo_root=""
|
||||
|
||||
repo_root="$(easy_docker_test_repo_root)"
|
||||
script_path="${EASY_DOCKER_TEST_TMPDIR}/run-should-use-github-fallback"
|
||||
easy_docker_test_write_executable "${script_path}" \
|
||||
"source \"${repo_root}/scripts/easy-docker/lib/install/gum/ensure.sh\"" \
|
||||
'should_use_github_fallback'
|
||||
|
||||
run "${script_path}" </dev/null
|
||||
|
||||
[ "${status}" -eq 1 ]
|
||||
[[ "${output}" == *"GitHub fallback prompt requires an interactive terminal."* ]]
|
||||
}
|
||||
|
||||
@test "ensure_gum succeeds immediately when gum is already installed" {
|
||||
# shellcheck disable=SC2317
|
||||
command_exists() {
|
||||
[ "${1}" = "gum" ]
|
||||
}
|
||||
|
||||
run ensure_gum 0
|
||||
|
||||
[ "${status}" -eq 0 ]
|
||||
[ -z "${output}" ]
|
||||
}
|
||||
|
||||
@test "ensure_gum stops with manual guidance when fallback is disabled" {
|
||||
# shellcheck disable=SC2317
|
||||
command_exists() {
|
||||
return 1
|
||||
}
|
||||
|
||||
# shellcheck disable=SC2317
|
||||
install_gum_with_package_manager() {
|
||||
echo "Package manager installation did not succeed."
|
||||
return 1
|
||||
}
|
||||
|
||||
run ensure_gum 1
|
||||
|
||||
[ "${status}" -eq 1 ]
|
||||
[[ "${output}" == *"gum is not installed. Trying package manager installation..."* ]]
|
||||
[[ "${output}" == *"Package manager installation did not succeed."* ]]
|
||||
[[ "${output}" == *"Installation fallback is disabled."* ]]
|
||||
[[ "${output}" == *"Install gum manually:"* ]]
|
||||
}
|
||||
|
||||
@test "ensure_gum succeeds when github fallback installs gum" {
|
||||
gum_installed=0
|
||||
|
||||
# shellcheck disable=SC2317
|
||||
command_exists() {
|
||||
if [ "${1}" = "gum" ] && [ "${gum_installed}" -eq 1 ]; then
|
||||
return 0
|
||||
fi
|
||||
return 1
|
||||
}
|
||||
|
||||
# shellcheck disable=SC2317
|
||||
install_gum_with_package_manager() {
|
||||
echo "Package manager installation did not succeed."
|
||||
return 1
|
||||
}
|
||||
|
||||
# shellcheck disable=SC2317
|
||||
should_use_github_fallback() {
|
||||
return 0
|
||||
}
|
||||
|
||||
# shellcheck disable=SC2317
|
||||
install_gum_from_github_release() {
|
||||
gum_installed=1
|
||||
return 0
|
||||
}
|
||||
|
||||
run ensure_gum 0
|
||||
|
||||
[ "${status}" -eq 0 ]
|
||||
[[ "${output}" == *"Trying pinned GitHub release fallback..."* ]]
|
||||
[[ "${output}" == *"gum was installed successfully."* ]]
|
||||
}
|
||||
|
||||
@test "ensure_gum aborts when github fallback is declined" {
|
||||
# shellcheck disable=SC2317
|
||||
command_exists() {
|
||||
return 1
|
||||
}
|
||||
|
||||
# shellcheck disable=SC2317
|
||||
install_gum_with_package_manager() {
|
||||
echo "No supported package manager was found."
|
||||
return 1
|
||||
}
|
||||
|
||||
# shellcheck disable=SC2317
|
||||
should_use_github_fallback() {
|
||||
return 1
|
||||
}
|
||||
|
||||
run ensure_gum 0
|
||||
|
||||
[ "${status}" -eq 1 ]
|
||||
[[ "${output}" == *"GitHub fallback was not selected."* ]]
|
||||
[[ "${output}" == *"Install gum manually:"* ]]
|
||||
}
|
||||
147
tests/easy-docker/40_docker_checks.bats
Executable file
147
tests/easy-docker/40_docker_checks.bats
Executable file
|
|
@ -0,0 +1,147 @@
|
|||
#!/usr/bin/env bats
|
||||
|
||||
load 'test_helper.bash'
|
||||
|
||||
setup() {
|
||||
easy_docker_test_begin
|
||||
easy_docker_test_source_docker_modules
|
||||
}
|
||||
|
||||
teardown() {
|
||||
easy_docker_test_end
|
||||
}
|
||||
|
||||
@test "format_missing_commands_list joins newline separated commands" {
|
||||
run format_missing_commands_list $'docker exec\ndocker compose pull\ndocker compose logs'
|
||||
|
||||
[ "${status}" -eq 0 ]
|
||||
[ "${output}" = "docker exec,docker compose pull,docker compose logs" ]
|
||||
}
|
||||
|
||||
@test "get_missing_docker_commands reports missing docker and compose subcommands" {
|
||||
docker_supports_command() {
|
||||
case "$*" in
|
||||
"exec" | "compose pull")
|
||||
return 1
|
||||
;;
|
||||
*)
|
||||
return 0
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
run get_missing_docker_commands
|
||||
|
||||
[ "${status}" -eq 1 ]
|
||||
[ "${output}" = $'docker exec\ndocker compose pull' ]
|
||||
}
|
||||
|
||||
@test "ensure_docker fails when docker is not installed" {
|
||||
# shellcheck disable=SC2317
|
||||
command_exists() {
|
||||
return 1
|
||||
}
|
||||
|
||||
run ensure_docker
|
||||
|
||||
[ "${status}" -eq 1 ]
|
||||
[[ "${output}" == *"docker is not installed."* ]]
|
||||
[[ "${output}" == *"Install Docker first:"* ]]
|
||||
}
|
||||
|
||||
@test "ensure_docker fails when docker compose is unavailable" {
|
||||
# shellcheck disable=SC2317
|
||||
command_exists() {
|
||||
[ "${1}" = "docker" ]
|
||||
}
|
||||
|
||||
# shellcheck disable=SC2317
|
||||
docker_compose_available() {
|
||||
return 1
|
||||
}
|
||||
|
||||
run ensure_docker
|
||||
|
||||
[ "${status}" -eq 1 ]
|
||||
[[ "${output}" == *"docker compose (Compose v2 command) is not available."* ]]
|
||||
[[ "${output}" == *"This script requires Docker Compose v2 via the 'docker compose' command."* ]]
|
||||
}
|
||||
|
||||
@test "ensure_docker fails when the docker daemon is not running" {
|
||||
# shellcheck disable=SC2317
|
||||
command_exists() {
|
||||
[ "${1}" = "docker" ]
|
||||
}
|
||||
|
||||
# shellcheck disable=SC2317
|
||||
docker_compose_available() {
|
||||
return 0
|
||||
}
|
||||
|
||||
# shellcheck disable=SC2317
|
||||
docker_daemon_running() {
|
||||
return 1
|
||||
}
|
||||
|
||||
run ensure_docker
|
||||
|
||||
[ "${status}" -eq 1 ]
|
||||
[[ "${output}" == *"docker daemon is not running."* ]]
|
||||
[[ "${output}" == *"Start the Docker daemon/service and retry."* ]]
|
||||
}
|
||||
|
||||
@test "ensure_docker reports missing required docker commands" {
|
||||
# shellcheck disable=SC2317
|
||||
command_exists() {
|
||||
[ "${1}" = "docker" ]
|
||||
}
|
||||
|
||||
# shellcheck disable=SC2317
|
||||
docker_compose_available() {
|
||||
return 0
|
||||
}
|
||||
|
||||
# shellcheck disable=SC2317
|
||||
docker_daemon_running() {
|
||||
return 0
|
||||
}
|
||||
|
||||
# shellcheck disable=SC2317
|
||||
get_missing_docker_commands() {
|
||||
printf '%s\n' "docker exec" "docker compose pull"
|
||||
return 1
|
||||
}
|
||||
|
||||
run ensure_docker
|
||||
|
||||
[ "${status}" -eq 1 ]
|
||||
[[ "${output}" == *"Missing required docker commands: docker exec,docker compose pull"* ]]
|
||||
[[ "${output}" == *"Standard 'docker' and 'docker compose' commands are required."* ]]
|
||||
}
|
||||
|
||||
@test "ensure_docker succeeds when all prerequisites are satisfied" {
|
||||
# shellcheck disable=SC2317
|
||||
command_exists() {
|
||||
[ "${1}" = "docker" ]
|
||||
}
|
||||
|
||||
# shellcheck disable=SC2317
|
||||
docker_compose_available() {
|
||||
return 0
|
||||
}
|
||||
|
||||
# shellcheck disable=SC2317
|
||||
docker_daemon_running() {
|
||||
return 0
|
||||
}
|
||||
|
||||
# shellcheck disable=SC2317
|
||||
get_missing_docker_commands() {
|
||||
return 0
|
||||
}
|
||||
|
||||
run ensure_docker
|
||||
|
||||
[ "${status}" -eq 0 ]
|
||||
[ -z "${output}" ]
|
||||
}
|
||||
149
tests/easy-docker/50_stack_metadata.bats
Executable file
149
tests/easy-docker/50_stack_metadata.bats
Executable file
|
|
@ -0,0 +1,149 @@
|
|||
#!/usr/bin/env bats
|
||||
|
||||
load 'test_helper.bash'
|
||||
|
||||
setup() {
|
||||
easy_docker_test_begin
|
||||
easy_docker_test_source_core_render_modules
|
||||
}
|
||||
|
||||
teardown() {
|
||||
easy_docker_test_end
|
||||
}
|
||||
|
||||
@test "create_stack_directory_with_metadata writes metadata and returns the stack directory" {
|
||||
local sandbox_root=""
|
||||
local stack_dir=""
|
||||
local result_stack_dir=""
|
||||
|
||||
sandbox_root="$(easy_docker_test_create_repo_sandbox "create-metadata")"
|
||||
easy_docker_test_override_repo_root "${sandbox_root}"
|
||||
|
||||
if ! create_stack_directory_with_metadata result_stack_dir "demo-stack" "production" "version-15"; then
|
||||
false
|
||||
fi
|
||||
|
||||
stack_dir="$(easy_docker_test_stack_dir "demo-stack")"
|
||||
[ "${result_stack_dir}" = "${stack_dir}" ]
|
||||
[ -d "${result_stack_dir}" ]
|
||||
[ "$(get_metadata_string_field "${result_stack_dir}/metadata.json" "stack_name")" = "demo-stack" ]
|
||||
[ "$(get_metadata_string_field "${result_stack_dir}/metadata.json" "setup_type")" = "production" ]
|
||||
[ "$(get_metadata_string_field "${result_stack_dir}/metadata.json" "frappe_branch")" = "version-15" ]
|
||||
[ -n "$(get_metadata_string_field "${result_stack_dir}/metadata.json" "created_at")" ]
|
||||
}
|
||||
|
||||
@test "create_stack_directory_with_metadata rejects duplicate stack directories" {
|
||||
local sandbox_root=""
|
||||
local result_stack_dir=""
|
||||
local metadata_path=""
|
||||
local status_code=""
|
||||
|
||||
sandbox_root="$(easy_docker_test_create_repo_sandbox "duplicate-stack")"
|
||||
easy_docker_test_override_repo_root "${sandbox_root}"
|
||||
|
||||
if ! create_stack_directory_with_metadata result_stack_dir "duplicate-stack" "production" "version-15"; then
|
||||
false
|
||||
fi
|
||||
|
||||
metadata_path="${result_stack_dir}/metadata.json"
|
||||
printf '%s\n' "original" >"${metadata_path}"
|
||||
|
||||
result_stack_dir=""
|
||||
if create_stack_directory_with_metadata result_stack_dir "duplicate-stack" "production" "version-15"; then
|
||||
status_code=0
|
||||
else
|
||||
status_code=$?
|
||||
fi
|
||||
[ "${status_code}" -eq 2 ]
|
||||
[ "${result_stack_dir}" = "" ]
|
||||
[ "$(cat "${metadata_path}")" = "original" ]
|
||||
}
|
||||
|
||||
@test "create_stack_directory_with_metadata does not leave a partial stack behind when frappe_branch is missing" {
|
||||
local sandbox_root=""
|
||||
local stack_dir=""
|
||||
local result_stack_dir=""
|
||||
local status_code=""
|
||||
|
||||
sandbox_root="$(easy_docker_test_create_repo_sandbox "missing-frappe-branch")"
|
||||
easy_docker_test_override_repo_root "${sandbox_root}"
|
||||
stack_dir="$(easy_docker_test_stack_dir "missing-frappe-branch")"
|
||||
|
||||
if create_stack_directory_with_metadata result_stack_dir "missing-frappe-branch" "production" ""; then
|
||||
status_code=0
|
||||
else
|
||||
status_code=$?
|
||||
fi
|
||||
|
||||
[ "${status_code}" -eq 1 ]
|
||||
[ "${result_stack_dir}" = "" ]
|
||||
[ ! -d "${stack_dir}" ]
|
||||
}
|
||||
|
||||
@test "rollback_stack_directory removes managed stack directories" {
|
||||
local sandbox_root=""
|
||||
local stack_dir=""
|
||||
|
||||
sandbox_root="$(easy_docker_test_create_repo_sandbox "rollback-stack")"
|
||||
easy_docker_test_override_repo_root "${sandbox_root}"
|
||||
stack_dir="$(easy_docker_test_stack_dir "rollback-stack")"
|
||||
mkdir -p "${stack_dir}/nested"
|
||||
printf '%s\n' "payload" >"${stack_dir}/nested/file.txt"
|
||||
|
||||
if ! rollback_stack_directory "${stack_dir}"; then
|
||||
false
|
||||
fi
|
||||
[ ! -d "${stack_dir}" ]
|
||||
}
|
||||
|
||||
@test "rollback_stack_directory rejects paths outside the managed stacks tree" {
|
||||
local sandbox_root=""
|
||||
local outside_dir=""
|
||||
local status_code=""
|
||||
|
||||
sandbox_root="$(easy_docker_test_create_repo_sandbox "rollback-outside")"
|
||||
easy_docker_test_override_repo_root "${sandbox_root}"
|
||||
outside_dir="$(mktemp -d)"
|
||||
|
||||
if rollback_stack_directory "${outside_dir}"; then
|
||||
status_code=0
|
||||
else
|
||||
status_code=$?
|
||||
fi
|
||||
[ "${status_code}" -eq 2 ]
|
||||
[ -d "${outside_dir}" ]
|
||||
|
||||
rm -rf "${outside_dir}"
|
||||
}
|
||||
|
||||
@test "get_stack_dir_by_name returns the matching stack directory and ignores junk entries" {
|
||||
local sandbox_root=""
|
||||
local stacks_dir=""
|
||||
local matching_stack_dir=""
|
||||
local junk_dir=""
|
||||
|
||||
sandbox_root="$(easy_docker_test_create_repo_sandbox "stack-lookup")"
|
||||
easy_docker_test_override_repo_root "${sandbox_root}"
|
||||
stacks_dir="${sandbox_root}/.easy-docker/stacks"
|
||||
|
||||
junk_dir="${stacks_dir}/not-a-stack"
|
||||
matching_stack_dir="${stacks_dir}/target-stack"
|
||||
|
||||
mkdir -p "${junk_dir}" "${matching_stack_dir}"
|
||||
printf '%s\n' '{ "stack_name": "target-stack" }' >"${matching_stack_dir}/metadata.json"
|
||||
|
||||
run get_stack_dir_by_name "target-stack"
|
||||
[ "${status}" -eq 0 ]
|
||||
[ "${output}" = "${matching_stack_dir}" ]
|
||||
}
|
||||
|
||||
@test "get_stack_dir_by_name fails when the stack is absent" {
|
||||
local sandbox_root=""
|
||||
|
||||
sandbox_root="$(easy_docker_test_create_repo_sandbox "stack-missing")"
|
||||
easy_docker_test_override_repo_root "${sandbox_root}"
|
||||
|
||||
run get_stack_dir_by_name "missing-stack"
|
||||
[ "${status}" -eq 1 ]
|
||||
[ -z "${output}" ]
|
||||
}
|
||||
207
tests/easy-docker/60_compose_render_failures.bats
Executable file
207
tests/easy-docker/60_compose_render_failures.bats
Executable file
|
|
@ -0,0 +1,207 @@
|
|||
#!/usr/bin/env bats
|
||||
|
||||
load 'test_helper.bash'
|
||||
|
||||
setup() {
|
||||
easy_docker_test_begin
|
||||
easy_docker_test_source_core_render_modules
|
||||
}
|
||||
|
||||
teardown() {
|
||||
easy_docker_test_end
|
||||
}
|
||||
|
||||
write_docker_stub() {
|
||||
local body="${1}"
|
||||
|
||||
easy_docker_test_write_bin_command docker \
|
||||
'set -euo pipefail' \
|
||||
"${body}"
|
||||
easy_docker_test_prepend_bin_dir
|
||||
}
|
||||
|
||||
@test "render_stack_compose_from_metadata fails when metadata.json is missing" {
|
||||
local sandbox_root=""
|
||||
local stack_dir=""
|
||||
local generated_compose_path=""
|
||||
local docker_log=""
|
||||
|
||||
sandbox_root="$(easy_docker_test_create_repo_sandbox "render-missing-metadata")"
|
||||
easy_docker_test_override_repo_root "${sandbox_root}"
|
||||
stack_dir="$(easy_docker_test_stack_dir "render-missing-metadata")"
|
||||
mkdir -p "${stack_dir}"
|
||||
|
||||
# shellcheck disable=SC2016
|
||||
write_docker_stub 'echo "docker should not have been called" >&2; exit 99'
|
||||
|
||||
generated_compose_path="${stack_dir}/compose.generated.yaml"
|
||||
docker_log="${EASY_DOCKER_TEST_TMPDIR}/docker.log"
|
||||
|
||||
run render_stack_compose_from_metadata "${stack_dir}"
|
||||
[ "${status}" -eq 1 ]
|
||||
[ ! -f "${generated_compose_path}" ]
|
||||
[ ! -f "${generated_compose_path}.tmp" ]
|
||||
[ ! -f "${docker_log}" ]
|
||||
}
|
||||
|
||||
@test "render_stack_compose_from_metadata fails when the env file is missing" {
|
||||
local sandbox_root=""
|
||||
local stack_dir=""
|
||||
local generated_compose_path=""
|
||||
local docker_log=""
|
||||
|
||||
sandbox_root="$(easy_docker_test_create_repo_sandbox "render-missing-env")"
|
||||
easy_docker_test_override_repo_root "${sandbox_root}"
|
||||
stack_dir="$(easy_docker_test_stack_dir "render-missing-env")"
|
||||
mkdir -p "${stack_dir}"
|
||||
|
||||
cat >"${stack_dir}/metadata.json" <<'EOF'
|
||||
{
|
||||
"stack_name": "render-missing-env",
|
||||
"compose_files": [
|
||||
"compose.yaml"
|
||||
]
|
||||
}
|
||||
EOF
|
||||
|
||||
# shellcheck disable=SC2016
|
||||
write_docker_stub 'echo "docker should not have been called" >&2; exit 99'
|
||||
|
||||
generated_compose_path="${stack_dir}/compose.generated.yaml"
|
||||
docker_log="${EASY_DOCKER_TEST_TMPDIR}/docker.log"
|
||||
|
||||
run render_stack_compose_from_metadata "${stack_dir}"
|
||||
[ "${status}" -eq 1 ]
|
||||
[ ! -f "${generated_compose_path}" ]
|
||||
[ ! -f "${generated_compose_path}.tmp" ]
|
||||
[ ! -f "${docker_log}" ]
|
||||
}
|
||||
|
||||
@test "render_stack_compose_from_metadata fails when compose_files are missing" {
|
||||
local sandbox_root=""
|
||||
local stack_dir=""
|
||||
local generated_compose_path=""
|
||||
local docker_log=""
|
||||
|
||||
sandbox_root="$(easy_docker_test_create_repo_sandbox "render-missing-compose-files")"
|
||||
easy_docker_test_override_repo_root "${sandbox_root}"
|
||||
stack_dir="$(easy_docker_test_stack_dir "render-missing-compose-files")"
|
||||
mkdir -p "${stack_dir}"
|
||||
|
||||
cat >"${stack_dir}/metadata.json" <<'EOF'
|
||||
{
|
||||
"stack_name": "render-missing-compose-files"
|
||||
}
|
||||
EOF
|
||||
|
||||
cat >"${stack_dir}/render-missing-compose-files.env" <<'EOF'
|
||||
ERPNEXT_VERSION=15.9.0-test
|
||||
EOF
|
||||
|
||||
# shellcheck disable=SC2016
|
||||
write_docker_stub 'echo "docker should not have been called" >&2; exit 99'
|
||||
|
||||
generated_compose_path="${stack_dir}/compose.generated.yaml"
|
||||
docker_log="${EASY_DOCKER_TEST_TMPDIR}/docker.log"
|
||||
|
||||
run render_stack_compose_from_metadata "${stack_dir}"
|
||||
[ "${status}" -eq 1 ]
|
||||
[ ! -f "${generated_compose_path}" ]
|
||||
[ ! -f "${generated_compose_path}.tmp" ]
|
||||
[ ! -f "${docker_log}" ]
|
||||
}
|
||||
|
||||
@test "render_stack_compose_from_metadata fails when a referenced compose file is missing" {
|
||||
local sandbox_root=""
|
||||
local stack_dir=""
|
||||
local generated_compose_path=""
|
||||
local docker_log=""
|
||||
|
||||
sandbox_root="$(easy_docker_test_create_repo_sandbox "render-missing-source")"
|
||||
easy_docker_test_override_repo_root "${sandbox_root}"
|
||||
stack_dir="$(easy_docker_test_stack_dir "render-missing-source")"
|
||||
mkdir -p "${stack_dir}"
|
||||
|
||||
cat >"${stack_dir}/metadata.json" <<'EOF'
|
||||
{
|
||||
"stack_name": "render-missing-source",
|
||||
"compose_files": [
|
||||
"compose.yaml",
|
||||
"overrides/compose.proxy.yaml"
|
||||
]
|
||||
}
|
||||
EOF
|
||||
|
||||
cat >"${stack_dir}/render-missing-source.env" <<'EOF'
|
||||
ERPNEXT_VERSION=15.9.0-test
|
||||
EOF
|
||||
|
||||
cat >"${sandbox_root}/compose.yaml" <<'EOF'
|
||||
services:
|
||||
backend:
|
||||
image: frappe/backend
|
||||
EOF
|
||||
|
||||
# shellcheck disable=SC2016
|
||||
write_docker_stub 'echo "docker should not have been called" >&2; exit 99'
|
||||
|
||||
generated_compose_path="${stack_dir}/compose.generated.yaml"
|
||||
docker_log="${EASY_DOCKER_TEST_TMPDIR}/docker.log"
|
||||
|
||||
run render_stack_compose_from_metadata "${stack_dir}"
|
||||
[ "${status}" -eq 1 ]
|
||||
[ ! -f "${generated_compose_path}" ]
|
||||
[ ! -f "${generated_compose_path}.tmp" ]
|
||||
[ ! -f "${docker_log}" ]
|
||||
}
|
||||
|
||||
@test "render_stack_compose_from_metadata removes its temporary file after a docker config failure" {
|
||||
local sandbox_root=""
|
||||
local stack_dir=""
|
||||
local generated_compose_path=""
|
||||
local docker_log=""
|
||||
|
||||
sandbox_root="$(easy_docker_test_create_repo_sandbox "render-docker-failure")"
|
||||
easy_docker_test_override_repo_root "${sandbox_root}"
|
||||
stack_dir="$(easy_docker_test_stack_dir "render-docker-failure")"
|
||||
mkdir -p "${stack_dir}"
|
||||
|
||||
cat >"${stack_dir}/metadata.json" <<'EOF'
|
||||
{
|
||||
"stack_name": "render-docker-failure",
|
||||
"compose_files": [
|
||||
"compose.yaml",
|
||||
"overrides/compose.proxy.yaml"
|
||||
]
|
||||
}
|
||||
EOF
|
||||
|
||||
cat >"${stack_dir}/render-docker-failure.env" <<'EOF'
|
||||
ERPNEXT_VERSION=15.9.0-test
|
||||
EOF
|
||||
|
||||
cat >"${sandbox_root}/compose.yaml" <<'EOF'
|
||||
services:
|
||||
backend:
|
||||
image: frappe/backend
|
||||
EOF
|
||||
mkdir -p "${sandbox_root}/overrides"
|
||||
cat >"${sandbox_root}/overrides/compose.proxy.yaml" <<'EOF'
|
||||
services:
|
||||
frontend:
|
||||
image: frappe/frontend
|
||||
EOF
|
||||
|
||||
# shellcheck disable=SC2016
|
||||
write_docker_stub 'printf "%s\n" "docker $*" >>"${EASY_DOCKER_TEST_TMPDIR}/docker.log"; if [ "${*: -1}" = "config" ]; then echo "simulated docker compose config failure" >&2; exit 23; fi; exit 0'
|
||||
|
||||
generated_compose_path="${stack_dir}/compose.generated.yaml"
|
||||
docker_log="${EASY_DOCKER_TEST_TMPDIR}/docker.log"
|
||||
|
||||
run render_stack_compose_from_metadata "${stack_dir}"
|
||||
[ "${status}" -eq 1 ]
|
||||
[ ! -f "${generated_compose_path}" ]
|
||||
[ ! -f "${generated_compose_path}.tmp" ]
|
||||
[ -f "${docker_log}" ]
|
||||
[ "$(cat "${docker_log}")" != "" ]
|
||||
}
|
||||
147
tests/easy-docker/test_helper.bash
Executable file
147
tests/easy-docker/test_helper.bash
Executable file
|
|
@ -0,0 +1,147 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
easy_docker_test_repo_root() {
|
||||
local helper_dir=""
|
||||
|
||||
helper_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
(cd "${helper_dir}/../.." && pwd)
|
||||
}
|
||||
|
||||
easy_docker_test_begin() {
|
||||
EASY_DOCKER_TEST_TMPDIR="$(mktemp -d)"
|
||||
export EASY_DOCKER_TEST_TMPDIR
|
||||
unset EASY_DOCKER_REPO_ROOT_OVERRIDE
|
||||
}
|
||||
|
||||
easy_docker_test_end() {
|
||||
if [ -n "${EASY_DOCKER_TEST_TMPDIR:-}" ] && [ -d "${EASY_DOCKER_TEST_TMPDIR}" ]; then
|
||||
rm -rf "${EASY_DOCKER_TEST_TMPDIR}"
|
||||
fi
|
||||
}
|
||||
|
||||
easy_docker_test_bin_dir() {
|
||||
printf '%s/bin\n' "${EASY_DOCKER_TEST_TMPDIR}"
|
||||
}
|
||||
|
||||
easy_docker_test_write_executable() {
|
||||
local target_path="${1}"
|
||||
local system_bash=""
|
||||
shift
|
||||
|
||||
system_bash="$(command -v bash)"
|
||||
mkdir -p "$(dirname "${target_path}")"
|
||||
|
||||
{
|
||||
printf '#!%s\n' "${system_bash}"
|
||||
printf '%s\n' "$@"
|
||||
} >"${target_path}"
|
||||
chmod +x "${target_path}"
|
||||
}
|
||||
|
||||
easy_docker_test_write_bin_command() {
|
||||
local command_name="${1}"
|
||||
local target_path=""
|
||||
shift
|
||||
|
||||
target_path="$(easy_docker_test_bin_dir)/${command_name}"
|
||||
easy_docker_test_write_executable "${target_path}" "$@"
|
||||
}
|
||||
|
||||
easy_docker_test_prepend_bin_dir() {
|
||||
PATH="$(easy_docker_test_bin_dir):${PATH}"
|
||||
export PATH
|
||||
}
|
||||
|
||||
easy_docker_test_source_common_modules() {
|
||||
local repo_root=""
|
||||
|
||||
repo_root="$(easy_docker_test_repo_root)"
|
||||
|
||||
# shellcheck source=scripts/easy-docker/lib/core/commands.sh
|
||||
source "${repo_root}/scripts/easy-docker/lib/core/commands.sh"
|
||||
# shellcheck source=scripts/easy-docker/lib/core/messages.sh
|
||||
source "${repo_root}/scripts/easy-docker/lib/core/messages.sh"
|
||||
}
|
||||
|
||||
easy_docker_test_source_core_render_modules() {
|
||||
local repo_root=""
|
||||
|
||||
repo_root="$(easy_docker_test_repo_root)"
|
||||
|
||||
easy_docker_test_source_common_modules
|
||||
|
||||
# shellcheck source=scripts/easy-docker/lib/app/wizard/common/core.sh
|
||||
source "${repo_root}/scripts/easy-docker/lib/app/wizard/common/core.sh"
|
||||
# shellcheck source=scripts/easy-docker/lib/app/wizard/common/compose/render.sh
|
||||
source "${repo_root}/scripts/easy-docker/lib/app/wizard/common/compose/render.sh"
|
||||
}
|
||||
|
||||
easy_docker_test_source_docker_modules() {
|
||||
local repo_root=""
|
||||
|
||||
repo_root="$(easy_docker_test_repo_root)"
|
||||
|
||||
easy_docker_test_source_common_modules
|
||||
|
||||
# shellcheck source=scripts/easy-docker/lib/checks/docker.sh
|
||||
source "${repo_root}/scripts/easy-docker/lib/checks/docker.sh"
|
||||
}
|
||||
|
||||
easy_docker_test_source_gum_modules() {
|
||||
local repo_root=""
|
||||
|
||||
repo_root="$(easy_docker_test_repo_root)"
|
||||
|
||||
easy_docker_test_source_common_modules
|
||||
|
||||
# shellcheck source=scripts/easy-docker/lib/install/gum/package_manager.sh
|
||||
source "${repo_root}/scripts/easy-docker/lib/install/gum/package_manager.sh"
|
||||
# shellcheck source=scripts/easy-docker/lib/install/gum/github_release.sh
|
||||
source "${repo_root}/scripts/easy-docker/lib/install/gum/github_release.sh"
|
||||
# shellcheck source=scripts/easy-docker/lib/install/gum/ensure.sh
|
||||
source "${repo_root}/scripts/easy-docker/lib/install/gum/ensure.sh"
|
||||
}
|
||||
|
||||
easy_docker_test_create_repo_sandbox() {
|
||||
local sandbox_name="${1}"
|
||||
local sandbox_root=""
|
||||
|
||||
sandbox_root="${EASY_DOCKER_TEST_TMPDIR}/repo-${sandbox_name}"
|
||||
mkdir -p "${sandbox_root}/.easy-docker/stacks" "${sandbox_root}/overrides"
|
||||
printf '%s\n' "${sandbox_root}"
|
||||
}
|
||||
|
||||
easy_docker_test_override_repo_root() {
|
||||
EASY_DOCKER_REPO_ROOT_OVERRIDE="${1}"
|
||||
export EASY_DOCKER_REPO_ROOT_OVERRIDE
|
||||
}
|
||||
|
||||
easy_docker_test_stack_dir() {
|
||||
local stack_name="${1}"
|
||||
|
||||
printf '%s/.easy-docker/stacks/%s\n' "${EASY_DOCKER_REPO_ROOT_OVERRIDE}" "${stack_name}"
|
||||
}
|
||||
|
||||
easy_docker_test_install_docker_stub() {
|
||||
local log_file=""
|
||||
|
||||
log_file="${EASY_DOCKER_TEST_TMPDIR}/docker.invocations"
|
||||
|
||||
# shellcheck disable=SC2016
|
||||
easy_docker_test_write_bin_command docker \
|
||||
'set -euo pipefail' \
|
||||
"log_file=\"${log_file}\"" \
|
||||
'printf '"'"'%s\n'"'"' "docker $*" >>"${log_file}"' \
|
||||
'if [ "${1:-}" != "compose" ]; then' \
|
||||
' echo "unexpected docker subcommand: ${1:-}" >&2' \
|
||||
' exit 64' \
|
||||
'fi' \
|
||||
'if [ "${!#}" != "config" ]; then' \
|
||||
' echo "expected docker compose config invocation" >&2' \
|
||||
' exit 65' \
|
||||
'fi' \
|
||||
'printf '"'"'invocation=%s\n'"'"' "docker $*"' \
|
||||
'printf '"'"'erpnext=%s\n'"'"' "${ERPNEXT_VERSION:-}"'
|
||||
|
||||
easy_docker_test_prepend_bin_dir
|
||||
}
|
||||
Loading…
Reference in a new issue