diff --git a/cli/bash/commands/basectl/subcommands/setup_common.sh b/cli/bash/commands/basectl/subcommands/setup_common.sh index 8dc46e8..741ff10 100644 --- a/cli/bash/commands/basectl/subcommands/setup_common.sh +++ b/cli/bash/commands/basectl/subcommands/setup_common.sh @@ -2069,7 +2069,9 @@ setup_run_check_json() { if setup_profiles_enabled; then if ! profile_json="$(setup_run_base_dev_layer check --format json)"; then - [[ -n "$profile_json" ]] || profile_json='{"schema_version":1,"status":"error","profiles":[],"checks":[]}' + if [[ -z "$profile_json" ]]; then + return 1 + fi fi profile_status="$(setup_json_payload_status "$profile_json")" status="$(setup_merge_diagnostic_status "$status" "$profile_status")" @@ -2077,7 +2079,9 @@ setup_run_check_json() { if [[ -n "$project" ]]; then if ! project_json="$(setup_run_project_artifact_check_json "$remote_network")"; then - [[ -n "$project_json" ]] || project_json='{"schema_version":1,"status":"error","checks":[]}' + if [[ -z "$project_json" ]]; then + return 1 + fi fi project_status="$(setup_json_payload_status "$project_json")" status="$(setup_merge_diagnostic_status "$status" "$project_status")" diff --git a/cli/bash/commands/basectl/tests/check.bats b/cli/bash/commands/basectl/tests/check.bats index 9cc646e..73929ac 100644 --- a/cli/bash/commands/basectl/tests/check.bats +++ b/cli/bash/commands/basectl/tests/check.bats @@ -524,6 +524,33 @@ load ./setup_helpers.bash [ "${stderr:-}" = "" ] } +@test "basectl check project --format json fails fast on runtime directory errors" { + local venv_dir="$TEST_HOME/.base.d/base/.venv" + local workspace="$TEST_TMPDIR/workspace" + + create_brew_stub + create_xcode_stubs + touch "$TEST_STATE_DIR/xcode-installed" + mkdir -p "$TEST_TMPDIR/CommandLineTools" "$workspace/demo" + touch "$TEST_STATE_DIR/python-installed" + touch "$TEST_STATE_DIR/bats-installed" + touch "$TEST_STATE_DIR/pyyaml-installed" + touch "$TEST_STATE_DIR/click-installed" + printf 'project:\n name: demo\nartifacts: []\n' > "$workspace/demo/base_manifest.yaml" + BASE_SETUP_TEST_WORKSPACE="$workspace" create_project_setup_venv_stub "$venv_dir" + BASE_SETUP_TEST_WORKSPACE="$workspace" create_project_setup_venv_stub "$TEST_HOME/.base.d/demo/.venv" 1 + touch "$TEST_STATE_DIR/project-setup-fail-before-output" + printf "Error: Unable to create Base runtime directory '%s'.\n" "$TEST_TMPDIR/unwritable-cache/cli/base_setup/logs" > "$TEST_STATE_DIR/project-setup-stderr" + + run_base_command_separate_stderr BASE_SETUP_TEST_WORKSPACE="$workspace" check demo --format json + + [ "$status" -eq 1 ] + [ "$output" = "" ] + [[ "$stderr" == *"Error: Unable to create Base runtime directory"* ]] + [[ "$stderr" != *'"project_checks"'* ]] + [[ "$stderr" != *"Project artifact check passed."* ]] +} + @test "basectl check project --format json reports broken project virtualenv integrity" { local missing_home="$TEST_TMPDIR/missing-project-python-home" local venv_dir="$TEST_HOME/.base.d/base/.venv" diff --git a/cli/bash/commands/basectl/tests/setup_helpers.bash b/cli/bash/commands/basectl/tests/setup_helpers.bash index 71ed50e..93c5609 100644 --- a/cli/bash/commands/basectl/tests/setup_helpers.bash +++ b/cli/bash/commands/basectl/tests/setup_helpers.bash @@ -559,6 +559,12 @@ if [[ "${1:-}" == "-m" && "${2:-}" == "base_setup" ]]; then if [[ "$action" == "bootstrap" ]]; then printf '%s\n' "${BASE_SETUP_RECREATE_PROJECT_VENV:-}" > "$BASE_SETUP_TEST_STATE_DIR/project-bootstrap-recreate-venv" fi + if [[ -f "$BASE_SETUP_TEST_STATE_DIR/project-setup-fail-before-output" ]]; then + if [[ -f "$BASE_SETUP_TEST_STATE_DIR/project-setup-stderr" ]]; then + cat "$BASE_SETUP_TEST_STATE_DIR/project-setup-stderr" >&2 + fi + exit "$(cat "$BASE_SETUP_TEST_STATE_DIR/project-setup-exit-code")" + fi if [[ "$action" == "precheck" && "$output_format" == "json" ]]; then if [[ "$remote_network" == true ]]; then printf '[{"id":"BASE-P080","status":"ok","name":"git_repository","message":"Project is inside a Git repository.","fix":""},{"id":"BASE-P083","status":"ok","name":"git_origin_reachability","message":"Project Git origin remote is reachable.","fix":""}]\n'