minitest-cli 0.42.0__tar.gz → 0.43.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.42.0 → minitest_cli-0.43.0}/.github/workflows/release.yml +0 -50
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/AGENTS.md +2 -1
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/PKG-INFO +29 -7
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/README.md +28 -6
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/RELEASE.md +4 -14
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/pyproject.toml +1 -1
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/upgrade.py +16 -28
- minitest_cli-0.43.0/src/minitest_cli/commands/upgrade_auto.py +81 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/main.py +3 -2
- minitest_cli-0.43.0/src/minitest_cli/utils/auto_update.py +156 -0
- minitest_cli-0.43.0/src/minitest_cli/utils/auto_update_notices.py +41 -0
- minitest_cli-0.43.0/src/minitest_cli/utils/auto_update_state.py +163 -0
- minitest_cli-0.43.0/src/minitest_cli/utils/auto_update_worker.py +135 -0
- minitest_cli-0.43.0/src/minitest_cli/utils/update_check.py +116 -0
- minitest_cli-0.43.0/src/minitest_cli/utils/versions.py +14 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/tests/conftest.py +2 -0
- minitest_cli-0.43.0/tests/test_auto_update.py +189 -0
- minitest_cli-0.43.0/tests/test_auto_update_worker.py +213 -0
- minitest_cli-0.43.0/tests/test_upgrade_auto_command.py +88 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/tests/test_upgrade_command.py +5 -30
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/uv.lock +1 -1
- minitest_cli-0.42.0/src/minitest_cli/utils/update_check.py +0 -110
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/.env.example +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/.github/workflows/ci.yml +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/.github/workflows/install-scripts.yml +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/.gitignore +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/.opencode/skill/release/SKILL.md +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/install.ps1 +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/install.sh +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/pyrightconfig.json +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/renovate.json +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/__init__.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/api/__init__.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/api/apps_manager_client.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/api/client.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/api/errors.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/assets/__init__.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/assets/callback.html +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/__init__.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/_abi_mismatch.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/_response_errors.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/app_knowledge.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/app_knowledge_helpers.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/app_network_helpers.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/app_skill.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/app_skill_helpers.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/app_skill_secret.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/app_skill_write.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/apps.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/apps_dependencies.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/apps_get.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/apps_helpers.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/apps_table.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/auth.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/auth_api_key.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/backend_api.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/backend_api_helpers.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/batch.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/batch_helpers.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/batch_warnings.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/build.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/build_bundle.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/build_commit.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/build_conversion.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/build_fix_prompts.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/build_get.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/build_helpers.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/build_signing.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/capabilities.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/commit_helpers.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/deprecated_alias.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/draft.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/draft_asks.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/draft_conversation.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/draft_create.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/draft_feature.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/draft_feature_apply.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/draft_feature_conflicts.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/draft_feature_helpers.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/draft_feature_show.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/draft_helpers.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/draft_legacy.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/draft_lifecycle.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/draft_pr.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/draft_render.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/draft_update.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/draft_watch.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/env.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/env_helpers.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/flow_types.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/flow_types_helpers.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/flow_types_write.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/glossary.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/init.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/init_helpers.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/init_playbook.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/issues.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/issues_fix.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/issues_get.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/issues_helpers.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/issues_projection.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/issues_service.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/knowledge.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/knowledge_documents.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/knowledge_helpers.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/private_network.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/private_network_helpers.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/recording_timeline.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/residential_proxy.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/run.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/run_backend_override.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/run_cancel.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/run_commit.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/run_commit_helpers.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/run_display.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/run_feedback.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/run_helpers.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/run_list.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/run_logs.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/run_recording.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/run_recording_helpers.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/run_tagged.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/run_targets.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/schedules.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/schedules_body.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/schedules_create.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/schedules_display.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/schedules_helpers.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/schedules_history.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/schedules_options.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/schedules_scope.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/schedules_spec.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/schedules_update.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/schedules_where.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/screens.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/screens_detail.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/screens_format.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/screens_helpers.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/screens_tree.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/secret.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/secret_create.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/secret_extract.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/secret_helpers.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/secret_lint.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/secret_manage.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/secret_state.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/secret_value.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/skill.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/tags.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/tags_helpers.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/test_file.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/test_file_helpers.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/test_file_list.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/test_profile.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/test_profile_card.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/test_profile_default.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/test_profile_helpers.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/test_profile_list.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/test_profile_secret_refs.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/test_profile_update.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/user_story.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/user_story_app_skills.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/user_story_bindings.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/user_story_camera.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/user_story_create.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/user_story_criteria.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/user_story_criterion_edits.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/user_story_delete.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/user_story_device_count.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/user_story_helpers.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/user_story_iap.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/user_story_modify.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/user_story_overrides.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/user_story_profiles.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/user_story_setup_commit.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/user_story_update.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/verdicts.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/verdicts_helpers.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/commands/verdicts_projection.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/core/__init__.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/core/app_context.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/core/auth.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/core/config.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/core/credentials.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/core/oauth.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/core/tenants.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/core/token_exchange.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/models/__init__.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/models/app.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/models/app_env_vars.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/models/app_failure.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/models/app_screen.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/models/base.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/models/batch.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/models/build.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/models/commit_build.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/models/draft_feature.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/models/flow_type.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/models/issues.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/models/lane_logs.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/models/recording.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/models/story_run.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/models/tag.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/models/targets.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/models/user_story.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/utils/__init__.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/utils/confirm.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/utils/dependency_sim.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/utils/mermaid.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/utils/output.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/utils/skill_refresh.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/src/minitest_cli/utils/video_frames.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/tests/__init__.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/tests/_backend_api_server.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/tests/_commit_transport.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/tests/_network_settings_server.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/tests/_secret_router.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/tests/draft_backend.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/tests/test_api_client_auth.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/tests/test_app_context.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/tests/test_app_knowledge_commands.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/tests/test_app_skill_commands.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/tests/test_apps_commands.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/tests/test_apps_dependencies.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/tests/test_auth.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/tests/test_auth_api_key.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/tests/test_auth_commands.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/tests/test_backend_api_commands.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/tests/test_backend_api_openapi_auth.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/tests/test_batch_commands.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/tests/test_build_bundle.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/tests/test_build_commands.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/tests/test_build_fix_prompts.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/tests/test_build_get_command.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/tests/test_capabilities_command.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/tests/test_channel_header.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/tests/test_code_quality.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/tests/test_commit_commands.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/tests/test_config_defaults.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/tests/test_deprecated_commands.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/tests/test_deprecated_flags.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/tests/test_draft_ask_commands.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/tests/test_draft_commands.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/tests/test_draft_conversation_commands.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/tests/test_draft_feature_commands.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/tests/test_draft_pr_commands.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/tests/test_env.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/tests/test_flow_types_commands.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/tests/test_init_command.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/tests/test_issues.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/tests/test_issues_commands.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/tests/test_issues_get_command.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/tests/test_knowledge_v2_commands.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/tests/test_mermaid.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/tests/test_native_device_types.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/tests/test_network_errors.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/tests/test_physical_devices.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/tests/test_private_network_commands.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/tests/test_recording_timeline.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/tests/test_residential_proxy_commands.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/tests/test_response_errors.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/tests/test_run_backend_override.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/tests/test_run_cancel.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/tests/test_run_commands.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/tests/test_run_frames_command.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/tests/test_run_logs_command.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/tests/test_schedules_commands.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/tests/test_screens_commands.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/tests/test_secret_commands.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/tests/test_secret_create.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/tests/test_secret_lint_extract.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/tests/test_skill_command.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/tests/test_suite_change_provenance.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/tests/test_tags_commands.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/tests/test_test_file_commands.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/tests/test_test_profile_commands.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/tests/test_test_profile_secret_refs.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/tests/test_user_story_bindings_commands.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/tests/test_user_story_commands.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/tests/test_user_story_in_app_purchases.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/tests/test_user_story_setup_commit.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/tests/test_verdicts.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/tests/test_verdicts_actionable.py +0 -0
- {minitest_cli-0.42.0 → minitest_cli-0.43.0}/tests/test_version.py +0 -0
|
@@ -78,53 +78,3 @@ jobs:
|
|
|
78
78
|
with:
|
|
79
79
|
generate_release_notes: true
|
|
80
80
|
files: dist/*
|
|
81
|
-
|
|
82
|
-
update-homebrew:
|
|
83
|
-
needs: publish-pypi
|
|
84
|
-
runs-on: ubuntu-latest
|
|
85
|
-
steps:
|
|
86
|
-
- name: Fetch PyPI metadata
|
|
87
|
-
id: pypi
|
|
88
|
-
run: |
|
|
89
|
-
VERSION="${GITHUB_REF_NAME#v}"
|
|
90
|
-
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
|
|
91
|
-
|
|
92
|
-
echo "Waiting for minitest-cli $VERSION to be available on PyPI..."
|
|
93
|
-
for i in $(seq 1 30); do
|
|
94
|
-
if curl -sSf --connect-timeout 5 --max-time 15 \
|
|
95
|
-
"https://pypi.org/pypi/minitest-cli/$VERSION/json" -o /tmp/pypi.json.tmp; then
|
|
96
|
-
mv /tmp/pypi.json.tmp /tmp/pypi.json
|
|
97
|
-
echo "Package is available on PyPI"
|
|
98
|
-
break
|
|
99
|
-
fi
|
|
100
|
-
echo "Attempt $i/30 - not yet available, waiting 10s..."
|
|
101
|
-
sleep 10
|
|
102
|
-
done
|
|
103
|
-
|
|
104
|
-
if [ ! -f /tmp/pypi.json ]; then
|
|
105
|
-
echo "::error::Package not found on PyPI after 5 minutes"
|
|
106
|
-
exit 1
|
|
107
|
-
fi
|
|
108
|
-
|
|
109
|
-
SDIST_URL=$(jq -r '.urls[] | select(.packagetype == "sdist") | .url' /tmp/pypi.json)
|
|
110
|
-
SDIST_SHA256=$(jq -r '.urls[] | select(.packagetype == "sdist") | .digests.sha256' /tmp/pypi.json)
|
|
111
|
-
if [ -z "$SDIST_URL" ] || [ "$SDIST_URL" = "null" ] || [ -z "$SDIST_SHA256" ] || [ "$SDIST_SHA256" = "null" ]; then
|
|
112
|
-
echo "::error::sdist metadata is missing from PyPI response"
|
|
113
|
-
exit 1
|
|
114
|
-
fi
|
|
115
|
-
echo "sdist_url=$SDIST_URL" >> "$GITHUB_OUTPUT"
|
|
116
|
-
echo "sdist_sha256=$SDIST_SHA256" >> "$GITHUB_OUTPUT"
|
|
117
|
-
|
|
118
|
-
- name: Trigger Homebrew tap update
|
|
119
|
-
uses: peter-evans/repository-dispatch@v3
|
|
120
|
-
with:
|
|
121
|
-
token: ${{ secrets.HOMEBREW_TAP_TOKEN }}
|
|
122
|
-
repository: minitap-ai/homebrew-tap
|
|
123
|
-
event-type: update-formula
|
|
124
|
-
client-payload: |
|
|
125
|
-
{
|
|
126
|
-
"formula": "minitest-cli",
|
|
127
|
-
"version": "${{ steps.pypi.outputs.version }}",
|
|
128
|
-
"sdist_url": "${{ steps.pypi.outputs.sdist_url }}",
|
|
129
|
-
"sdist_sha256": "${{ steps.pypi.outputs.sdist_sha256 }}"
|
|
130
|
-
}
|
|
@@ -22,7 +22,8 @@ uv add <package> # Add new dependency (always
|
|
|
22
22
|
- `api/client.py` - httpx async client with auto auth + X-Minitest-Channel header
|
|
23
23
|
- `utils/`
|
|
24
24
|
- `output.py` - --json helpers: stdout=data, stderr=diagnostics
|
|
25
|
-
- `update_check.py` - PyPI version check (cached
|
|
25
|
+
- `update_check.py` - PyPI version check (cached 1h, non-blocking); hands newer releases to auto-update
|
|
26
|
+
- `auto_update*.py` - background self-update of the CLI and agent skill: eligibility and plan (`auto_update.py`), lock/state/running-command registry and the saved on/off preference (`auto_update_state.py`, toggled by `minitest upgrade auto`, `commands/upgrade_auto.py`), one-time notices, and the detached worker (`python -m minitest_cli.utils.auto_update_worker`). Tests run with `MINITEST_NO_AUTO_UPDATE=1` (conftest) so they never touch the real install.
|
|
26
27
|
- `main.py` - Typer app entry point, global flags, command group registration
|
|
27
28
|
- `tests/` - Unit tests
|
|
28
29
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: minitest-cli
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.43.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
|
|
@@ -62,12 +62,6 @@ Both scripts use `uv` if available, or install it automatically.
|
|
|
62
62
|
uv tool install minitest-cli
|
|
63
63
|
```
|
|
64
64
|
|
|
65
|
-
**Homebrew** (macOS):
|
|
66
|
-
|
|
67
|
-
```bash
|
|
68
|
-
brew install minitap-ai/tap/minitest-cli
|
|
69
|
-
```
|
|
70
|
-
|
|
71
65
|
**uvx** (zero-install, all platforms):
|
|
72
66
|
|
|
73
67
|
```bash
|
|
@@ -83,6 +77,33 @@ uv sync
|
|
|
83
77
|
uv run minitest --help
|
|
84
78
|
```
|
|
85
79
|
|
|
80
|
+
### Staying up to date
|
|
81
|
+
|
|
82
|
+
A CLI installed with `uv tool install` or the one-liner keeps itself
|
|
83
|
+
current. When a command sees a newer release on PyPI, it updates the CLI in the
|
|
84
|
+
background and your next command runs the new version. The update waits until
|
|
85
|
+
no other `minitest` command is running, and only installs releases that have
|
|
86
|
+
been out for at least an hour. The same background job refreshes the agent
|
|
87
|
+
skill (`npx skills update minitest-cli`) when it has changed. The next command
|
|
88
|
+
prints one line saying what was updated; the details go to
|
|
89
|
+
`~/.minitest/auto_update.log`.
|
|
90
|
+
|
|
91
|
+
Auto-update never runs in CI (`CI` set), in containers, on Windows, or for
|
|
92
|
+
`uvx` and source checkouts; those keep printing an "Update available" notice.
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
minitest upgrade auto # show the setting, why it is off, the last update
|
|
96
|
+
minitest upgrade auto off # turn it off for this user (saved in ~/.minitest/preferences.json)
|
|
97
|
+
minitest upgrade auto on # turn it back on
|
|
98
|
+
minitest upgrade # update by hand at any time
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
`MINITEST_NO_AUTO_UPDATE=1` also turns it off, and wins over the saved setting.
|
|
102
|
+
|
|
103
|
+
> **Installed with Homebrew?** The `minitap-ai/tap/minitest-cli` formula is
|
|
104
|
+
> retired: it stopped at 0.24.0 and is now disabled. Switch to uv with
|
|
105
|
+
> `brew uninstall minitest-cli && uv tool install minitest-cli`.
|
|
106
|
+
|
|
86
107
|
## Quick Start
|
|
87
108
|
|
|
88
109
|
```bash
|
|
@@ -191,6 +212,7 @@ app defaults.
|
|
|
191
212
|
| `MINITEST_WEBAPP_URL` | Minitest webapp base URL (used for review links) | No (defaults to production) |
|
|
192
213
|
| `MINITEST_SUPABASE_URL` | Supabase project URL used for OAuth login | No (defaults to production) |
|
|
193
214
|
| `MINITEST_SUPABASE_PUBLISHABLE_KEY` | Supabase publishable (anon) key used for OAuth login | No (defaults to production) |
|
|
215
|
+
| `MINITEST_NO_AUTO_UPDATE` | Set to `1` to stop the CLI and agent skill from updating themselves (or run `minitest upgrade auto off`) | No |
|
|
194
216
|
|
|
195
217
|
> The recommended way to set these is to copy `.env.example` to `.env` — the CLI loads `.env` automatically. The shipped `.env.example` already targets the **dev** environment (see below).
|
|
196
218
|
|
|
@@ -28,12 +28,6 @@ Both scripts use `uv` if available, or install it automatically.
|
|
|
28
28
|
uv tool install minitest-cli
|
|
29
29
|
```
|
|
30
30
|
|
|
31
|
-
**Homebrew** (macOS):
|
|
32
|
-
|
|
33
|
-
```bash
|
|
34
|
-
brew install minitap-ai/tap/minitest-cli
|
|
35
|
-
```
|
|
36
|
-
|
|
37
31
|
**uvx** (zero-install, all platforms):
|
|
38
32
|
|
|
39
33
|
```bash
|
|
@@ -49,6 +43,33 @@ uv sync
|
|
|
49
43
|
uv run minitest --help
|
|
50
44
|
```
|
|
51
45
|
|
|
46
|
+
### Staying up to date
|
|
47
|
+
|
|
48
|
+
A CLI installed with `uv tool install` or the one-liner keeps itself
|
|
49
|
+
current. When a command sees a newer release on PyPI, it updates the CLI in the
|
|
50
|
+
background and your next command runs the new version. The update waits until
|
|
51
|
+
no other `minitest` command is running, and only installs releases that have
|
|
52
|
+
been out for at least an hour. The same background job refreshes the agent
|
|
53
|
+
skill (`npx skills update minitest-cli`) when it has changed. The next command
|
|
54
|
+
prints one line saying what was updated; the details go to
|
|
55
|
+
`~/.minitest/auto_update.log`.
|
|
56
|
+
|
|
57
|
+
Auto-update never runs in CI (`CI` set), in containers, on Windows, or for
|
|
58
|
+
`uvx` and source checkouts; those keep printing an "Update available" notice.
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
minitest upgrade auto # show the setting, why it is off, the last update
|
|
62
|
+
minitest upgrade auto off # turn it off for this user (saved in ~/.minitest/preferences.json)
|
|
63
|
+
minitest upgrade auto on # turn it back on
|
|
64
|
+
minitest upgrade # update by hand at any time
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
`MINITEST_NO_AUTO_UPDATE=1` also turns it off, and wins over the saved setting.
|
|
68
|
+
|
|
69
|
+
> **Installed with Homebrew?** The `minitap-ai/tap/minitest-cli` formula is
|
|
70
|
+
> retired: it stopped at 0.24.0 and is now disabled. Switch to uv with
|
|
71
|
+
> `brew uninstall minitest-cli && uv tool install minitest-cli`.
|
|
72
|
+
|
|
52
73
|
## Quick Start
|
|
53
74
|
|
|
54
75
|
```bash
|
|
@@ -157,6 +178,7 @@ app defaults.
|
|
|
157
178
|
| `MINITEST_WEBAPP_URL` | Minitest webapp base URL (used for review links) | No (defaults to production) |
|
|
158
179
|
| `MINITEST_SUPABASE_URL` | Supabase project URL used for OAuth login | No (defaults to production) |
|
|
159
180
|
| `MINITEST_SUPABASE_PUBLISHABLE_KEY` | Supabase publishable (anon) key used for OAuth login | No (defaults to production) |
|
|
181
|
+
| `MINITEST_NO_AUTO_UPDATE` | Set to `1` to stop the CLI and agent skill from updating themselves (or run `minitest upgrade auto off`) | No |
|
|
160
182
|
|
|
161
183
|
> The recommended way to set these is to copy `.env.example` to `.env` — the CLI loads `.env` automatically. The shipped `.env.example` already targets the **dev** environment (see below).
|
|
162
184
|
|
|
@@ -3,8 +3,10 @@
|
|
|
3
3
|
## Overview
|
|
4
4
|
|
|
5
5
|
Releases are automated via GitHub Actions. Pushing a version tag triggers the
|
|
6
|
-
full pipeline: build, publish to PyPI, create a GitHub Release
|
|
7
|
-
Homebrew formula
|
|
6
|
+
full pipeline: build, publish to PyPI, and create a GitHub Release. uv is the
|
|
7
|
+
only distribution channel (the Homebrew formula is retired); users
|
|
8
|
+
on a `uv tool install` pick the release up automatically through auto-update
|
|
9
|
+
once it has been on PyPI for an hour.
|
|
8
10
|
|
|
9
11
|
## Steps
|
|
10
12
|
|
|
@@ -38,8 +40,6 @@ The tag push triggers `.github/workflows/release.yml`, which:
|
|
|
38
40
|
2. **Publish to PyPI** — uses trusted publishing (OIDC), no API token needed
|
|
39
41
|
3. **GitHub Release** — creates a release with auto-generated notes and attaches
|
|
40
42
|
the built artifacts
|
|
41
|
-
4. **Homebrew update** — dispatches an event to `minitap-ai/homebrew-tap` with
|
|
42
|
-
the new version, sdist URL, and SHA256 hash
|
|
43
43
|
|
|
44
44
|
### 4. Verify
|
|
45
45
|
|
|
@@ -52,11 +52,6 @@ minitest --version
|
|
|
52
52
|
|
|
53
53
|
# uvx
|
|
54
54
|
uvx --from minitest-cli@X.Y.Z minitest --version
|
|
55
|
-
|
|
56
|
-
# Homebrew (after tap update completes)
|
|
57
|
-
brew update
|
|
58
|
-
brew install minitap-ai/tap/minitest-cli
|
|
59
|
-
minitest --version
|
|
60
55
|
```
|
|
61
56
|
|
|
62
57
|
## Prerequisites
|
|
@@ -76,11 +71,6 @@ Configure on PyPI at https://pypi.org/manage/project/minitest-cli/settings/publi
|
|
|
76
71
|
|
|
77
72
|
Create a GitHub Actions environment named `pypi` in the repository settings.
|
|
78
73
|
|
|
79
|
-
### Homebrew tap token
|
|
80
|
-
|
|
81
|
-
A `HOMEBREW_TAP_TOKEN` secret must be set in this repository with a GitHub
|
|
82
|
-
personal access token that has write access to `minitap-ai/homebrew-tap`.
|
|
83
|
-
|
|
84
74
|
## Version scheme
|
|
85
75
|
|
|
86
76
|
We follow [Semantic Versioning](https://semver.org/):
|
|
@@ -8,16 +8,13 @@ import httpx
|
|
|
8
8
|
import typer
|
|
9
9
|
|
|
10
10
|
from minitest_cli import __version__
|
|
11
|
+
from minitest_cli.commands.upgrade_auto import auto
|
|
11
12
|
from minitest_cli.utils.output import err_console, print_error, print_success
|
|
12
13
|
from minitest_cli.utils.skill_refresh import UpgradeStatus, check_and_refresh
|
|
13
|
-
from minitest_cli.utils.update_check import
|
|
14
|
-
CHECK_TIMEOUT_SECONDS,
|
|
15
|
-
PYPI_URL,
|
|
16
|
-
_is_brew_install,
|
|
17
|
-
_is_newer,
|
|
18
|
-
)
|
|
14
|
+
from minitest_cli.utils.update_check import CHECK_TIMEOUT_SECONDS, PYPI_URL, _is_newer
|
|
19
15
|
|
|
20
16
|
app = typer.Typer(name="upgrade", help="Upgrade the CLI and refresh the agent skill.")
|
|
17
|
+
app.command("auto")(auto)
|
|
21
18
|
|
|
22
19
|
|
|
23
20
|
def _get_latest_pypi_version() -> str | None:
|
|
@@ -44,31 +41,22 @@ def _upgrade_cli() -> UpgradeStatus:
|
|
|
44
41
|
|
|
45
42
|
err_console.print(f"\n[bold]Upgrading minitest-cli:[/bold] {__version__} → {latest}\n")
|
|
46
43
|
|
|
47
|
-
#
|
|
48
|
-
|
|
49
|
-
|
|
44
|
+
# minitest-cli is distributed through uv only (the Homebrew formula is retired).
|
|
45
|
+
uv_bin = shutil.which("uv")
|
|
46
|
+
if uv_bin:
|
|
47
|
+
cmd = [uv_bin, "tool", "upgrade", "--reinstall", "minitest-cli"]
|
|
50
48
|
else:
|
|
51
|
-
|
|
52
|
-
if uv_bin:
|
|
53
|
-
cmd = [uv_bin, "tool", "upgrade", "--reinstall", "minitest-cli"]
|
|
54
|
-
else:
|
|
55
|
-
cmd = [sys.executable, "-m", "uv", "tool", "upgrade", "--reinstall", "minitest-cli"]
|
|
49
|
+
cmd = [sys.executable, "-m", "uv", "tool", "upgrade", "--reinstall", "minitest-cli"]
|
|
56
50
|
|
|
57
|
-
is_uv = "uv" in cmd[0] or cmd[:2] == [sys.executable, "-m"]
|
|
58
51
|
err_console.print(f"[dim]Running: {' '.join(cmd)}[/dim]\n")
|
|
59
52
|
|
|
60
|
-
# Capture output
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
output
|
|
67
|
-
if output.strip():
|
|
68
|
-
err_console.print(output)
|
|
69
|
-
else:
|
|
70
|
-
result = subprocess.run(cmd, check=False, stdin=subprocess.DEVNULL)
|
|
71
|
-
output = ""
|
|
53
|
+
# Capture output to detect uv's "Nothing to upgrade" false-success.
|
|
54
|
+
result = subprocess.run(
|
|
55
|
+
cmd, check=False, capture_output=True, text=True, stdin=subprocess.DEVNULL
|
|
56
|
+
)
|
|
57
|
+
output = result.stdout + result.stderr
|
|
58
|
+
if output.strip():
|
|
59
|
+
err_console.print(output)
|
|
72
60
|
|
|
73
61
|
if result.returncode != 0:
|
|
74
62
|
print_error("CLI upgrade failed. Try running the command manually.")
|
|
@@ -76,7 +64,7 @@ def _upgrade_cli() -> UpgradeStatus:
|
|
|
76
64
|
|
|
77
65
|
# uv tool upgrade exits 0 with "Nothing to upgrade" when the package
|
|
78
66
|
# isn't managed by it (e.g. editable / dev install).
|
|
79
|
-
if
|
|
67
|
+
if "nothing to upgrade" in output.lower():
|
|
80
68
|
print_error(
|
|
81
69
|
f"Upgrade tool reported nothing to upgrade, but version {__version__} "
|
|
82
70
|
f"is behind {latest}. Try upgrading manually."
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
"""`minitest upgrade auto [on|off]` – show or change background auto-update."""
|
|
2
|
+
|
|
3
|
+
from enum import StrEnum
|
|
4
|
+
from typing import Annotated, Any
|
|
5
|
+
|
|
6
|
+
import typer
|
|
7
|
+
from rich.console import Console
|
|
8
|
+
|
|
9
|
+
from minitest_cli.commands.user_story_helpers import is_json_mode
|
|
10
|
+
from minitest_cli.core.config import Settings, get_settings
|
|
11
|
+
from minitest_cli.utils import auto_update
|
|
12
|
+
from minitest_cli.utils.auto_update_state import (
|
|
13
|
+
log_path,
|
|
14
|
+
read_state,
|
|
15
|
+
save_auto_update_enabled,
|
|
16
|
+
section,
|
|
17
|
+
)
|
|
18
|
+
from minitest_cli.utils.output import print_json, print_success
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class Switch(StrEnum):
|
|
22
|
+
ON = "on"
|
|
23
|
+
OFF = "off"
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def _status(settings: Settings) -> dict[str, Any]:
|
|
27
|
+
reason = auto_update.blocker(settings)
|
|
28
|
+
cli = section(read_state(settings), "cli")
|
|
29
|
+
return {
|
|
30
|
+
"autoUpdate": "off" if reason else "on",
|
|
31
|
+
"reason": reason,
|
|
32
|
+
"installCanUpdate": auto_update.cli_upgrade_supported(),
|
|
33
|
+
"lastUpdate": (
|
|
34
|
+
{"target": cli.get("target"), "status": cli.get("status")}
|
|
35
|
+
if cli.get("target")
|
|
36
|
+
else None
|
|
37
|
+
),
|
|
38
|
+
"log": str(log_path(settings)),
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def _print_status(status: dict[str, Any]) -> None:
|
|
43
|
+
console = Console()
|
|
44
|
+
reason = f" ({status['reason']})" if status["reason"] else ""
|
|
45
|
+
console.print(f"Auto-update: [bold]{status['autoUpdate']}[/bold]{reason}")
|
|
46
|
+
if status["autoUpdate"] == "on" and not status["installCanUpdate"]:
|
|
47
|
+
console.print(
|
|
48
|
+
"This install cannot update itself (it is not a `uv tool install`): "
|
|
49
|
+
"run `minitest upgrade` to update."
|
|
50
|
+
)
|
|
51
|
+
if status["lastUpdate"]:
|
|
52
|
+
last = status["lastUpdate"]
|
|
53
|
+
console.print(f"Last update: {last['target']} ({last['status']})")
|
|
54
|
+
console.print(f"Log: {status['log']}")
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def auto(
|
|
58
|
+
switch: Annotated[
|
|
59
|
+
Switch | None,
|
|
60
|
+
typer.Argument(help="Turn background auto-update on or off; omit to show the setting."),
|
|
61
|
+
] = None,
|
|
62
|
+
) -> None:
|
|
63
|
+
"""Show, or turn on/off, background updates of the CLI and its agent skill.
|
|
64
|
+
|
|
65
|
+
The choice is saved in ~/.minitest/preferences.json. MINITEST_NO_AUTO_UPDATE=1
|
|
66
|
+
and CI environments keep auto-update off whatever is saved here.
|
|
67
|
+
"""
|
|
68
|
+
settings = get_settings()
|
|
69
|
+
if switch is not None:
|
|
70
|
+
save_auto_update_enabled(settings, switch is Switch.ON)
|
|
71
|
+
if not is_json_mode():
|
|
72
|
+
print_success(
|
|
73
|
+
"Auto-update turned on."
|
|
74
|
+
if switch is Switch.ON
|
|
75
|
+
else "Auto-update turned off. `minitest upgrade` still updates by hand."
|
|
76
|
+
)
|
|
77
|
+
status = _status(settings)
|
|
78
|
+
if is_json_mode():
|
|
79
|
+
print_json(status)
|
|
80
|
+
else:
|
|
81
|
+
_print_status(status)
|
|
@@ -84,6 +84,7 @@ def _version_callback(value: bool) -> None:
|
|
|
84
84
|
|
|
85
85
|
@app.callback()
|
|
86
86
|
def main(
|
|
87
|
+
context: typer.Context,
|
|
87
88
|
_version: Annotated[
|
|
88
89
|
bool,
|
|
89
90
|
typer.Option(
|
|
@@ -118,5 +119,5 @@ def main(
|
|
|
118
119
|
ctx.app_flag = app_id # type: ignore[attr-defined]
|
|
119
120
|
ctx.settings = settings # type: ignore[attr-defined]
|
|
120
121
|
|
|
121
|
-
# Non-blocking update check
|
|
122
|
-
check_for_updates(settings)
|
|
122
|
+
# Non-blocking update check; `minitest upgrade` does the update itself.
|
|
123
|
+
check_for_updates(settings, allow_auto_update=context.invoked_subcommand != "upgrade")
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
"""Keep the CLI and its agent skill current without anyone running `minitest upgrade`.
|
|
2
|
+
|
|
3
|
+
When a command sees a newer release on PyPI, it starts a detached worker
|
|
4
|
+
(``auto_update_worker``) and carries on: the worker waits until no minitest
|
|
5
|
+
command is running, upgrades the CLI with `uv tool upgrade` (uv is the only
|
|
6
|
+
distribution channel),
|
|
7
|
+
then refreshes the agent skill. The next command runs the new version.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
import os
|
|
11
|
+
import shutil
|
|
12
|
+
import subprocess
|
|
13
|
+
import sys
|
|
14
|
+
import time
|
|
15
|
+
from dataclasses import dataclass
|
|
16
|
+
from pathlib import Path
|
|
17
|
+
|
|
18
|
+
from minitest_cli import __version__
|
|
19
|
+
from minitest_cli.core.config import Settings
|
|
20
|
+
from minitest_cli.utils.auto_update_state import (
|
|
21
|
+
LOG_MAX_BYTES,
|
|
22
|
+
acquire_lock,
|
|
23
|
+
auto_update_enabled,
|
|
24
|
+
hand_lock_to,
|
|
25
|
+
log_path,
|
|
26
|
+
read_state,
|
|
27
|
+
release_lock,
|
|
28
|
+
section,
|
|
29
|
+
update_section,
|
|
30
|
+
)
|
|
31
|
+
from minitest_cli.utils.versions import is_newer
|
|
32
|
+
|
|
33
|
+
ENV_OPT_OUT = "MINITEST_NO_AUTO_UPDATE"
|
|
34
|
+
OFF_COMMAND = "minitest upgrade auto off"
|
|
35
|
+
RELEASE_COOLDOWN_SECONDS = 3600
|
|
36
|
+
RETRY_AFTER_SECONDS = 24 * 3600
|
|
37
|
+
SKILL_CHECK_INTERVAL_SECONDS = 6 * 3600
|
|
38
|
+
WORKER_MODULE = "minitest_cli.utils.auto_update_worker"
|
|
39
|
+
DOCKERENV_PATH = Path("/.dockerenv")
|
|
40
|
+
_HOME = Path.home()
|
|
41
|
+
_UV_FALLBACKS = (_HOME / ".local/bin/uv", _HOME / ".cargo/bin/uv", Path("/opt/homebrew/bin/uv"))
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
@dataclass(frozen=True)
|
|
45
|
+
class Plan:
|
|
46
|
+
cli_target: str | None
|
|
47
|
+
skill: bool
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def _truthy(value: str | None) -> bool:
|
|
51
|
+
return value is not None and value.strip().lower() not in ("", "0", "false", "no", "off")
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def environment_blocker() -> str | None:
|
|
55
|
+
"""Why auto-update must not run here at all, or None when it may."""
|
|
56
|
+
if _truthy(os.environ.get(ENV_OPT_OUT)):
|
|
57
|
+
return f"{ENV_OPT_OUT} is set"
|
|
58
|
+
if _truthy(os.environ.get("CI")):
|
|
59
|
+
return "running in CI"
|
|
60
|
+
if os.environ.get("KUBERNETES_SERVICE_HOST") or DOCKERENV_PATH.exists():
|
|
61
|
+
return "running in a container"
|
|
62
|
+
if sys.platform == "win32":
|
|
63
|
+
return "not supported on Windows"
|
|
64
|
+
return None
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def blocker(settings: Settings) -> str | None:
|
|
68
|
+
"""Why auto-update is off for this user/environment, or None when it is on."""
|
|
69
|
+
reason = environment_blocker()
|
|
70
|
+
if reason is None and not auto_update_enabled(settings):
|
|
71
|
+
reason = f"turned off with `{OFF_COMMAND}`"
|
|
72
|
+
return reason
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def is_uv_tool_install() -> bool:
|
|
76
|
+
"""True for `uv tool install` (and the one-line installers, which use it).
|
|
77
|
+
|
|
78
|
+
uvx, pip and source checkouts are left alone: they have no receipt.
|
|
79
|
+
"""
|
|
80
|
+
return (Path(sys.prefix) / "uv-receipt.toml").exists()
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def _find_uv() -> str | None:
|
|
84
|
+
found = shutil.which("uv")
|
|
85
|
+
if found:
|
|
86
|
+
return found
|
|
87
|
+
return next((str(path) for path in _UV_FALLBACKS if path.exists()), None)
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def upgrade_command() -> list[str] | None:
|
|
91
|
+
uv = _find_uv()
|
|
92
|
+
return [uv, "tool", "upgrade", "minitest-cli"] if uv else None
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def cli_upgrade_supported() -> bool:
|
|
96
|
+
return is_uv_tool_install() and upgrade_command() is not None
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def plan(settings: Settings, latest: str, released_at: float | None, now: float) -> Plan:
|
|
100
|
+
"""Decide what the background worker should do on this command."""
|
|
101
|
+
state = read_state(settings)
|
|
102
|
+
cli = section(state, "cli")
|
|
103
|
+
attempted = (
|
|
104
|
+
cli.get("target") == latest
|
|
105
|
+
and cli.get("status") != "deferred"
|
|
106
|
+
and now - float(cli.get("startedAt") or 0) < RETRY_AFTER_SECONDS
|
|
107
|
+
)
|
|
108
|
+
settled = released_at is not None and now - released_at >= RELEASE_COOLDOWN_SECONDS
|
|
109
|
+
upgrade = (
|
|
110
|
+
is_newer(latest, __version__) and settled and not attempted and cli_upgrade_supported()
|
|
111
|
+
)
|
|
112
|
+
skill_checked_at = float(section(state, "skill").get("checkedAt") or 0)
|
|
113
|
+
skill_due = now - skill_checked_at >= SKILL_CHECK_INTERVAL_SECONDS
|
|
114
|
+
target = latest if upgrade else None
|
|
115
|
+
return Plan(cli_target=target, skill=skill_due or upgrade)
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
def start(settings: Settings, todo: Plan, now: float) -> bool:
|
|
119
|
+
"""Start the detached worker for ``todo``; False when another update is underway."""
|
|
120
|
+
if not (todo.cli_target or todo.skill) or not acquire_lock(settings):
|
|
121
|
+
return False
|
|
122
|
+
args = [sys.executable, "-m", WORKER_MODULE]
|
|
123
|
+
if todo.cli_target:
|
|
124
|
+
args += ["--cli-target", todo.cli_target]
|
|
125
|
+
update_section(
|
|
126
|
+
settings,
|
|
127
|
+
"cli",
|
|
128
|
+
target=todo.cli_target,
|
|
129
|
+
previous=__version__,
|
|
130
|
+
startedAt=now,
|
|
131
|
+
finishedAt=None,
|
|
132
|
+
status="running",
|
|
133
|
+
notified=False,
|
|
134
|
+
)
|
|
135
|
+
if todo.skill:
|
|
136
|
+
args.append("--skill")
|
|
137
|
+
update_section(settings, "skill", checkedAt=now)
|
|
138
|
+
log = log_path(settings)
|
|
139
|
+
mode = "w" if log.exists() and log.stat().st_size > LOG_MAX_BYTES else "a"
|
|
140
|
+
try:
|
|
141
|
+
with log.open(mode) as handle:
|
|
142
|
+
worker = subprocess.Popen( # noqa: S603 - fixed argv, no shell
|
|
143
|
+
args,
|
|
144
|
+
stdin=subprocess.DEVNULL,
|
|
145
|
+
stdout=handle,
|
|
146
|
+
stderr=subprocess.STDOUT,
|
|
147
|
+
start_new_session=True,
|
|
148
|
+
close_fds=True,
|
|
149
|
+
)
|
|
150
|
+
except OSError:
|
|
151
|
+
release_lock(settings)
|
|
152
|
+
if todo.cli_target:
|
|
153
|
+
update_section(settings, "cli", status="failed", finishedAt=time.time())
|
|
154
|
+
return False
|
|
155
|
+
hand_lock_to(settings, worker.pid)
|
|
156
|
+
return True
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"""Tell the user, once, what the last background update did."""
|
|
2
|
+
|
|
3
|
+
from minitest_cli import __version__
|
|
4
|
+
from minitest_cli.core.config import Settings
|
|
5
|
+
from minitest_cli.utils.auto_update import OFF_COMMAND
|
|
6
|
+
from minitest_cli.utils.auto_update_state import log_path, read_state, section, update_section
|
|
7
|
+
from minitest_cli.utils.versions import is_newer
|
|
8
|
+
|
|
9
|
+
FINISHED_STATUSES = ("done", "failed")
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def pending_notices(settings: Settings) -> list[str]:
|
|
13
|
+
"""Return the notices not shown yet and mark them as shown."""
|
|
14
|
+
state = read_state(settings)
|
|
15
|
+
notices: list[str] = []
|
|
16
|
+
|
|
17
|
+
cli = section(state, "cli")
|
|
18
|
+
target = cli.get("target")
|
|
19
|
+
if target and not cli.get("notified") and cli.get("status") in FINISHED_STATUSES:
|
|
20
|
+
if is_newer(str(target), __version__):
|
|
21
|
+
notices.append(
|
|
22
|
+
f"minitest-cli could not update itself to {target} "
|
|
23
|
+
f"(details: {log_path(settings)}). Run `minitest upgrade`, "
|
|
24
|
+
f"or `{OFF_COMMAND}` to stop trying."
|
|
25
|
+
)
|
|
26
|
+
else:
|
|
27
|
+
notices.append(f"minitest-cli updated itself to {__version__}.")
|
|
28
|
+
update_section(settings, "cli", notified=True)
|
|
29
|
+
|
|
30
|
+
skill = section(state, "skill")
|
|
31
|
+
if not skill.get("notified") and skill.get("status") in ("upgraded", "failed"):
|
|
32
|
+
if skill["status"] == "upgraded":
|
|
33
|
+
notices.append("The minitest-cli agent skill was refreshed to its latest version.")
|
|
34
|
+
else:
|
|
35
|
+
notices.append(
|
|
36
|
+
"The minitest-cli agent skill could not be refreshed "
|
|
37
|
+
f"(details: {log_path(settings)}). Run `minitest upgrade`."
|
|
38
|
+
)
|
|
39
|
+
update_section(settings, "skill", notified=True)
|
|
40
|
+
|
|
41
|
+
return notices
|