Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ and Base versions are tracked in the repo-root `VERSION` file.

### Added

- Added opt-in project Git `origin` reachability diagnostics with
`basectl check|doctor <project> --remote-network`.
- Added an explicit `ai` prerequisite profile for Codex CLI and Claude Code
setup, check, doctor, onboard, and shell completion flows.

Expand Down
9 changes: 8 additions & 1 deletion cli/bash/commands/basectl/subcommands/check.sh
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ Options:
--profile <list> Include named prerequisite profiles. Known profiles: dev, sre, ai.
--format <text|json> Select output format. Defaults to text.
--manifest <path> Use a specific base_manifest.yaml path for project checks.
--remote-network Opt in to bounded project Git origin reachability checks.
-v Enable DEBUG logging for this subcommand.
-h, --help Show this help text.

Expand All @@ -36,6 +37,7 @@ EOF
base_check_subcommand_main() {
local output_format="text"
local project=""
local remote_network=false

setup_clear_run_state

Expand Down Expand Up @@ -86,6 +88,9 @@ base_check_subcommand_main() {
BASE_SETUP_MANIFEST="$1"
export BASE_SETUP_MANIFEST
;;
--remote-network)
remote_network=true
;;
-v)
setup_enable_debug_logging
;;
Expand All @@ -107,10 +112,12 @@ base_check_subcommand_main() {
done

BASE_SETUP_PROJECT_NAME="$project"
BASE_SETUP_REMOTE_NETWORK="$remote_network"
export BASE_SETUP_PROJECT_NAME
export BASE_SETUP_REMOTE_NETWORK
log_debug "Running 'basectl check'."
if [[ "$output_format" == json ]]; then
setup_run_check_json
setup_run_check_json "$remote_network"
else
setup_run_check
fi
Expand Down
14 changes: 11 additions & 3 deletions cli/bash/commands/basectl/subcommands/doctor.sh
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ Options:
--profile <list> Include named prerequisite profiles. Known profiles: dev, sre, ai.
--format <text|json> Select output format. Defaults to text.
--manifest <path> Use a specific base_manifest.yaml path for project diagnostics.
--remote-network Opt in to bounded project Git origin reachability diagnostics.
-v Enable DEBUG logging for this subcommand.
-h, --help Show this help text.

Expand Down Expand Up @@ -259,6 +260,7 @@ base_doctor_run_json() {
local errors=0 profile_errors=0 profile_json="[]"
local project="$1"
local project_errors=0 project_json="[]"
local remote_network="${2:-${BASE_SETUP_REMOTE_NETWORK:-}}"
local status="ok"

setup_collect_base_check_results warn || true
Expand All @@ -277,7 +279,7 @@ base_doctor_run_json() {
fi

if [[ -n "$project" ]]; then
if project_json="$(setup_run_project_artifact_doctor_json)"; then
if project_json="$(setup_run_project_artifact_doctor_json "$remote_network")"; then
project_errors=0
else
project_errors=$?
Expand Down Expand Up @@ -321,6 +323,7 @@ base_doctor_run_json() {

base_doctor_subcommand_main() {
local errors=0 output_format="text" profile_errors=0 project=""
local remote_network=false

setup_clear_run_state

Expand Down Expand Up @@ -371,6 +374,9 @@ base_doctor_subcommand_main() {
BASE_SETUP_MANIFEST="$1"
export BASE_SETUP_MANIFEST
;;
--remote-network)
remote_network=true
;;
-v)
setup_enable_debug_logging
;;
Expand All @@ -392,11 +398,13 @@ base_doctor_subcommand_main() {
done

BASE_SETUP_PROJECT_NAME="$project"
BASE_SETUP_REMOTE_NETWORK="$remote_network"
export BASE_SETUP_PROJECT_NAME
export BASE_SETUP_REMOTE_NETWORK
log_debug "Running 'basectl doctor'."
if setup_ci_runtime_only; then
if [[ "$output_format" == json ]]; then
base_doctor_run_json "$project"
base_doctor_run_json "$project" "$remote_network"
else
base_doctor_run_ci_runtime_text "$project"
fi
Expand All @@ -406,7 +414,7 @@ base_doctor_subcommand_main() {
setup_require_macos

if [[ "$output_format" == json ]]; then
base_doctor_run_json "$project"
base_doctor_run_json "$project" "$remote_network"
return $?
fi

Expand Down
32 changes: 25 additions & 7 deletions cli/bash/commands/basectl/subcommands/setup_common.sh
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ setup_ensure_cached_paths() {
setup_clear_run_state() {
# Clear legacy lowercase state too so inherited environments cannot trigger
# lib_std.sh dry-run behavior unless this command explicitly enables it.
unset dry_run DRY_RUN BASE_SETUP_PROFILE_ERROR BASE_SETUP_PROFILES BASE_SETUP_PROJECT_NAME BASE_SETUP_MANIFEST BASE_SETUP_RECREATE_VENV BASE_PROJECT
unset dry_run DRY_RUN BASE_SETUP_PROFILE_ERROR BASE_SETUP_PROFILES BASE_SETUP_PROJECT_NAME BASE_SETUP_MANIFEST BASE_SETUP_REMOTE_NETWORK BASE_SETUP_RECREATE_VENV BASE_PROJECT
setup_refresh_cached_paths
}

Expand Down Expand Up @@ -861,6 +861,7 @@ setup_run_project_pre_venv_layer() {
local output_format="$2"
local manifest_path="$3"
local project="$4"
local remote_network="${5:-${BASE_SETUP_REMOTE_NETWORK:-}}"
local python_bin venv_dir
local args=()

Expand All @@ -871,6 +872,9 @@ setup_run_project_pre_venv_layer() {
args+=(--manifest "$manifest_path")
args+=(--action "$action")
args+=(--format "$output_format")
if [[ "$remote_network" == true ]]; then
args+=(--remote-network)
fi
args+=("$project")

env BASE_HOME="$BASE_HOME" BASE_PROJECT="$project" PYTHONPATH="$_BASE_SETUP_PYTHONPATH_CACHE" "$python_bin" -m base_setup "${args[@]}"
Expand Down Expand Up @@ -912,7 +916,7 @@ setup_run_project_bootstrap_layer() {
setup_run_project_artifact_layer() {
local action="$1"
local output_format="$2"
local exit_code manifest_path precheck_json project project_venv_dir python_bin resolved_name resolved_root resolve_output venv_dir
local exit_code manifest_path precheck_json project project_venv_dir python_bin remote_network resolved_name resolved_root resolve_output venv_dir
local args=()

if setup_is_dry_run && ! setup_base_python_package_installed "$(setup_pyyaml_package)"; then
Expand Down Expand Up @@ -954,6 +958,11 @@ setup_run_project_artifact_layer() {
if [[ "$action" == check || "$action" == doctor ]]; then
args+=(--format "$output_format")
fi
remote_network=false
if [[ "${BASE_SETUP_REMOTE_NETWORK:-}" == true && ( "$action" == check || "$action" == doctor ) ]]; then
args+=(--remote-network)
remote_network=true
fi
args+=("$project")

if [[ "$output_format" != json ]]; then
Expand Down Expand Up @@ -982,15 +991,15 @@ setup_run_project_artifact_layer() {
fi
if [[ "$output_format" == json ]]; then
if [[ "$action" == doctor ]]; then
precheck_json="$(setup_run_project_pre_venv_layer predoctor json "$manifest_path" "$project")" || true
precheck_json="$(setup_run_project_pre_venv_layer predoctor json "$manifest_path" "$project" "$remote_network")" || true
[[ -n "$precheck_json" ]] || precheck_json="[]"
setup_print_project_venv_doctor_json \
"$precheck_json" \
"error" \
"$_BASE_SETUP_VENV_HEALTH_MESSAGE" \
"$(setup_recovery_project_venv "$project")"
else
precheck_json="$(setup_run_project_pre_venv_layer precheck json "$manifest_path" "$project")" || true
precheck_json="$(setup_run_project_pre_venv_layer precheck json "$manifest_path" "$project" "$remote_network")" || true
[[ -n "$precheck_json" ]] || precheck_json="[]"
setup_print_project_check_json_with_venv \
"$precheck_json" \
Expand All @@ -1000,11 +1009,11 @@ setup_run_project_artifact_layer() {
"$project"
fi
elif [[ "$action" == doctor ]]; then
setup_run_project_pre_venv_layer predoctor text "$manifest_path" "$project" || true
setup_run_project_pre_venv_layer predoctor text "$manifest_path" "$project" "$remote_network" || true
printf 'error %-9s %-26s %s\n' "BASE-P050" "Project virtualenv" "$_BASE_SETUP_VENV_HEALTH_MESSAGE"
printf ' Fix: %s\n' "$(setup_recovery_project_venv "$project")"
elif [[ "$action" == check ]]; then
setup_run_project_pre_venv_layer precheck text "$manifest_path" "$project" || true
setup_run_project_pre_venv_layer precheck text "$manifest_path" "$project" "$remote_network" || true
log_warn "$_BASE_SETUP_VENV_HEALTH_MESSAGE"
log_warn "$(setup_recovery_project_venv "$project")"
else
Expand Down Expand Up @@ -1036,6 +1045,10 @@ setup_run_project_artifact_check() {
}

setup_run_project_artifact_check_json() {
if [[ -n "${1:-}" ]]; then
BASE_SETUP_REMOTE_NETWORK="$1"
export BASE_SETUP_REMOTE_NETWORK
fi
setup_run_project_artifact_layer check json
}

Expand All @@ -1044,6 +1057,10 @@ setup_run_project_artifact_doctor() {
}

setup_run_project_artifact_doctor_json() {
if [[ -n "${1:-}" ]]; then
BASE_SETUP_REMOTE_NETWORK="$1"
export BASE_SETUP_REMOTE_NETWORK
fi
setup_run_project_artifact_layer doctor json
}

Expand Down Expand Up @@ -1655,6 +1672,7 @@ setup_run_check_json() {
local project="${BASE_SETUP_PROJECT_NAME:-}"
local project_json=""
local project_status="ok"
local remote_network="${1:-${BASE_SETUP_REMOTE_NETWORK:-}}"
local status

setup_collect_base_check_results warn || true
Expand All @@ -1669,7 +1687,7 @@ setup_run_check_json() {
fi

if [[ -n "$project" ]]; then
if ! project_json="$(setup_run_project_artifact_check_json)"; then
if ! project_json="$(setup_run_project_artifact_check_json "$remote_network")"; then
[[ -n "$project_json" ]] || project_json='{"schema_version":1,"status":"error","checks":[]}'
fi
project_status="$(setup_json_payload_status "$project_json")"
Expand Down
27 changes: 25 additions & 2 deletions cli/bash/commands/basectl/tests/check.bats
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ load ./setup_helpers.bash
[[ "$output" == *"basectl check [project] [options]"* ]]
[[ "$output" != *"--dev"* ]]
[[ "$output" == *"--profile <list>"* ]]
[[ "$output" == *"--remote-network"* ]]
[[ "$output" == *"Verify the local Base CLI environment and, when provided, project artifacts on macOS without making changes."* ]]
}

Expand Down Expand Up @@ -221,6 +222,27 @@ load ./setup_helpers.bash
[ "$(cat "$TEST_STATE_DIR/project-setup-args")" = "$(printf '%s\n' --manifest "$workspace/demo/base_manifest.yaml" --action check --format text demo)" ]
}

@test "basectl check project passes opt-in remote network diagnostics flag" {
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/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"

run_base_command BASE_SETUP_TEST_WORKSPACE="$workspace" check demo --remote-network

[ "$status" -eq 0 ]
[ "$(cat "$TEST_STATE_DIR/project-setup-args")" = "$(printf '%s\n' --manifest "$workspace/demo/base_manifest.yaml" --action check --format text --remote-network demo)" ]
}

@test "basectl check --format json writes successful check results to stdout" {
local click_line
local pyyaml_line
Expand Down Expand Up @@ -402,7 +424,7 @@ load ./setup_helpers.bash
BASE_SETUP_TEST_PYTHON_PREFIX="$TEST_TMPDIR/python-prefix" \
BASE_SETUP_TEST_WORKSPACE="$workspace" \
BASE_SETUP_XCODE_COMMAND_LINE_TOOLS_DIR="$TEST_TMPDIR/CommandLineTools" \
"$BASE_REPO_ROOT/bin/basectl" check demo --format json
"$BASE_REPO_ROOT/bin/basectl" check demo --remote-network --format json

[ "$status" -eq 0 ]
[[ "$output" == *'"schema_version": 1'* ]]
Expand Down Expand Up @@ -443,14 +465,15 @@ load ./setup_helpers.bash
BASE_SETUP_TEST_PYTHON_PREFIX="$TEST_TMPDIR/python-prefix" \
BASE_SETUP_TEST_WORKSPACE="$workspace" \
BASE_SETUP_XCODE_COMMAND_LINE_TOOLS_DIR="$TEST_TMPDIR/CommandLineTools" \
"$BASE_REPO_ROOT/bin/basectl" check demo --format json
"$BASE_REPO_ROOT/bin/basectl" check demo --remote-network --format json

[ "$status" -eq 1 ]
[[ "$output" == *'"schema_version": 1'* ]]
[[ "$output" == *'"status": "error"'* ]]
[[ "$output" == *'"project": "demo"'* ]]
[[ "$output" == *'"project_checks":'* ]]
[[ "$output" == *'"id":"BASE-P080","status":"ok","name":"git_repository"'* ]]
[[ "$output" == *'"id":"BASE-P083","status":"ok","name":"git_origin_reachability"'* ]]
[[ "$output" == *'"id":"BASE-P050","status":"error","name":"project_virtualenv"'* ]]
[[ "$output" != *'"ok":'* ]]
[[ "$output" == *"Virtual environment Python is broken because home path '$missing_home' no longer provides Python."* ]]
Expand Down
Loading
Loading