diff --git a/cli/bash/commands/basectl/basectl.sh b/cli/bash/commands/basectl/basectl.sh index 64cc93da..5b5189bc 100644 --- a/cli/bash/commands/basectl/basectl.sh +++ b/cli/bash/commands/basectl/basectl.sh @@ -539,6 +539,9 @@ basectl_args_request_help() { continue fi case "$argument" in + --) + return 1 + ;; --manifest|--format|--repos|--profile|--environment|--config|--log-file|--project|--workspace|--path|--target|--version|--command|--status|--older-than|--keep-last|--since|--until|--last|--lines) expect_value=1 ;; diff --git a/cli/bash/commands/basectl/subcommands/build.sh b/cli/bash/commands/basectl/subcommands/build.sh index c94e0f2d..dac94766 100644 --- a/cli/bash/commands/basectl/subcommands/build.sh +++ b/cli/bash/commands/basectl/subcommands/build.sh @@ -85,7 +85,6 @@ base_build_run_target_record() { base_project_set_history_context "$resolved_name" "$project_root" "$manifest_path" command_to_run="$(base_command_with_runner "$command_runner" "$build_command" "" "${extra_args[@]}")" || return $? - command_to_run="$(base_command_with_mise_config "$mise_config_path" "$command_to_run")" || return $? display_command="$(base_display_command_with_runner "$command_runner" "$build_command" "" "${extra_args[@]}")" || return $? display_command="$(base_command_with_mise_config "$mise_config_path" "$display_command")" || return $? @@ -104,7 +103,7 @@ base_build_run_target_record() { base_std_log_info "Building target '$target_name' for project '$resolved_name': $display_command" base_validate_command_runner "$command_runner" - base_project_run_shell_command "$working_dir" "$command_to_run" basectl-build "${extra_args[@]}" + base_project_run_shell_command "$working_dir" "$command_to_run" basectl-build "$mise_config_path" "${extra_args[@]}" } base_build_list_targets() { diff --git a/cli/bash/commands/basectl/subcommands/demo.sh b/cli/bash/commands/basectl/subcommands/demo.sh index 6e3f3e0f..7920e4af 100644 --- a/cli/bash/commands/basectl/subcommands/demo.sh +++ b/cli/bash/commands/basectl/subcommands/demo.sh @@ -62,7 +62,6 @@ base_demo_subcommand_main() { command_runner="${command_runner:-}" printf -v quoted_demo_script '%q' "$demo_script" command_to_run="$(base_command_with_runner "$command_runner" "$quoted_demo_script" "" "${extra_args[@]}")" || return $? - command_to_run="$(base_command_with_mise_config "$mise_config_path" "$command_to_run")" || return $? display_command="$(base_display_command_with_runner "$command_runner" "$quoted_demo_script" "" "${extra_args[@]}")" || return $? display_command="$(base_command_with_mise_config "$mise_config_path" "$display_command")" || return $? @@ -82,5 +81,5 @@ base_demo_subcommand_main() { return $? fi base_validate_command_runner "$command_runner" - base_project_run_shell_command "$project_root" "$command_to_run" basectl-demo "${extra_args[@]}" + base_project_run_shell_command "$project_root" "$command_to_run" basectl-demo "$mise_config_path" "${extra_args[@]}" } diff --git a/cli/bash/commands/basectl/subcommands/project_command_helpers.sh b/cli/bash/commands/basectl/subcommands/project_command_helpers.sh index 2d87d98d..050c53b2 100644 --- a/cli/bash/commands/basectl/subcommands/project_command_helpers.sh +++ b/cli/bash/commands/basectl/subcommands/project_command_helpers.sh @@ -389,7 +389,8 @@ base_project_run_shell_command() { local working_dir="$1" local command_to_run="$2" local command_name="$3" - shift 3 + local mise_config_path="${4:-}" + shift 4 # Bash assigns the word after `bash -c ` to `$0`; use a stable # sentinel so delegated extra args start at `$1` and populate `$@`. @@ -408,6 +409,10 @@ base_project_run_shell_command() { PATH="${PATH:+$PATH:}$HOME/.local/bin" export PATH fi + if [[ -n "$mise_config_path" ]]; then + export MISE_CONFIG_FILE="$mise_config_path" + export MISE_OVERRIDE_CONFIG_FILENAMES="$mise_config_path" + fi cd "$working_dir" && bash -c "$command_to_run" "$command_name" "$@" ) } diff --git a/cli/bash/commands/basectl/subcommands/run.sh b/cli/bash/commands/basectl/subcommands/run.sh index 2bf3a667..a7744e3b 100644 --- a/cli/bash/commands/basectl/subcommands/run.sh +++ b/cli/bash/commands/basectl/subcommands/run.sh @@ -262,7 +262,6 @@ base_run_subcommand_main() { command_runner="${command_runner:-}" command_to_run="$(base_command_with_runner "$command_runner" "$run_command" "$uv_extras" "${extra_args[@]}")" || return $? - command_to_run="$(base_command_with_mise_config "$mise_config_path" "$command_to_run")" || return $? display_command="$(base_display_command_with_runner "$command_runner" "$run_command" "$uv_extras" "${extra_args[@]}")" || return $? display_command="$(base_command_with_mise_config "$mise_config_path" "$display_command")" || return $? @@ -278,5 +277,5 @@ base_run_subcommand_main() { base_std_log_info "Running command '$command_name' for project '$resolved_name': $display_command" base_validate_command_runner "$command_runner" - base_project_run_shell_command "$project_root" "$command_to_run" basectl-run "${extra_args[@]}" + base_project_run_shell_command "$project_root" "$command_to_run" basectl-run "$mise_config_path" "${extra_args[@]}" } diff --git a/cli/bash/commands/basectl/subcommands/test.sh b/cli/bash/commands/basectl/subcommands/test.sh index d50edd9c..2ac7d3c4 100644 --- a/cli/bash/commands/basectl/subcommands/test.sh +++ b/cli/bash/commands/basectl/subcommands/test.sh @@ -63,7 +63,6 @@ base_test_subcommand_main() { command_runner="${command_runner:-}" command_to_run="$(base_command_with_runner "$command_runner" "$test_command" "$uv_extras" "${extra_args[@]}")" || return $? - command_to_run="$(base_command_with_mise_config "$mise_config_path" "$command_to_run")" || return $? display_command="$(base_display_command_with_runner "$command_runner" "$test_command" "$uv_extras" "${extra_args[@]}")" || return $? display_command="$(base_command_with_mise_config "$mise_config_path" "$display_command")" || return $? @@ -86,12 +85,11 @@ base_test_subcommand_main() { uv_extras="${BASE_COMMAND_PROTOCOL_FIELDS[uv_extras]:-}" command_runner="${command_runner:-}" command_to_run="$(base_command_with_runner "$command_runner" "$test_command" "$uv_extras" "${extra_args[@]}")" || return $? - command_to_run="$(base_command_with_mise_config "$mise_config_path" "$command_to_run")" || return $? base_project_activate_environment \ "$resolved_name" "$project_root" "$manifest_path" "$dry_run" "$route_venv_dir" "$uses_uv_manager" >/dev/null base_std_log_info "Running tests for project '$resolved_name': $display_command" base_validate_command_runner "$command_runner" - base_project_run_shell_command "$project_root" "$command_to_run" basectl-test "${extra_args[@]}" + base_project_run_shell_command "$project_root" "$command_to_run" basectl-test "$mise_config_path" "${extra_args[@]}" } diff --git a/cli/bash/commands/basectl/tests/project-command-helpers.bats b/cli/bash/commands/basectl/tests/project-command-helpers.bats index 823c3ac3..9a8dfbc4 100644 --- a/cli/bash/commands/basectl/tests/project-command-helpers.bats +++ b/cli/bash/commands/basectl/tests/project-command-helpers.bats @@ -356,6 +356,7 @@ manifest=$project_root/base_manifest.yaml" ] "$working_dir" \ 'printf "pwd=%s\n" "$PWD"; printf "sentinel=%s\n" "$0"; printf "args=<%s><%s>\n" "$1" "$2"' \ basectl-test \ + "" \ "one word" \ two @@ -365,6 +366,26 @@ manifest=$project_root/base_manifest.yaml" ] [[ "$output" == *"args="* ]] } +@test "project command helper binds mise config around compound shell commands" { + source_project_command_helpers + + local working_dir="$TEST_TMPDIR/project" + local mise_config="$working_dir/.mise.toml" + mkdir -p "$working_dir" + touch "$mise_config" + + run base_project_run_shell_command \ + "$working_dir" \ + 'if [[ "$MISE_CONFIG_FILE" == "$1" ]]; then printf "config=%s\n" "$MISE_CONFIG_FILE"; else exit 1; fi; true && printf "override=%s\n" "$MISE_OVERRIDE_CONFIG_FILENAMES"' \ + basectl-test \ + "$mise_config" \ + "$mise_config" + + [ "$status" -eq 0 ] + [[ "$output" == *"config=$mise_config"* ]] + [[ "$output" == *"override=$mise_config"* ]] +} + @test "project command helper wraps uv runner commands" { source_project_command_helpers diff --git a/cli/bash/commands/basectl/tests/runtime-dispatch.bats b/cli/bash/commands/basectl/tests/runtime-dispatch.bats index f44aef92..53f16999 100644 --- a/cli/bash/commands/basectl/tests/runtime-dispatch.bats +++ b/cli/bash/commands/basectl/tests/runtime-dispatch.bats @@ -641,6 +641,24 @@ EOF [[ "$output" != *"basectl $(head -n 1 "$BASE_REPO_ROOT/VERSION")"* ]] } +@test "basectl preserves literal help after the passthrough delimiter" { + run env \ + BASE_HOME="$BASE_REPO_ROOT" \ + bash -c ' + source "$BASE_HOME/cli/bash/commands/basectl/basectl.sh" + base_std_log_debug() { :; } + basectl_get_base_home() { :; } + basectl_initialize_run_bundle() { :; } + basectl_finalize_run_bundle() { :; } + basectl_history_record() { :; } + basectl_do_test() { printf "test-args=%s\\n" "$*"; } + basectl_main test -- help + ' + + [ "$status" -eq 0 ] + [ "$output" = "test-args=-- help" ] +} + @test "README version badge matches VERSION" { local expected_version expected_badge diff --git a/lib/shell/completions/tests/completions.bats b/lib/shell/completions/tests/completions.bats index 2f168955..7ef2ac1d 100644 --- a/lib/shell/completions/tests/completions.bats +++ b/lib/shell/completions/tests/completions.bats @@ -5,6 +5,9 @@ bats_require_minimum_version 1.5.0 setup() { setup_test_tmpdir + export HOME="$TEST_TMPDIR/home" + export BASE_CACHE_DIR="$TEST_TMPDIR/base-cache" + mkdir -p "$HOME" "$BASE_CACHE_DIR" } basectl_help_commands() { @@ -234,16 +237,38 @@ for line in Path(sys.argv[1]).read_text(encoding="utf-8").splitlines(): continue tokens = command.split()[1:] path = [] - for token in tokens: - if token.startswith(("<", "[")): - break + index = 0 + while index < len(tokens): + token = tokens[index] if token == "--ci": + index += 1 continue + if token.startswith("[") or token.startswith("<"): + break path.append(token) + if token.startswith("--") and index + 1 < len(tokens) and tokens[index + 1].startswith("<"): + value_name = tokens[index + 1][1:-1].lower() + if "version" in value_name: + path.append("1.8.0") + elif "number" in value_name or value_name.endswith("-id") or value_name == "id": + path.append("1") + else: + path.append("example") + index += 1 + index += 1 print(" ".join(path)) PY } +@test "documented public leaves provide values for required selector options" { + run documented_public_leaves + + [ "$status" -eq 0 ] + [[ "$output" == *$'release check --version 1.8.0\n'* ]] + [[ "$output" == *$'release plan --version 1.8.0\n'* ]] + [[ "$output" != *$'release check --version\n'* ]] +} + @test "documented public leaves drive completion option parity" { local path # GitHub pass-through leaves have no Base-owned option contract. Workspace