minitest-cli 0.33.0__tar.gz → 0.35.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/PKG-INFO +59 -9
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/README.md +58 -8
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/pyproject.toml +1 -1
- minitest_cli-0.35.0/src/minitest_cli/commands/app_network_helpers.py +114 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/app_skill.py +1 -1
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/apps.py +11 -20
- minitest_cli-0.35.0/src/minitest_cli/commands/apps_table.py +28 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/batch.py +24 -17
- minitest_cli-0.35.0/src/minitest_cli/commands/deprecated_alias.py +57 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/draft_feature.py +10 -6
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/draft_feature_apply.py +1 -1
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/draft_feature_conflicts.py +1 -1
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/draft_feature_helpers.py +3 -1
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/draft_feature_show.py +1 -1
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/issues.py +9 -7
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/issues_fix.py +1 -1
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/maintenance.py +2 -2
- minitest_cli-0.35.0/src/minitest_cli/commands/private_network.py +143 -0
- minitest_cli-0.35.0/src/minitest_cli/commands/private_network_helpers.py +93 -0
- minitest_cli-0.35.0/src/minitest_cli/commands/residential_proxy.py +121 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/run.py +7 -5
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/run_cancel.py +12 -5
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/run_commit.py +15 -7
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/run_recording.py +6 -1
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/run_recording_helpers.py +5 -3
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/skill.py +4 -1
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/test_profile.py +3 -1
- minitest_cli-0.35.0/src/minitest_cli/commands/user_story_app_skills.py +51 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/user_story_bindings.py +7 -38
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/verdicts.py +2 -2
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/main.py +1 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/models/app.py +7 -0
- minitest_cli-0.35.0/tests/_network_settings_server.py +106 -0
- minitest_cli-0.35.0/tests/conftest.py +11 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/tests/test_app_skill_commands.py +6 -3
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/tests/test_apps_commands.py +15 -1
- minitest_cli-0.33.0/tests/test_scenario_command.py → minitest_cli-0.35.0/tests/test_deprecated_commands.py +22 -10
- minitest_cli-0.35.0/tests/test_deprecated_flags.py +102 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/tests/test_draft_feature_commands.py +4 -4
- minitest_cli-0.35.0/tests/test_private_network_commands.py +118 -0
- minitest_cli-0.35.0/tests/test_residential_proxy_commands.py +89 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/tests/test_run_cancel.py +1 -1
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/uv.lock +1 -1
- minitest_cli-0.33.0/src/minitest_cli/commands/deprecated_alias.py +0 -16
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/.env.example +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/.github/workflows/ci.yml +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/.github/workflows/install-scripts.yml +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/.github/workflows/release.yml +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/.gitignore +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/.opencode/skill/release/SKILL.md +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/AGENTS.md +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/RELEASE.md +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/install.ps1 +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/install.sh +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/pyrightconfig.json +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/renovate.json +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/__init__.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/api/__init__.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/api/apps_manager_client.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/api/client.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/api/errors.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/assets/__init__.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/assets/callback.html +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/__init__.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/_response_errors.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/app_knowledge.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/app_knowledge_helpers.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/app_skill_helpers.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/app_skill_secret.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/app_skill_write.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/apps_dependencies.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/apps_get.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/apps_helpers.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/auth.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/auth_api_key.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/batch_helpers.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/batch_warnings.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/build.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/build_commit.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/build_fix_prompts.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/build_helpers.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/capabilities.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/commit_helpers.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/env.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/env_helpers.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/flow_types.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/flow_types_helpers.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/flow_types_write.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/init.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/init_helpers.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/init_playbook.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/issues_helpers.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/issues_projection.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/issues_service.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/maintenance_callbacks.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/maintenance_helpers.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/maintenance_state.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/recording_timeline.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/run_commit_helpers.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/run_display.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/run_feedback.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/run_helpers.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/run_tagged.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/run_targets.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/screens.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/screens_detail.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/screens_format.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/screens_helpers.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/screens_tree.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/tags.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/tags_helpers.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/test_file.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/test_file_helpers.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/test_file_list.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/test_profile_card.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/test_profile_default.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/test_profile_helpers.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/test_profile_list.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/test_profile_update.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/upgrade.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/user_story.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/user_story_camera.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/user_story_create.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/user_story_criteria.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/user_story_criterion_edits.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/user_story_delete.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/user_story_device_count.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/user_story_helpers.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/user_story_modify.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/user_story_overrides.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/user_story_profiles.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/user_story_setup_commit.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/user_story_update.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/verdicts_helpers.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/verdicts_projection.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/core/__init__.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/core/app_context.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/core/auth.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/core/config.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/core/credentials.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/core/oauth.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/core/tenants.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/core/token_exchange.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/models/__init__.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/models/app_env_vars.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/models/app_failure.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/models/app_screen.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/models/base.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/models/batch.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/models/build.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/models/commit_build.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/models/draft_feature.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/models/flow_type.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/models/issues.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/models/recording.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/models/story_run.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/models/tag.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/models/targets.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/models/user_story.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/utils/__init__.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/utils/confirm.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/utils/dependency_sim.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/utils/mermaid.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/utils/output.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/utils/skill_refresh.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/utils/update_check.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/utils/video_frames.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/tests/__init__.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/tests/_commit_transport.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/tests/test_api_client_auth.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/tests/test_app_knowledge_commands.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/tests/test_apps_dependencies.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/tests/test_auth.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/tests/test_auth_api_key.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/tests/test_auth_commands.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/tests/test_batch_commands.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/tests/test_build_commands.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/tests/test_build_fix_prompts.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/tests/test_capabilities_command.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/tests/test_channel_header.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/tests/test_code_quality.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/tests/test_commit_commands.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/tests/test_env.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/tests/test_flow_types_commands.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/tests/test_init_command.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/tests/test_issues.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/tests/test_issues_commands.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/tests/test_mermaid.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/tests/test_native_device_types.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/tests/test_network_errors.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/tests/test_recording_timeline.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/tests/test_response_errors.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/tests/test_run_commands.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/tests/test_run_frames_command.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/tests/test_screens_commands.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/tests/test_skill_command.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/tests/test_suite_change_provenance.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/tests/test_tags_commands.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/tests/test_test_file_commands.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/tests/test_test_profile_commands.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/tests/test_upgrade_command.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/tests/test_user_story_bindings_commands.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/tests/test_user_story_commands.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/tests/test_user_story_setup_commit.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/tests/test_verdicts.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/tests/test_verdicts_actionable.py +0 -0
- {minitest_cli-0.33.0 → minitest_cli-0.35.0}/tests/test_version.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: minitest-cli
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.35.0
|
|
4
4
|
Summary: Minitest CLI – command-line interface for the Minitest testing platform
|
|
5
5
|
Project-URL: Homepage, https://minitap.ai/
|
|
6
6
|
Project-URL: Source, https://github.com/minitap-ai/minitest-cli
|
|
@@ -166,21 +166,71 @@ app defaults.
|
|
|
166
166
|
| Command | Description |
|
|
167
167
|
| ---------------- | ------------------------- |
|
|
168
168
|
| `minitest auth` | Authentication management |
|
|
169
|
-
| `minitest apps` | List, inspect, and create apps |
|
|
170
|
-
| `minitest scenario` | Create, update, list and delete scenarios
|
|
171
|
-
| `minitest scenario-binding` | Bind test
|
|
172
|
-
| `minitest
|
|
173
|
-
| `minitest
|
|
169
|
+
| `minitest apps` | List, inspect, and create apps; residential proxy and private network settings |
|
|
170
|
+
| `minitest scenario` | Create, update, list and delete scenarios |
|
|
171
|
+
| `minitest scenario-binding` | Bind test accounts, test files or app skills to scenarios |
|
|
172
|
+
| `minitest draft` | Drafts — branches of the test suite |
|
|
173
|
+
| `minitest test-profile` | Test profiles (Test accounts in the webapp) |
|
|
174
|
+
| `minitest tags` | List, create, update and delete scenario tags |
|
|
175
|
+
| `minitest app-skill` | App skills (Skills in the webapp): procedures Mini loads to arrange test state |
|
|
174
176
|
| `minitest screens` | Inspect the screens exploration mapped for an app |
|
|
175
177
|
| `minitest build` | Native iOS/Android build management |
|
|
176
|
-
| `minitest run` |
|
|
177
|
-
| `minitest
|
|
178
|
+
| `minitest run` | Start runs and inspect their scenario runs |
|
|
179
|
+
| `minitest batch` | List, inspect and cancel runs (a batch is a Run in the webapp) |
|
|
180
|
+
| `minitest issues` | Read app issues and their fix prompts, mark them fixed |
|
|
181
|
+
| `minitest maintenance` | CLI-only scenario maintenance against local code |
|
|
182
|
+
| `minitest skill` | Print the CLI skill for your AI coding agent (not app skills) |
|
|
183
|
+
|
|
184
|
+
### Deprecated names
|
|
185
|
+
|
|
186
|
+
Old names keep working as hidden aliases: they print a deprecation warning on
|
|
187
|
+
stderr and leave `--json` stdout unchanged. Switch to the new names.
|
|
188
|
+
|
|
189
|
+
| Deprecated | Use instead |
|
|
190
|
+
| ---------- | ----------- |
|
|
191
|
+
| `minitest user-story` | `minitest scenario` |
|
|
192
|
+
| `minitest user-story-binding` | `minitest scenario-binding` |
|
|
193
|
+
| `minitest scenario-binding set-skills` | `minitest scenario-binding set-app-skills` |
|
|
194
|
+
| `minitest df` | `minitest draft` |
|
|
195
|
+
| `minitest flow-types` | `minitest tags` |
|
|
196
|
+
| `run from-commit --user-story` / `-u` | `run from-commit --scenario` / `-s` |
|
|
197
|
+
| `batch list --user-story-id` | `batch list --scenario` |
|
|
198
|
+
| `run cancel --srp`, `run recording --srp` | `--target-id` |
|
|
199
|
+
| `--type` on `scenario create/update/list` | `--tag` |
|
|
200
|
+
|
|
201
|
+
## App network settings
|
|
202
|
+
|
|
203
|
+
Two per-app settings decide how test devices reach the network. Anyone on the
|
|
204
|
+
app can read them; only workspace **owners and admins** can change them (other
|
|
205
|
+
roles get `Only workspace owners and admins can change this setting`, exit 2).
|
|
206
|
+
`set` reads the current settings first and changes only what you pass.
|
|
207
|
+
Domains are an exact host (`api.stg.example.com`) or `*.example.com`, which
|
|
208
|
+
matches subdomains only, not `example.com` itself.
|
|
209
|
+
|
|
210
|
+
```bash
|
|
211
|
+
# Residential proxy: reach the listed domains from a residential IP in one country
|
|
212
|
+
minitest --app <app-id> apps residential-proxy show
|
|
213
|
+
minitest --app <app-id> apps residential-proxy set [--enable|--disable] [--country tr] \
|
|
214
|
+
[--domain ipinfo.io ...] [--remove-domain <d> ...] [--clear-domains]
|
|
215
|
+
|
|
216
|
+
# Private network: reach internal domains through a connector running in your network
|
|
217
|
+
minitest --app <app-id> apps private-network show
|
|
218
|
+
minitest --app <app-id> apps private-network connectors
|
|
219
|
+
minitest --app <app-id> apps private-network set [--enable|--disable] [--connector <name-or-id>] \
|
|
220
|
+
[--domain api.stg.corp.internal ...] [--remove-domain <d> ...] [--clear-domains] [--port 443 ...]
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
`--clear-domains --domain a --domain b` replaces the list; `--port` replaces the
|
|
224
|
+
ports (default 443). Turning the private network on needs a connector and at
|
|
225
|
+
least one domain. Connectors cannot be created from the CLI: a workspace owner
|
|
226
|
+
or admin creates them in the webapp, under **Workspace settings → Private
|
|
227
|
+
network**.
|
|
178
228
|
|
|
179
229
|
## CLI-only maintenance
|
|
180
230
|
|
|
181
231
|
`minitest maintenance` lets a coding agent keep Minitest scenarios in sync
|
|
182
232
|
without connecting GitHub. Run it from the app repository: the code stays on the
|
|
183
|
-
machine, while the CLI sends only proposed
|
|
233
|
+
machine, while the CLI sends only proposed scenario edits and the local HEAD SHA.
|
|
184
234
|
|
|
185
235
|
```bash
|
|
186
236
|
# Print the server-composed maintenance instructions for your coding agent
|
|
@@ -133,21 +133,71 @@ app defaults.
|
|
|
133
133
|
| Command | Description |
|
|
134
134
|
| ---------------- | ------------------------- |
|
|
135
135
|
| `minitest auth` | Authentication management |
|
|
136
|
-
| `minitest apps` | List, inspect, and create apps |
|
|
137
|
-
| `minitest scenario` | Create, update, list and delete scenarios
|
|
138
|
-
| `minitest scenario-binding` | Bind test
|
|
139
|
-
| `minitest
|
|
140
|
-
| `minitest
|
|
136
|
+
| `minitest apps` | List, inspect, and create apps; residential proxy and private network settings |
|
|
137
|
+
| `minitest scenario` | Create, update, list and delete scenarios |
|
|
138
|
+
| `minitest scenario-binding` | Bind test accounts, test files or app skills to scenarios |
|
|
139
|
+
| `minitest draft` | Drafts — branches of the test suite |
|
|
140
|
+
| `minitest test-profile` | Test profiles (Test accounts in the webapp) |
|
|
141
|
+
| `minitest tags` | List, create, update and delete scenario tags |
|
|
142
|
+
| `minitest app-skill` | App skills (Skills in the webapp): procedures Mini loads to arrange test state |
|
|
141
143
|
| `minitest screens` | Inspect the screens exploration mapped for an app |
|
|
142
144
|
| `minitest build` | Native iOS/Android build management |
|
|
143
|
-
| `minitest run` |
|
|
144
|
-
| `minitest
|
|
145
|
+
| `minitest run` | Start runs and inspect their scenario runs |
|
|
146
|
+
| `minitest batch` | List, inspect and cancel runs (a batch is a Run in the webapp) |
|
|
147
|
+
| `minitest issues` | Read app issues and their fix prompts, mark them fixed |
|
|
148
|
+
| `minitest maintenance` | CLI-only scenario maintenance against local code |
|
|
149
|
+
| `minitest skill` | Print the CLI skill for your AI coding agent (not app skills) |
|
|
150
|
+
|
|
151
|
+
### Deprecated names
|
|
152
|
+
|
|
153
|
+
Old names keep working as hidden aliases: they print a deprecation warning on
|
|
154
|
+
stderr and leave `--json` stdout unchanged. Switch to the new names.
|
|
155
|
+
|
|
156
|
+
| Deprecated | Use instead |
|
|
157
|
+
| ---------- | ----------- |
|
|
158
|
+
| `minitest user-story` | `minitest scenario` |
|
|
159
|
+
| `minitest user-story-binding` | `minitest scenario-binding` |
|
|
160
|
+
| `minitest scenario-binding set-skills` | `minitest scenario-binding set-app-skills` |
|
|
161
|
+
| `minitest df` | `minitest draft` |
|
|
162
|
+
| `minitest flow-types` | `minitest tags` |
|
|
163
|
+
| `run from-commit --user-story` / `-u` | `run from-commit --scenario` / `-s` |
|
|
164
|
+
| `batch list --user-story-id` | `batch list --scenario` |
|
|
165
|
+
| `run cancel --srp`, `run recording --srp` | `--target-id` |
|
|
166
|
+
| `--type` on `scenario create/update/list` | `--tag` |
|
|
167
|
+
|
|
168
|
+
## App network settings
|
|
169
|
+
|
|
170
|
+
Two per-app settings decide how test devices reach the network. Anyone on the
|
|
171
|
+
app can read them; only workspace **owners and admins** can change them (other
|
|
172
|
+
roles get `Only workspace owners and admins can change this setting`, exit 2).
|
|
173
|
+
`set` reads the current settings first and changes only what you pass.
|
|
174
|
+
Domains are an exact host (`api.stg.example.com`) or `*.example.com`, which
|
|
175
|
+
matches subdomains only, not `example.com` itself.
|
|
176
|
+
|
|
177
|
+
```bash
|
|
178
|
+
# Residential proxy: reach the listed domains from a residential IP in one country
|
|
179
|
+
minitest --app <app-id> apps residential-proxy show
|
|
180
|
+
minitest --app <app-id> apps residential-proxy set [--enable|--disable] [--country tr] \
|
|
181
|
+
[--domain ipinfo.io ...] [--remove-domain <d> ...] [--clear-domains]
|
|
182
|
+
|
|
183
|
+
# Private network: reach internal domains through a connector running in your network
|
|
184
|
+
minitest --app <app-id> apps private-network show
|
|
185
|
+
minitest --app <app-id> apps private-network connectors
|
|
186
|
+
minitest --app <app-id> apps private-network set [--enable|--disable] [--connector <name-or-id>] \
|
|
187
|
+
[--domain api.stg.corp.internal ...] [--remove-domain <d> ...] [--clear-domains] [--port 443 ...]
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
`--clear-domains --domain a --domain b` replaces the list; `--port` replaces the
|
|
191
|
+
ports (default 443). Turning the private network on needs a connector and at
|
|
192
|
+
least one domain. Connectors cannot be created from the CLI: a workspace owner
|
|
193
|
+
or admin creates them in the webapp, under **Workspace settings → Private
|
|
194
|
+
network**.
|
|
145
195
|
|
|
146
196
|
## CLI-only maintenance
|
|
147
197
|
|
|
148
198
|
`minitest maintenance` lets a coding agent keep Minitest scenarios in sync
|
|
149
199
|
without connecting GitHub. Run it from the app repository: the code stays on the
|
|
150
|
-
machine, while the CLI sends only proposed
|
|
200
|
+
machine, while the CLI sends only proposed scenario edits and the local HEAD SHA.
|
|
151
201
|
|
|
152
202
|
```bash
|
|
153
203
|
# Print the server-composed maintenance instructions for your coding agent
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
"""Shared plumbing for the per-app network settings (residential proxy, private network)."""
|
|
2
|
+
|
|
3
|
+
import asyncio
|
|
4
|
+
import re
|
|
5
|
+
from typing import Any
|
|
6
|
+
|
|
7
|
+
import httpx
|
|
8
|
+
import typer
|
|
9
|
+
|
|
10
|
+
from minitest_cli.api.client import ApiClient
|
|
11
|
+
from minitest_cli.api.errors import format_network_error
|
|
12
|
+
from minitest_cli.commands._response_errors import extract_detail
|
|
13
|
+
from minitest_cli.core.app_context import resolve_app_id
|
|
14
|
+
from minitest_cli.core.auth import require_auth
|
|
15
|
+
from minitest_cli.core.config import Settings
|
|
16
|
+
from minitest_cli.utils.output import print_error
|
|
17
|
+
|
|
18
|
+
EXIT_GENERAL_ERROR = 1
|
|
19
|
+
EXIT_AUTH_ERROR = 2
|
|
20
|
+
EXIT_NETWORK_ERROR = 3
|
|
21
|
+
EXIT_NOT_FOUND = 4
|
|
22
|
+
|
|
23
|
+
ADMIN_ONLY_MESSAGE = "Only workspace owners and admins can change this setting."
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def is_json_mode() -> bool:
|
|
27
|
+
return typer.Context.json_mode # type: ignore[attr-defined]
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def resolve_target() -> tuple[Settings, str]:
|
|
31
|
+
settings: Settings = typer.Context.settings # type: ignore[attr-defined]
|
|
32
|
+
require_auth(settings)
|
|
33
|
+
return settings, resolve_app_id(settings, typer.Context.app_flag) # type: ignore[attr-defined]
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def fail(message: str, code: int = EXIT_GENERAL_ERROR) -> typer.Exit:
|
|
37
|
+
print_error(message)
|
|
38
|
+
return typer.Exit(code=code)
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def _raise_for_status(resp: httpx.Response) -> None:
|
|
42
|
+
if resp.status_code < 400:
|
|
43
|
+
return
|
|
44
|
+
detail = extract_detail(resp)
|
|
45
|
+
if resp.status_code == 403:
|
|
46
|
+
raise fail(f"{ADMIN_ONLY_MESSAGE} ({detail})", EXIT_AUTH_ERROR)
|
|
47
|
+
if resp.status_code == 401:
|
|
48
|
+
raise fail(f"Authentication failed: {detail}", EXIT_AUTH_ERROR)
|
|
49
|
+
if resp.status_code == 404:
|
|
50
|
+
raise fail(f"Not found: {detail}", EXIT_NOT_FOUND)
|
|
51
|
+
if resp.status_code in (400, 409, 422):
|
|
52
|
+
raise fail(f"Rejected by the server ({resp.status_code}): {detail}")
|
|
53
|
+
raise fail(f"API error ({resp.status_code}): {detail}", EXIT_NETWORK_ERROR)
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def call_api(
|
|
57
|
+
settings: Settings, method: str, path: str, body: dict[str, Any] | None = None
|
|
58
|
+
) -> dict[str, Any]:
|
|
59
|
+
async def _run() -> dict[str, Any]:
|
|
60
|
+
async with ApiClient(settings) as client:
|
|
61
|
+
resp = await client.request(method, path, json=body)
|
|
62
|
+
_raise_for_status(resp)
|
|
63
|
+
try:
|
|
64
|
+
return resp.json()
|
|
65
|
+
except ValueError as exc:
|
|
66
|
+
raise fail(
|
|
67
|
+
f"Unexpected non-JSON response ({resp.status_code}): {resp.text[:200]}",
|
|
68
|
+
EXIT_NETWORK_ERROR,
|
|
69
|
+
) from exc
|
|
70
|
+
|
|
71
|
+
try:
|
|
72
|
+
return asyncio.run(_run())
|
|
73
|
+
except httpx.HTTPError as exc:
|
|
74
|
+
raise fail(format_network_error(exc), EXIT_NETWORK_ERROR) from exc
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def merge_domains(
|
|
78
|
+
current: list[str],
|
|
79
|
+
*,
|
|
80
|
+
add: list[str] | None,
|
|
81
|
+
remove: list[str] | None,
|
|
82
|
+
clear: bool,
|
|
83
|
+
pattern: str,
|
|
84
|
+
max_domains: int,
|
|
85
|
+
) -> list[str]:
|
|
86
|
+
"""Apply ``--clear-domains``, ``--remove-domain`` then ``--domain`` and validate the result."""
|
|
87
|
+
added = [_normalize(d) for d in add or []]
|
|
88
|
+
invalid = [d for d in added if not re.fullmatch(pattern, d)]
|
|
89
|
+
if invalid:
|
|
90
|
+
raise fail(
|
|
91
|
+
f"Invalid domain(s): {', '.join(invalid)}. Use a lowercase host like api.example.com, "
|
|
92
|
+
"or *.example.com to match its subdomains (not example.com itself)."
|
|
93
|
+
)
|
|
94
|
+
removed = {_normalize(d) for d in remove or []}
|
|
95
|
+
unknown = sorted(removed - set(current))
|
|
96
|
+
if unknown:
|
|
97
|
+
raise fail(f"Not in the current domain list: {', '.join(unknown)}.")
|
|
98
|
+
base = [] if clear else [d for d in current if d not in removed]
|
|
99
|
+
merged = list(dict.fromkeys([*base, *added]))
|
|
100
|
+
if len(merged) > max_domains:
|
|
101
|
+
raise fail(f"Too many domains: {len(merged)} (max {max_domains}).")
|
|
102
|
+
return merged
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
def _normalize(domain: str) -> str:
|
|
106
|
+
return domain.strip().lower().rstrip(".")
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def on_off(value: bool) -> str:
|
|
110
|
+
return "on" if value else "off"
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
def domain_list(domains: list[str]) -> str:
|
|
114
|
+
return ", ".join(domains) if domains else "-"
|
|
@@ -21,7 +21,7 @@ from minitest_cli.utils.output import print_info, print_json, print_success, pri
|
|
|
21
21
|
|
|
22
22
|
app = typer.Typer(
|
|
23
23
|
name="app-skill",
|
|
24
|
-
help="Manage app skills: procedures Mini loads to arrange test state.",
|
|
24
|
+
help="Manage app skills (Skills in the webapp): procedures Mini loads to arrange test state.",
|
|
25
25
|
no_args_is_help=True,
|
|
26
26
|
)
|
|
27
27
|
app.add_typer(app_skill_secret.app)
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"""App management commands: list, get, create, dependencies."""
|
|
1
|
+
"""App management commands: list, get, create, dependencies, network settings."""
|
|
2
2
|
|
|
3
3
|
import asyncio
|
|
4
4
|
from pathlib import Path
|
|
@@ -10,8 +10,14 @@ import typer
|
|
|
10
10
|
from minitest_cli.api.apps_manager_client import AppsManagerClient # noqa: F401 re-exported for tests
|
|
11
11
|
from minitest_cli.api.client import ApiClient
|
|
12
12
|
from minitest_cli.api.errors import format_network_error
|
|
13
|
-
from minitest_cli.commands import
|
|
13
|
+
from minitest_cli.commands import (
|
|
14
|
+
apps_dependencies,
|
|
15
|
+
apps_get,
|
|
16
|
+
private_network,
|
|
17
|
+
residential_proxy,
|
|
18
|
+
)
|
|
14
19
|
from minitest_cli.commands.apps_helpers import create_app_request
|
|
20
|
+
from minitest_cli.commands.apps_table import APP_TABLE_HEADERS, app_row
|
|
15
21
|
from minitest_cli.core.auth import require_auth
|
|
16
22
|
from minitest_cli.core.config import Settings
|
|
17
23
|
from minitest_cli.core.tenants import fetch_user_tenants, resolve_tenant_id
|
|
@@ -29,6 +35,8 @@ EXIT_NETWORK_ERROR = 3
|
|
|
29
35
|
app = typer.Typer(name="apps", help="App management.")
|
|
30
36
|
app.command(name="dependencies")(apps_dependencies.dependencies)
|
|
31
37
|
app.command(name="get")(apps_get.get_app)
|
|
38
|
+
app.add_typer(residential_proxy.app)
|
|
39
|
+
app.add_typer(private_network.app)
|
|
32
40
|
|
|
33
41
|
|
|
34
42
|
@app.callback()
|
|
@@ -36,22 +44,6 @@ def _callback() -> None:
|
|
|
36
44
|
"""App management."""
|
|
37
45
|
|
|
38
46
|
|
|
39
|
-
APP_TABLE_HEADERS = ["ID", "Name", "Platform"]
|
|
40
|
-
|
|
41
|
-
_PLATFORM_LABELS: dict[str, str] = {
|
|
42
|
-
"android": "Android",
|
|
43
|
-
"ios": "iOS",
|
|
44
|
-
"web": "Web",
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
def _format_platforms(values: list[str]) -> str:
|
|
49
|
-
"""Render an app's platform lanes for the table."""
|
|
50
|
-
if not values:
|
|
51
|
-
return "—"
|
|
52
|
-
return ", ".join(_PLATFORM_LABELS.get(v, v) for v in values)
|
|
53
|
-
|
|
54
|
-
|
|
55
47
|
def _get_settings() -> Settings:
|
|
56
48
|
return typer.Context.settings # type: ignore[attr-defined]
|
|
57
49
|
|
|
@@ -92,8 +84,7 @@ def list_apps() -> None:
|
|
|
92
84
|
print_json([a.model_dump(mode="json", by_alias=True) for a in data.apps])
|
|
93
85
|
return
|
|
94
86
|
|
|
95
|
-
|
|
96
|
-
print_table(APP_TABLE_HEADERS, rows, title="Apps")
|
|
87
|
+
print_table(APP_TABLE_HEADERS, [app_row(a) for a in data.apps], title="Apps")
|
|
97
88
|
|
|
98
89
|
|
|
99
90
|
@app.command(name="create")
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"""Rows of the `apps list` table."""
|
|
2
|
+
|
|
3
|
+
from minitest_cli.models.app import AppResponse
|
|
4
|
+
|
|
5
|
+
APP_TABLE_HEADERS = ["ID", "Name", "Platform", "Repository", "Folder"]
|
|
6
|
+
|
|
7
|
+
_PLATFORM_LABELS: dict[str, str] = {
|
|
8
|
+
"android": "Android",
|
|
9
|
+
"ios": "iOS",
|
|
10
|
+
"web": "Web",
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def _format_platforms(values: list[str]) -> str:
|
|
15
|
+
if not values:
|
|
16
|
+
return "—"
|
|
17
|
+
return ", ".join(_PLATFORM_LABELS.get(v, v) for v in values)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def app_row(app: AppResponse) -> list[str]:
|
|
21
|
+
repo = app.repository
|
|
22
|
+
return [
|
|
23
|
+
app.id,
|
|
24
|
+
app.name,
|
|
25
|
+
_format_platforms(app.platforms),
|
|
26
|
+
repo.full_name if repo else "—",
|
|
27
|
+
(repo.folder or "/") if repo else "—",
|
|
28
|
+
]
|
|
@@ -7,6 +7,7 @@ import typer
|
|
|
7
7
|
|
|
8
8
|
from minitest_cli.api.client import ApiClient
|
|
9
9
|
from minitest_cli.commands.batch_helpers import batches_base_path
|
|
10
|
+
from minitest_cli.commands.deprecated_alias import deprecated_option, merge_deprecated_option
|
|
10
11
|
from minitest_cli.commands.run_display import _derive_run_status
|
|
11
12
|
from minitest_cli.commands.run_helpers import (
|
|
12
13
|
ensure_uuid,
|
|
@@ -26,7 +27,7 @@ from minitest_cli.utils.output import (
|
|
|
26
27
|
print_table,
|
|
27
28
|
)
|
|
28
29
|
|
|
29
|
-
app = typer.Typer(name="batch", help="
|
|
30
|
+
app = typer.Typer(name="batch", help="List, inspect and cancel runs (Runs in the webapp).")
|
|
30
31
|
|
|
31
32
|
BATCH_TABLE_HEADERS = ["ID", "Status", "Source", "Commit", "Tag", "Targets", "Created"]
|
|
32
33
|
|
|
@@ -57,26 +58,32 @@ def list_batches(
|
|
|
57
58
|
typer.Option("--result", help="Filter by derived result (repeatable)."),
|
|
58
59
|
] = None,
|
|
59
60
|
commit_sha: Annotated[str | None, typer.Option("--commit-sha")] = None,
|
|
60
|
-
|
|
61
|
+
scenario_id: Annotated[
|
|
62
|
+
str | None, typer.Option("--scenario", help="Only runs that include this scenario ID.")
|
|
63
|
+
] = None,
|
|
64
|
+
legacy_user_story_id: Annotated[
|
|
65
|
+
str | None, deprecated_option("--user-story-id", new_flag="--scenario")
|
|
66
|
+
] = None,
|
|
61
67
|
search: Annotated[str | None, typer.Option("--search")] = None,
|
|
62
68
|
all_pages: Annotated[bool, typer.Option("--all", help="Fetch all pages.")] = False,
|
|
63
69
|
) -> None:
|
|
64
|
-
"""List batches
|
|
70
|
+
"""List the runs (batches) of the current app."""
|
|
65
71
|
settings, app_id, json_mode = resolve_app()
|
|
66
72
|
if all_pages:
|
|
67
73
|
page, page_size = 1, 100
|
|
68
74
|
|
|
75
|
+
scenario_id = merge_deprecated_option(
|
|
76
|
+
scenario_id, legacy_user_story_id, old_flag="--user-story-id", new_flag="--scenario"
|
|
77
|
+
)
|
|
78
|
+
filters = {
|
|
79
|
+
"status": status_filter,
|
|
80
|
+
"result": result_filter,
|
|
81
|
+
"commit_sha": commit_sha,
|
|
82
|
+
"user_story_id": scenario_id,
|
|
83
|
+
"search": search,
|
|
84
|
+
}
|
|
69
85
|
params: dict[str, object] = {"page": page, "page_size": page_size}
|
|
70
|
-
if
|
|
71
|
-
params["status"] = status_filter
|
|
72
|
-
if result_filter:
|
|
73
|
-
params["result"] = result_filter
|
|
74
|
-
if commit_sha:
|
|
75
|
-
params["commit_sha"] = commit_sha
|
|
76
|
-
if user_story_id:
|
|
77
|
-
params["user_story_id"] = user_story_id
|
|
78
|
-
if search:
|
|
79
|
-
params["search"] = search
|
|
86
|
+
params.update({key: value for key, value in filters.items() if value})
|
|
80
87
|
|
|
81
88
|
async def _list() -> BatchListResponse:
|
|
82
89
|
async with ApiClient(settings) as client:
|
|
@@ -108,9 +115,9 @@ def list_batches(
|
|
|
108
115
|
|
|
109
116
|
@app.command(name="get")
|
|
110
117
|
def get_batch(
|
|
111
|
-
batch_id: Annotated[str, typer.Argument(help="
|
|
118
|
+
batch_id: Annotated[str, typer.Argument(help="Run (batch) ID.")],
|
|
112
119
|
) -> None:
|
|
113
|
-
"""Get
|
|
120
|
+
"""Get one run (batch) with its scenario runs."""
|
|
114
121
|
settings, app_id, json_mode = resolve_app()
|
|
115
122
|
ensure_uuid(batch_id, kind="batch id")
|
|
116
123
|
|
|
@@ -173,9 +180,9 @@ def get_batch(
|
|
|
173
180
|
|
|
174
181
|
@app.command()
|
|
175
182
|
def cancel(
|
|
176
|
-
batch_id: Annotated[str, typer.Argument(help="
|
|
183
|
+
batch_id: Annotated[str, typer.Argument(help="Run (batch) ID to cancel.")],
|
|
177
184
|
) -> None:
|
|
178
|
-
"""Cancel a batch and all its pending/running scenario runs."""
|
|
185
|
+
"""Cancel a run (batch) and all its pending/running scenario runs."""
|
|
179
186
|
settings, app_id, json_mode = resolve_app()
|
|
180
187
|
ensure_uuid(batch_id, kind="batch id")
|
|
181
188
|
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import functools
|
|
2
|
+
from collections.abc import Callable
|
|
3
|
+
from typing import Any
|
|
4
|
+
|
|
5
|
+
import typer
|
|
6
|
+
|
|
7
|
+
from minitest_cli.utils.output import print_error, print_warning
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def deprecated_alias(source: typer.Typer, *, old_name: str) -> typer.Typer:
|
|
11
|
+
"""Expose ``source``'s commands under a hidden legacy name that warns on stderr."""
|
|
12
|
+
new_name = source.info.name
|
|
13
|
+
alias = typer.Typer(name=old_name, help=f"Deprecated: use `minitest {new_name}`.", hidden=True)
|
|
14
|
+
|
|
15
|
+
@alias.callback()
|
|
16
|
+
def _warn() -> None:
|
|
17
|
+
print_warning(f"`minitest {old_name}` is deprecated; use `minitest {new_name}` instead.")
|
|
18
|
+
|
|
19
|
+
alias.registered_commands = source.registered_commands
|
|
20
|
+
return alias
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def deprecated_command(
|
|
24
|
+
group: typer.Typer, command: Callable[..., Any], *, old_name: str, new_name: str
|
|
25
|
+
) -> None:
|
|
26
|
+
"""Register ``command`` again under a hidden legacy subcommand name that warns on stderr."""
|
|
27
|
+
group_name = group.info.name
|
|
28
|
+
|
|
29
|
+
@functools.wraps(command)
|
|
30
|
+
def _legacy(*args: Any, **kwargs: Any) -> Any:
|
|
31
|
+
print_warning(
|
|
32
|
+
f"`minitest {group_name} {old_name}` is deprecated; "
|
|
33
|
+
f"use `minitest {group_name} {new_name}` instead."
|
|
34
|
+
)
|
|
35
|
+
return command(*args, **kwargs)
|
|
36
|
+
|
|
37
|
+
group.command(name=old_name, hidden=True, help=f"Deprecated: use `{new_name}`.")(_legacy)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def deprecated_option(*param_decls: str, new_flag: str) -> Any:
|
|
41
|
+
"""A hidden option kept for a renamed flag; pair it with ``merge_deprecated_option``."""
|
|
42
|
+
return typer.Option(*param_decls, hidden=True, help=f"Deprecated alias for {new_flag}.")
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def merge_deprecated_option[T](
|
|
46
|
+
new: T | None, old: T | None, *, old_flag: str, new_flag: str
|
|
47
|
+
) -> T | None:
|
|
48
|
+
"""Return the renamed flag's value, falling back to its deprecated alias with a warning."""
|
|
49
|
+
if old is None:
|
|
50
|
+
return new
|
|
51
|
+
print_warning(f"{old_flag} is deprecated; use {new_flag} instead.")
|
|
52
|
+
if new is None:
|
|
53
|
+
return old
|
|
54
|
+
if isinstance(new, list) and isinstance(old, list):
|
|
55
|
+
return [*new, *old] # type: ignore[return-value]
|
|
56
|
+
print_error(f"Use either {new_flag} or {old_flag}, not both.")
|
|
57
|
+
raise typer.Exit(code=1)
|
|
@@ -11,6 +11,7 @@ import typer
|
|
|
11
11
|
|
|
12
12
|
from minitest_cli.api.client import ApiClient
|
|
13
13
|
from minitest_cli.commands import draft_feature_apply, draft_feature_show
|
|
14
|
+
from minitest_cli.commands.deprecated_alias import deprecated_alias
|
|
14
15
|
from minitest_cli.commands.draft_feature_helpers import (
|
|
15
16
|
DRAFT_FEATURE_TABLE_HEADERS,
|
|
16
17
|
base_path,
|
|
@@ -21,7 +22,7 @@ from minitest_cli.commands.run_helpers import ensure_uuid, resolve_app, run_api_
|
|
|
21
22
|
from minitest_cli.models.draft_feature import DraftFeatureResponse, DraftFeatureStatus
|
|
22
23
|
from minitest_cli.utils.output import output, print_error, print_info, print_success, print_table
|
|
23
24
|
|
|
24
|
-
app = typer.Typer(name="
|
|
25
|
+
app = typer.Typer(name="draft", help="Drafts — branches of the app's test suite.")
|
|
25
26
|
draft_feature_show.register(app)
|
|
26
27
|
draft_feature_apply.register(app)
|
|
27
28
|
|
|
@@ -42,7 +43,7 @@ def list_draft_features(
|
|
|
42
43
|
async def _list() -> list[DraftFeatureResponse]:
|
|
43
44
|
async with ApiClient(settings) as client:
|
|
44
45
|
resp = await client.get(base_path(app_id), params=params)
|
|
45
|
-
handle_response_error(resp, resource="
|
|
46
|
+
handle_response_error(resp, resource="Drafts")
|
|
46
47
|
return [DraftFeatureResponse.model_validate(item) for item in resp.json()]
|
|
47
48
|
|
|
48
49
|
features = run_api_call(_list())
|
|
@@ -51,12 +52,12 @@ def list_draft_features(
|
|
|
51
52
|
output([f.model_dump(mode="json", by_alias=True) for f in features], json_mode=True)
|
|
52
53
|
return
|
|
53
54
|
if not features:
|
|
54
|
-
print_info("No
|
|
55
|
+
print_info("No drafts found.")
|
|
55
56
|
return
|
|
56
57
|
print_table(
|
|
57
58
|
DRAFT_FEATURE_TABLE_HEADERS,
|
|
58
59
|
[format_draft_feature_row(f) for f in features],
|
|
59
|
-
title=f"
|
|
60
|
+
title=f"Drafts ({len(features)})",
|
|
60
61
|
)
|
|
61
62
|
|
|
62
63
|
|
|
@@ -88,7 +89,7 @@ def create_draft_feature(
|
|
|
88
89
|
|
|
89
90
|
feature = run_api_call(_create())
|
|
90
91
|
if not json_mode:
|
|
91
|
-
print_success(f"Draft
|
|
92
|
+
print_success(f"Draft created: {feature.id}")
|
|
92
93
|
output(feature.model_dump(mode="json", by_alias=True), json_mode=json_mode)
|
|
93
94
|
|
|
94
95
|
|
|
@@ -114,4 +115,7 @@ def delete_draft_feature(
|
|
|
114
115
|
if json_mode:
|
|
115
116
|
output(feature.model_dump(mode="json", by_alias=True), json_mode=True)
|
|
116
117
|
else:
|
|
117
|
-
print_success(f"Draft
|
|
118
|
+
print_success(f"Draft abandoned: {feature.id} (status: {feature.status.value})")
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
legacy_app = deprecated_alias(app, old_name="df")
|
{minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/draft_feature_conflicts.py
RENAMED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"""Rendering for `minitest
|
|
1
|
+
"""Rendering for `minitest draft show --view conflicts`.
|
|
2
2
|
|
|
3
3
|
The three sides of a conflict are whole story tuples, so printing them as three
|
|
4
4
|
JSON blobs in a table makes the one thing a resolver needs — which key is in
|
{minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/draft_feature_helpers.py
RENAMED
|
@@ -59,7 +59,9 @@ def handle_response_error(resp: httpx.Response, *, resource: str = "Draft featur
|
|
|
59
59
|
if resp.status_code == 409:
|
|
60
60
|
detail = extract_detail(resp)
|
|
61
61
|
print_error(detail or f"{resource} changed since it was read.")
|
|
62
|
-
print_info(
|
|
62
|
+
print_info(
|
|
63
|
+
"Re-run `draft show --view diff`, rebuild against the mainRev it returns, retry."
|
|
64
|
+
)
|
|
63
65
|
raise typer.Exit(code=EXIT_CONFLICT)
|
|
64
66
|
if resp.status_code >= 400:
|
|
65
67
|
detail = extract_detail(resp)
|