testo-core 1.1.1__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.
- testo_core-1.1.1/.gitignore +76 -0
- testo_core-1.1.1/CHANGELOG.md +252 -0
- testo_core-1.1.1/LICENSE +21 -0
- testo_core-1.1.1/PKG-INFO +310 -0
- testo_core-1.1.1/README.md +238 -0
- testo_core-1.1.1/pyproject.toml +166 -0
- testo_core-1.1.1/pytest.ini +29 -0
- testo_core-1.1.1/testo_api/__init__.py +3 -0
- testo_core-1.1.1/testo_api/cycle_execution_manager.py +539 -0
- testo_core-1.1.1/testo_api/dependencies.py +21 -0
- testo_core-1.1.1/testo_api/main.py +162 -0
- testo_core-1.1.1/testo_api/models.py +408 -0
- testo_core-1.1.1/testo_api/routes/__init__.py +1 -0
- testo_core-1.1.1/testo_api/routes/ai.py +100 -0
- testo_core-1.1.1/testo_api/routes/analytics.py +141 -0
- testo_core-1.1.1/testo_api/routes/cycles.py +214 -0
- testo_core-1.1.1/testo_api/routes/dashboard.py +121 -0
- testo_core-1.1.1/testo_api/routes/health.py +46 -0
- testo_core-1.1.1/testo_api/routes/history.py +149 -0
- testo_core-1.1.1/testo_api/security.py +77 -0
- testo_core-1.1.1/testo_core/__init__.py +65 -0
- testo_core-1.1.1/testo_core/cli/__init__.py +5 -0
- testo_core-1.1.1/testo_core/cli/app.py +161 -0
- testo_core-1.1.1/testo_core/cli/cleanup.py +42 -0
- testo_core-1.1.1/testo_core/cli/commands/__init__.py +6 -0
- testo_core-1.1.1/testo_core/cli/commands/clean.py +75 -0
- testo_core-1.1.1/testo_core/cli/commands/config.py +127 -0
- testo_core-1.1.1/testo_core/cli/commands/config_db.py +140 -0
- testo_core-1.1.1/testo_core/cli/commands/diff_cli.py +112 -0
- testo_core-1.1.1/testo_core/cli/commands/doctor.py +161 -0
- testo_core-1.1.1/testo_core/cli/commands/init_cmd.py +65 -0
- testo_core-1.1.1/testo_core/cli/commands/plans.py +92 -0
- testo_core-1.1.1/testo_core/cli/commands/report.py +424 -0
- testo_core-1.1.1/testo_core/cli/commands/run.py +100 -0
- testo_core-1.1.1/testo_core/cli/commands/version.py +18 -0
- testo_core-1.1.1/testo_core/cli/commands/watch.py +135 -0
- testo_core-1.1.1/testo_core/cli/runner.py +211 -0
- testo_core-1.1.1/testo_core/cli/ui/__init__.py +5 -0
- testo_core-1.1.1/testo_core/cli/ui/ci_renderer.py +19 -0
- testo_core-1.1.1/testo_core/cli/ui/console.py +65 -0
- testo_core-1.1.1/testo_core/cli/ui/panels.py +128 -0
- testo_core-1.1.1/testo_core/cli/ui/progress.py +29 -0
- testo_core-1.1.1/testo_core/cli/ui/renderers.py +178 -0
- testo_core-1.1.1/testo_core/cli/ui/summary_dashboard.py +345 -0
- testo_core-1.1.1/testo_core/config/__init__.py +28 -0
- testo_core-1.1.1/testo_core/config/database_section.py +165 -0
- testo_core-1.1.1/testo_core/config/errors.py +29 -0
- testo_core-1.1.1/testo_core/config/loader.py +458 -0
- testo_core-1.1.1/testo_core/config/resolver.py +95 -0
- testo_core-1.1.1/testo_core/config/schema.py +117 -0
- testo_core-1.1.1/testo_core/config/triggers.py +294 -0
- testo_core-1.1.1/testo_core/engine/__init__.py +30 -0
- testo_core-1.1.1/testo_core/engine/events.py +46 -0
- testo_core-1.1.1/testo_core/engine/executor.py +256 -0
- testo_core-1.1.1/testo_core/engine/exit_codes.py +45 -0
- testo_core-1.1.1/testo_core/engine/log_buffer.py +144 -0
- testo_core-1.1.1/testo_core/engine/orchestrator.py +246 -0
- testo_core-1.1.1/testo_core/engine/result.py +51 -0
- testo_core-1.1.1/testo_core/frameworks/__init__.py +21 -0
- testo_core-1.1.1/testo_core/frameworks/base.py +73 -0
- testo_core-1.1.1/testo_core/frameworks/behave_adapter.py +49 -0
- testo_core-1.1.1/testo_core/frameworks/behavex_adapter.py +82 -0
- testo_core-1.1.1/testo_core/frameworks/command_adapter.py +41 -0
- testo_core-1.1.1/testo_core/frameworks/pytest_adapter.py +121 -0
- testo_core-1.1.1/testo_core/history/__init__.py +16 -0
- testo_core-1.1.1/testo_core/history/maintenance.py +46 -0
- testo_core-1.1.1/testo_core/history/read_model.py +52 -0
- testo_core-1.1.1/testo_core/history/report_links.py +45 -0
- testo_core-1.1.1/testo_core/history/snapshots.py +21 -0
- testo_core-1.1.1/testo_core/history/views.py +122 -0
- testo_core-1.1.1/testo_core/mascot/__init__.py +422 -0
- testo_core-1.1.1/testo_core/mascot/__main__.py +30 -0
- testo_core-1.1.1/testo_core/mascot/export_ts.py +51 -0
- testo_core-1.1.1/testo_core/mascot/render.py +114 -0
- testo_core-1.1.1/testo_core/paths.py +102 -0
- testo_core-1.1.1/testo_core/persistence/__init__.py +23 -0
- testo_core-1.1.1/testo_core/persistence/backend.py +21 -0
- testo_core-1.1.1/testo_core/persistence/composite.py +50 -0
- testo_core-1.1.1/testo_core/persistence/db_backend.py +128 -0
- testo_core-1.1.1/testo_core/persistence/failure_context.py +112 -0
- testo_core-1.1.1/testo_core/persistence/health.py +109 -0
- testo_core-1.1.1/testo_core/persistence/json_backend.py +63 -0
- testo_core-1.1.1/testo_core/reporting/__init__.py +11 -0
- testo_core-1.1.1/testo_core/reporting/allure.py +84 -0
- testo_core-1.1.1/testo_core/reporting/allure_cli.py +212 -0
- testo_core-1.1.1/testo_core/reporting/allure_results.py +232 -0
- testo_core-1.1.1/testo_core/reporting/collector.py +144 -0
- testo_core-1.1.1/testo_core/reporting/entry.py +129 -0
- testo_core-1.1.1/testo_core/reporting/exporter.py +151 -0
- testo_core-1.1.1/testo_core/reporting/history_inject.py +76 -0
- testo_core-1.1.1/testo_core/reporting/integrations.py +232 -0
- testo_core-1.1.1/testo_core/reporting/junit_import.py +161 -0
- testo_core-1.1.1/testo_core/reporting/metrics.py +191 -0
- testo_core-1.1.1/testo_core/reporting/metrics_extractor.py +187 -0
- testo_core-1.1.1/testo_core/reporting/native_reports.py +277 -0
- testo_core-1.1.1/testo_core/reporting/paths.py +81 -0
- testo_core-1.1.1/testo_core/reporting/pyramid_data.py +33 -0
- testo_core-1.1.1/testo_core/reporting/pyramid_viz.py +120 -0
- testo_core-1.1.1/testo_core/reporting/report_generator.py +537 -0
- testo_core-1.1.1/testo_core/reporting/reporters/__init__.py +14 -0
- testo_core-1.1.1/testo_core/reporting/reporters/allure_reporter.py +137 -0
- testo_core-1.1.1/testo_core/reporting/reporters/base.py +63 -0
- testo_core-1.1.1/testo_core/reporting/reporters/extent_builder.py +106 -0
- testo_core-1.1.1/testo_core/reporting/reporters/extent_reporter.py +61 -0
- testo_core-1.1.1/testo_core/reporting/reporters/factory.py +122 -0
- testo_core-1.1.1/testo_core/reporting/reporters/orchestrate.py +93 -0
- testo_core-1.1.1/testo_core/reporting/reporters/reportportal_client.py +367 -0
- testo_core-1.1.1/testo_core/reporting/reporters/reportportal_reporter.py +97 -0
- testo_core-1.1.1/testo_core/reporting/reporters/templates/extent_dashboard.html.j2 +244 -0
- testo_core-1.1.1/testo_core/reporting/reporters/testbeats_payloads.py +197 -0
- testo_core-1.1.1/testo_core/reporting/reporters/testbeats_reporter.py +115 -0
- testo_core-1.1.1/testo_core/reporting/server.py +140 -0
- testo_core-1.1.1/testo_core/repository/__init__.py +15 -0
- testo_core-1.1.1/testo_core/repository/adapters.py +137 -0
- testo_core-1.1.1/testo_core/repository/base.py +62 -0
- testo_core-1.1.1/testo_core/repository/db.py +31 -0
- testo_core-1.1.1/testo_core/repository/db_config.py +117 -0
- testo_core-1.1.1/testo_core/repository/factory.py +115 -0
- testo_core-1.1.1/testo_core/repository/models.py +87 -0
- testo_core-1.1.1/testo_core/repository/report_archive_repository.py +90 -0
- testo_core-1.1.1/testo_core/security/__init__.py +15 -0
- testo_core-1.1.1/testo_core/security/redaction.py +53 -0
- testo_core-1.1.1/testo_core/services/__init__.py +86 -0
- testo_core-1.1.1/testo_core/services/ai/__init__.py +33 -0
- testo_core-1.1.1/testo_core/services/ai/config.py +54 -0
- testo_core-1.1.1/testo_core/services/ai/factory.py +18 -0
- testo_core-1.1.1/testo_core/services/ai/integration_settings.py +66 -0
- testo_core-1.1.1/testo_core/services/ai/provider_base.py +54 -0
- testo_core-1.1.1/testo_core/services/ai/providers/__init__.py +4 -0
- testo_core-1.1.1/testo_core/services/ai/providers/anthropic_provider.py +76 -0
- testo_core-1.1.1/testo_core/services/ai/providers/openai_provider.py +78 -0
- testo_core-1.1.1/testo_core/services/ci_provenance.py +84 -0
- testo_core-1.1.1/testo_core/services/cycle_run.py +355 -0
- testo_core-1.1.1/testo_core/services/dashboard_service.py +341 -0
- testo_core-1.1.1/testo_core/services/delta_models.py +61 -0
- testo_core-1.1.1/testo_core/services/delta_service.py +284 -0
- testo_core-1.1.1/testo_core/services/failure_analysis_service.py +192 -0
- testo_core-1.1.1/testo_core/services/failure_context_builder.py +105 -0
- testo_core-1.1.1/testo_core/services/metrics_service.py +41 -0
- testo_core-1.1.1/testo_core/services/report_archive.py +160 -0
- testo_core-1.1.1/testo_core/services/report_archive_diff.py +191 -0
- testo_core-1.1.1/testo_core/services/report_service.py +121 -0
- testo_core-1.1.1/testo_core/services/run_snapshot_diff.py +37 -0
- testo_core-1.1.1/tests/README.md +11 -0
- testo_core-1.1.1/tests/TEST_LAYOUT.md +58 -0
- testo_core-1.1.1/tests/__init__.py +1 -0
- testo_core-1.1.1/tests/_allure_utils.py +41 -0
- testo_core-1.1.1/tests/conftest.py +412 -0
- testo_core-1.1.1/tests/contract/api/test_adhoc_executions_contract.py +98 -0
- testo_core-1.1.1/tests/contract/api/test_ai_contract.py +118 -0
- testo_core-1.1.1/tests/contract/api/test_analytics_contract.py +333 -0
- testo_core-1.1.1/tests/contract/api/test_cycle_executions_contract.py +97 -0
- testo_core-1.1.1/tests/contract/api/test_cycles_contract.py +93 -0
- testo_core-1.1.1/tests/contract/api/test_dashboard_contract.py +136 -0
- testo_core-1.1.1/tests/contract/api/test_history_contract.py +197 -0
- testo_core-1.1.1/tests/contract/api/test_security_contract.py +136 -0
- testo_core-1.1.1/tests/contract/ci/test_tiered_ci_contract.py +48 -0
- testo_core-1.1.1/tests/contract/ci/test_wrapper_contract.py +41 -0
- testo_core-1.1.1/tests/contract/testo_core/test_cli_docs_drift.py +61 -0
- testo_core-1.1.1/tests/contract/testo_core/test_docs_vault.py +78 -0
- testo_core-1.1.1/tests/contract/testo_core/test_exit_code_contract.py +82 -0
- testo_core-1.1.1/tests/contract/testo_core/test_packaging_contract.py +67 -0
- testo_core-1.1.1/tests/contract/testo_core/test_repository_contract.py +42 -0
- testo_core-1.1.1/tests/contract/testo_core/test_run_metadata_contract.py +145 -0
- testo_core-1.1.1/tests/contracts/models.py +76 -0
- testo_core-1.1.1/tests/contracts/test_mock_api_contracts.py +142 -0
- testo_core-1.1.1/tests/e2e/__init__.py +1 -0
- testo_core-1.1.1/tests/e2e/flows/__init__.py +1 -0
- testo_core-1.1.1/tests/e2e/flows/flow_runner.py +39 -0
- testo_core-1.1.1/tests/e2e/flows/flow_scenario.py +42 -0
- testo_core-1.1.1/tests/e2e/flows/test_external_provider_lifecycle.py +78 -0
- testo_core-1.1.1/tests/e2e/flows/test_plugin_mocked_paths.py +78 -0
- testo_core-1.1.1/tests/e2e/provisioners/__init__.py +1 -0
- testo_core-1.1.1/tests/e2e/provisioners/github.py +68 -0
- testo_core-1.1.1/tests/e2e/provisioners/gitlab.py +70 -0
- testo_core-1.1.1/tests/e2e/provisioners/local.py +11 -0
- testo_core-1.1.1/tests/e2e/provisioners/mock_github.py +12 -0
- testo_core-1.1.1/tests/e2e/provisioners/mock_gitlab.py +12 -0
- testo_core-1.1.1/tests/e2e/sandbox_api/test_user_journeys.py +87 -0
- testo_core-1.1.1/tests/e2e/verifiers/__init__.py +1 -0
- testo_core-1.1.1/tests/e2e/verifiers/artifact_bundle.py +32 -0
- testo_core-1.1.1/tests/e2e/verifiers/cleanup_audit.py +10 -0
- testo_core-1.1.1/tests/e2e/verifiers/provider_status.py +10 -0
- testo_core-1.1.1/tests/fixtures/__init__.py +1 -0
- testo_core-1.1.1/tests/fixtures/ci/github_workflow_minimal.yml +13 -0
- testo_core-1.1.1/tests/fixtures/e2e/github_workflow_e2e.yml +9 -0
- testo_core-1.1.1/tests/fixtures/e2e/gitlab_pipeline_e2e.yml +9 -0
- testo_core-1.1.1/tests/fixtures/e2e/local.external.env.sample +10 -0
- testo_core-1.1.1/tests/fixtures/e2e/local.fast.env.sample +5 -0
- testo_core-1.1.1/tests/fixtures/e2e/local.heavy.env.sample +5 -0
- testo_core-1.1.1/tests/fixtures/e2e/sample_plugin.py +5 -0
- testo_core-1.1.1/tests/fixtures/e2e/sample_repo_config.yaml +6 -0
- testo_core-1.1.1/tests/fixtures/engine/__init__.py +233 -0
- testo_core-1.1.1/tests/fixtures/engine/scripts/echo.py +37 -0
- testo_core-1.1.1/tests/fixtures/engine/scripts/hang.py +9 -0
- testo_core-1.1.1/tests/integration/api/test_history_endpoints.py +35 -0
- testo_core-1.1.1/tests/integration/sandbox_api/conftest.py +36 -0
- testo_core-1.1.1/tests/integration/sandbox_api/test_auth_flow.py +32 -0
- testo_core-1.1.1/tests/integration/sandbox_api/test_chaos_flow.py +48 -0
- testo_core-1.1.1/tests/integration/sandbox_api/test_items_flow.py +41 -0
- testo_core-1.1.1/tests/integration/sandbox_api/test_upload_flow.py +46 -0
- testo_core-1.1.1/tests/integration/testo_core/engine/test_subprocess_smoke.py +119 -0
- testo_core-1.1.1/tests/unit/cases/json_payloads.py +22 -0
- testo_core-1.1.1/tests/unit/cases/paths.py +22 -0
- testo_core-1.1.1/tests/unit/cases/strings.py +26 -0
- testo_core-1.1.1/tests/unit/ci/test_e2e_artifact_redaction.py +16 -0
- testo_core-1.1.1/tests/unit/ci/test_export_static_site.py +125 -0
- testo_core-1.1.1/tests/unit/ci/test_github_action_wrapper.py +97 -0
- testo_core-1.1.1/tests/unit/ci/test_gitlab_pages_demo_contract.py +125 -0
- testo_core-1.1.1/tests/unit/ci/test_gitlab_template_contract.py +22 -0
- testo_core-1.1.1/tests/unit/ci/test_marker_tiering_contract.py +26 -0
- testo_core-1.1.1/tests/unit/test_cycle_execution_manager.py +310 -0
- testo_core-1.1.1/tests/unit/test_defaults_and_placeholders.py +21 -0
- testo_core-1.1.1/tests/unit/testo_core/cli/conftest.py +23 -0
- testo_core-1.1.1/tests/unit/testo_core/cli/test_cli_commands_smoke.py +61 -0
- testo_core-1.1.1/tests/unit/testo_core/cli/test_config_discovery.py +127 -0
- testo_core-1.1.1/tests/unit/testo_core/cli/test_run_archive.py +152 -0
- testo_core-1.1.1/tests/unit/testo_core/cli/test_run_ci_ndjson.py +205 -0
- testo_core-1.1.1/tests/unit/testo_core/cli/test_run_exit_codes.py +196 -0
- testo_core-1.1.1/tests/unit/testo_core/cli/test_run_flags.py +226 -0
- testo_core-1.1.1/tests/unit/testo_core/engine/test_executor.py +236 -0
- testo_core-1.1.1/tests/unit/testo_core/engine/test_exit_codes.py +72 -0
- testo_core-1.1.1/tests/unit/testo_core/engine/test_log_buffer.py +115 -0
- testo_core-1.1.1/tests/unit/testo_core/engine/test_orchestrator.py +176 -0
- testo_core-1.1.1/tests/unit/testo_core/engine/test_orchestrator_lifecycle.py +345 -0
- testo_core-1.1.1/tests/unit/testo_core/test_ai_config_model.py +14 -0
- testo_core-1.1.1/tests/unit/testo_core/test_ai_provider_abstraction.py +30 -0
- testo_core-1.1.1/tests/unit/testo_core/test_allure_cli.py +60 -0
- testo_core-1.1.1/tests/unit/testo_core/test_allure_reporter.py +82 -0
- testo_core-1.1.1/tests/unit/testo_core/test_behave_adapter.py +11 -0
- testo_core-1.1.1/tests/unit/testo_core/test_behavex_adapter.py +52 -0
- testo_core-1.1.1/tests/unit/testo_core/test_ci_provenance.py +81 -0
- testo_core-1.1.1/tests/unit/testo_core/test_cli_app.py +23 -0
- testo_core-1.1.1/tests/unit/testo_core/test_cli_clean.py +96 -0
- testo_core-1.1.1/tests/unit/testo_core/test_cli_config_db.py +94 -0
- testo_core-1.1.1/tests/unit/testo_core/test_cli_diff.py +163 -0
- testo_core-1.1.1/tests/unit/testo_core/test_cli_doctor.py +76 -0
- testo_core-1.1.1/tests/unit/testo_core/test_cli_help_panels.py +22 -0
- testo_core-1.1.1/tests/unit/testo_core/test_cli_init.py +79 -0
- testo_core-1.1.1/tests/unit/testo_core/test_cli_report_archive.py +94 -0
- testo_core-1.1.1/tests/unit/testo_core/test_cli_version_flag.py +37 -0
- testo_core-1.1.1/tests/unit/testo_core/test_cli_watch.py +79 -0
- testo_core-1.1.1/tests/unit/testo_core/test_command_adapter.py +265 -0
- testo_core-1.1.1/tests/unit/testo_core/test_config_resolver.py +74 -0
- testo_core-1.1.1/tests/unit/testo_core/test_cycle_config_triggers.py +124 -0
- testo_core-1.1.1/tests/unit/testo_core/test_cycle_run_service.py +253 -0
- testo_core-1.1.1/tests/unit/testo_core/test_dashboard_service.py +202 -0
- testo_core-1.1.1/tests/unit/testo_core/test_database_url_resolution.py +107 -0
- testo_core-1.1.1/tests/unit/testo_core/test_delta_service.py +217 -0
- testo_core-1.1.1/tests/unit/testo_core/test_failure_analysis_service.py +423 -0
- testo_core-1.1.1/tests/unit/testo_core/test_failure_context_builder.py +112 -0
- testo_core-1.1.1/tests/unit/testo_core/test_flow_runner_harness.py +64 -0
- testo_core-1.1.1/tests/unit/testo_core/test_history.py +175 -0
- testo_core-1.1.1/tests/unit/testo_core/test_integrations_branch_matrix.py +116 -0
- testo_core-1.1.1/tests/unit/testo_core/test_integrations_more.py +124 -0
- testo_core-1.1.1/tests/unit/testo_core/test_integrations_unit.py +19 -0
- testo_core-1.1.1/tests/unit/testo_core/test_metrics.py +52 -0
- testo_core-1.1.1/tests/unit/testo_core/test_metrics_advanced.py +26 -0
- testo_core-1.1.1/tests/unit/testo_core/test_metrics_extractor_more.py +47 -0
- testo_core-1.1.1/tests/unit/testo_core/test_metrics_extractor_unit.py +25 -0
- testo_core-1.1.1/tests/unit/testo_core/test_native_report_snapshot.py +73 -0
- testo_core-1.1.1/tests/unit/testo_core/test_native_reports.py +131 -0
- testo_core-1.1.1/tests/unit/testo_core/test_paths.py +43 -0
- testo_core-1.1.1/tests/unit/testo_core/test_paths_behave_native.py +15 -0
- testo_core-1.1.1/tests/unit/testo_core/test_persistence_backends.py +421 -0
- testo_core-1.1.1/tests/unit/testo_core/test_persistence_failure_context.py +126 -0
- testo_core-1.1.1/tests/unit/testo_core/test_pyramid_data.py +97 -0
- testo_core-1.1.1/tests/unit/testo_core/test_pyramid_viz.py +46 -0
- testo_core-1.1.1/tests/unit/testo_core/test_pytest_adapter.py +173 -0
- testo_core-1.1.1/tests/unit/testo_core/test_redaction.py +34 -0
- testo_core-1.1.1/tests/unit/testo_core/test_report_archive.py +124 -0
- testo_core-1.1.1/tests/unit/testo_core/test_report_archive_diff.py +219 -0
- testo_core-1.1.1/tests/unit/testo_core/test_report_generator.py +138 -0
- testo_core-1.1.1/tests/unit/testo_core/test_report_generator_branch_matrix.py +41 -0
- testo_core-1.1.1/tests/unit/testo_core/test_report_generator_helpers.py +28 -0
- testo_core-1.1.1/tests/unit/testo_core/test_report_generator_http.py +28 -0
- testo_core-1.1.1/tests/unit/testo_core/test_report_generator_static_sync.py +53 -0
- testo_core-1.1.1/tests/unit/testo_core/test_report_history_inject.py +117 -0
- testo_core-1.1.1/tests/unit/testo_core/test_report_service_more.py +44 -0
- testo_core-1.1.1/tests/unit/testo_core/test_reporters_config.py +83 -0
- testo_core-1.1.1/tests/unit/testo_core/test_reporting_paths.py +128 -0
- testo_core-1.1.1/tests/unit/testo_core/test_reporting_server.py +32 -0
- testo_core-1.1.1/tests/unit/testo_core/test_repository_factory.py +62 -0
- testo_core-1.1.1/tests/unit/testo_core/test_repository_sqlite.py +115 -0
- testo_core-1.1.1/tests/unit/testo_core/test_run_snapshot_diff.py +84 -0
- testo_core-1.1.1/tests/unit/testo_core/test_services.py +27 -0
- testo_core-1.1.1/tests/unit/testo_core/test_stage_tier_config.py +101 -0
- testo_core-1.1.1/tests/unit/testo_core/test_summary_dashboard.py +55 -0
- testo_core-1.1.1/tests/unit/testo_core/test_triggers.py +235 -0
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
__pycache__/
|
|
2
|
+
*.pyc
|
|
3
|
+
.DS_Store
|
|
4
|
+
.venv/
|
|
5
|
+
venv/
|
|
6
|
+
|
|
7
|
+
# Local secrets (copy from .env.example)
|
|
8
|
+
.env
|
|
9
|
+
|
|
10
|
+
# Default local SQLite DB when DATABASE_URL is unset (testo_core/repository/db_config.py)
|
|
11
|
+
uqo_history.db
|
|
12
|
+
testo_history.db
|
|
13
|
+
|
|
14
|
+
# Generated sandbox DB from the test suite (tests/artifacts/)
|
|
15
|
+
tests/artifacts/*.db
|
|
16
|
+
|
|
17
|
+
# Cursor IDE local state (debug logs, plans, rules, etc.)
|
|
18
|
+
.cursor/
|
|
19
|
+
|
|
20
|
+
# Local e2e test scratch (cleanup ledgers, etc.)
|
|
21
|
+
.artifacts/
|
|
22
|
+
|
|
23
|
+
# Built Python distribution artifacts
|
|
24
|
+
dist/
|
|
25
|
+
build/
|
|
26
|
+
*.egg-info/
|
|
27
|
+
|
|
28
|
+
# Local release-gate run logs
|
|
29
|
+
artifacts/release-gate-*/
|
|
30
|
+
|
|
31
|
+
# Generated report HTML (static/history/ is served by the API for each run's Report Links)
|
|
32
|
+
static/
|
|
33
|
+
|
|
34
|
+
# Persisted run history (SQLite + per-run HTML snapshots)
|
|
35
|
+
artifacts/uqo_run_history.sqlite
|
|
36
|
+
artifacts/testo_sandbox.db
|
|
37
|
+
artifacts/history/
|
|
38
|
+
|
|
39
|
+
# Local/generated artifacts
|
|
40
|
+
.coverage
|
|
41
|
+
coverage.xml
|
|
42
|
+
artifacts/allure-report/
|
|
43
|
+
artifacts/allure-results/
|
|
44
|
+
artifacts/allure-results-archive/
|
|
45
|
+
artifacts/allure-report.zip
|
|
46
|
+
artifacts/metrics.json
|
|
47
|
+
|
|
48
|
+
# Runtime logs
|
|
49
|
+
logs/
|
|
50
|
+
|
|
51
|
+
# Frontend workspace artifacts
|
|
52
|
+
frontend/node_modules/
|
|
53
|
+
frontend/dist/
|
|
54
|
+
|
|
55
|
+
# Root Node tooling (Allure CLI, commitlint)
|
|
56
|
+
node_modules/
|
|
57
|
+
|
|
58
|
+
# Local sample-cycle run output (testo run --cycle sample-*)
|
|
59
|
+
artifacts/sample-behave/
|
|
60
|
+
artifacts/sample-pytests/
|
|
61
|
+
artifacts/sample-all-frameworks/
|
|
62
|
+
artifacts/self-test/
|
|
63
|
+
artifacts/fake-api/
|
|
64
|
+
.testo/
|
|
65
|
+
|
|
66
|
+
# Local test-suite scratch DBs
|
|
67
|
+
tests/artifacts/
|
|
68
|
+
|
|
69
|
+
# Local ReportPortal Postgres data volume
|
|
70
|
+
data/
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
# GitLab Pages demo output (scripts/export_static_site.py + the Pages job)
|
|
74
|
+
/public/
|
|
75
|
+
/.ci-history/
|
|
76
|
+
/.demo/
|
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to `testo-core` will be documented in this file.
|
|
4
|
+
|
|
5
|
+
This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## [Unreleased]
|
|
10
|
+
|
|
11
|
+
## [1.1.1] - 2026-10-19
|
|
12
|
+
|
|
13
|
+
First release meant for PyPI (`pip install testo-core`).
|
|
14
|
+
|
|
15
|
+
### Added
|
|
16
|
+
- Open-source community files: `SECURITY.md` (private vulnerability reporting), `CODE_OF_CONDUCT.md` (Contributor Covenant 2.1), `CITATION.cff`, issue forms (`.github/ISSUE_TEMPLATE/*.yml`, blank issues off, links to Discussions and the security form) and `.github/dependabot.yml` (weekly grouped updates for pip, npm and GitHub Actions, `chore(deps)` commits with the `no-changelog` label; `commitlint.config.js` skips Dependabot's long commit bodies). `CONTRIBUTING.md` gains "Finding something to work on" and a note on the AI-agent files, and its Quickstart link is fixed
|
|
17
|
+
- README: animated walkthroughs of the web UI and of the CLI (`docs/assets/demo/`)
|
|
18
|
+
- `docs/Prompts & Snippets/Setup Prompts.md`: copy-paste prompts for an AI coding assistant to install Testosterone in another project, write its `testosterone.yaml`, run it in GitHub Actions or GitLab CI, open the web UI and troubleshoot. They install from GitHub until `testo-core` is on PyPI. Command Reference no longer calls `doctor`, `clean`, `watch` and `init` unimplemented
|
|
19
|
+
|
|
20
|
+
### Fixed
|
|
21
|
+
- `pip install testo-core` followed by `testo run` crashed with `ModuleNotFoundError: No module named 'sqlalchemy'`: run history is always saved (SQLite by default) but `sqlmodel` was only in the `[db]` extra. It is now a core dependency; `[db]` keeps the Postgres driver and `tomli-w`. A new `package` CI job (`scripts/package_smoke.sh`) installs the built wheel with no extras and runs a cycle, and the publish workflow runs the same check before uploading
|
|
22
|
+
- Compare showed "n/a" / "Unknown" for "Test time (sum)" and "Avg per test" on every run because nothing stored them. Both persistence backends now write `metrics_duration_ms` (sum of per-test Allure durations) and `avg_case_ms` (that sum over the test count, `null` with no tests), plus `test_time_ms` per stage. Runs saved earlier still show "n/a". A new contract test fails when `history/views.py` reads a run metadata key that persistence never writes
|
|
23
|
+
|
|
24
|
+
### Changed
|
|
25
|
+
- Package metadata for PyPI: description, MIT license expression, author, keywords, classifiers and project links (homepage, docs, demo, issues, changelog). The README shown on PyPI has its relative images and links rewritten to GitHub URLs at build time (`hatch-fancy-pypi-readme`), and the sdist now carries only the Python package, its tests and the top-level docs (about 260 KB instead of 3.5 MB)
|
|
26
|
+
- `publish.yml` fails before uploading when the release tag does not match `pyproject.toml`'s version, and runs `twine check --strict`
|
|
27
|
+
- README: PyPI badge and a `pip install testo-core` quickstart
|
|
28
|
+
- Pages demo: the read-only notice is now a dismissible alert with a × button, remembered across reloads, and a "Read-only demo" badge in the header reopens it
|
|
29
|
+
- Detailed architecture diagram (`docs/assets/testosterone-architecture-detailed-{dark,light}.png`, drawn by `scripts/render_architecture_diagram.js`) showing `CycleRunService`, the `history/` read side and the repository; it replaces the six-box picture in the README and leads `docs/Architecture/System Diagram.md`
|
|
30
|
+
- Docs vault: the architecture diagram now has its own note (`docs/Architecture/System Diagram.md`) so it shows in Obsidian and the GitHub wiki, not only the README; Architecture Overview's text sketch is a Mermaid flowchart. New decision note for the vault and wiki sync, the second wave of the 2026-10-07 interview fixes, and this repo's workflows in CI-CD Pipeline Setup. `scripts/docs_vault.py lint --base` accepts a second edit to a note already dated today
|
|
31
|
+
|
|
32
|
+
## [1.1.0] - 2026-10-07
|
|
33
|
+
|
|
34
|
+
One engine behind every surface. The Docker-based second execution stack, the Streamlit UI, MinIO and the `uqo` command are gone; the CLI, the API and CI all run cycles through `CycleRunService`. The release also adds an API security model, a type-checked API, same-cycle run comparison and a read-only demo on GitHub Pages. Upgrading from 1.0: see "Migrating from v1.0" in the README.
|
|
35
|
+
|
|
36
|
+
### Added
|
|
37
|
+
- Docs vault rules: `docs/CLAUDE.md` (schema), `docs/log.md`, frontmatter on every note, and `scripts/docs_vault.py lint` (frontmatter, broken links, wikilinks, orphans, `updated` date on edited notes) as a `docs_vault` CI job and a contract test. `.github/workflows/wiki-sync.yml` regenerates the GitHub wiki from `docs/` on every push to `main` that touches the vault. The root `CLAUDE.md` gains the six second-brain rules, and `docs/Specs & ADRs/` gains decision notes for the 2026-10-06 architecture consolidation and the 2026-10-07 interview fixes
|
|
38
|
+
- Pages demo on GitHub and GitLab: `.github/workflows/pages-demo.yml` (GitHub Pages, `https://<owner>.github.io/<repo>/`) and `.gitlab-ci.yml` (GitLab Pages) each run testosterone's own suite (`self-test` cycle) and the deliberately broken [fake-api](https://github.com/taltal-beep/fake-api) app (`fake-api` cycle), then publishes the React UI as a read-only snapshot of those runs (`scripts/export_static_site.py` freezes the API's own responses; `frontend/src/lib/static-backend.ts` serves them to the unchanged pages). Run history is cached between pipelines. `.github/workflows/mirror-to-gitlab.yml` mirrors `main` to GitLab, inert until configured
|
|
39
|
+
- `frontend` CI job in `ci.yml`: runs the React dashboard's typecheck, vitest suite and production build on every PR (the frontend had no CI coverage)
|
|
40
|
+
- `POST /api/v1/adhoc-executions`: run one framework (`pytest`, `behave`, `behavex`, `command`) against a repo without defining a cycle. It runs as a one-stage `adhoc` cycle through `CycleRunService`, with status and SSE events under `/api/v1/cycle-executions/{id}`
|
|
41
|
+
- Quick Run page in the React frontend (`/quick-run`, under Advanced) built on that endpoint; it replaces the Legacy Execution page
|
|
42
|
+
- Engine run records now store failure evidence for failed runs (failing cases, first traceback, log tail, timeout flag; all redacted) for the AI failure summary, and CI provenance (`ci_provider`, `ci_pipeline_id`, `ci_job_id`, `ci_commit_sha`, `ci_ref_name`) when run in CI
|
|
43
|
+
- After every cycle run, test KPIs are pushed to InfluxDB and/or a Prometheus Pushgateway when `INFLUXDB_*` / `PROMETHEUS_PUSHGATEWAY_URL` are set
|
|
44
|
+
|
|
45
|
+
### Changed
|
|
46
|
+
- Loose `testo_core` root modules moved into their subpackages (no compatibility shims): `db.py` → `repository/db.py`, `db_config.py` → `repository/db_config.py`, `report_generator.py` / `metrics.py` / `metrics_extractor.py` / `integrations.py` → `reporting/`, `triggers.py` → `config/triggers.py`. Only the cross-cutting `paths.py` stays at the root
|
|
47
|
+
- CI type-checks `testo_api` as well as `testo_core` (`mypy testo_core testo_api`, blocking). The AI config routes validate their status payload through Pydantic, and report diffs type the change kind as a `Literal`
|
|
48
|
+
- Pages demo explains itself: the banner says it shows testosterone's self-test and fake-api (whose red is deliberate), only cycles that ran are exported and their Run buttons are disabled with the local `testo run` command, the read-only message no longer names GitLab, and with an optional `ANTHROPIC_API_KEY` the export freezes an AI failure summary per failed run (otherwise the card says summaries are generated live)
|
|
49
|
+
- API access control: CORS now allows only the Vite dev/preview servers by default (`TESTO_CORS_ORIGINS`; credentials only for an explicit origin list, never with `*`) and mutating requests from other browser origins get `403`, optional `TESTO_API_TOKEN` requires a bearer token on mutating requests (the frontend sends `VITE_TESTO_API_TOKEN`), and `testo-api` warns when bound beyond loopback without a token. `ARCHITECTURE.md` gains "Security model" and "Trade-offs and known limits" sections
|
|
50
|
+
- Running a cycle (trigger gate, engine, reporters, native report snapshot, report archive, trigger snapshot) now lives in one application service, `testo_core/services/cycle_run.py` (`CycleRunService`). `testo run` and `POST /api/v1/cycles/{cycle}/executions` both call it, so the API no longer imports private helpers from `testo_core/cli/runner.py`
|
|
51
|
+
- API cycle executions now save the trigger snapshot after a successful triggered run, as `testo run` already did; before, a cycle with `trigger:` started from the dashboard never advanced its snapshot
|
|
52
|
+
- Frontend API types are now generated from FastAPI's OpenAPI schema (`frontend/openapi.json` → `frontend/src/lib/api-schema.ts`) instead of being hand-written; CI's `frontend` job runs `tsc` and fails on a stale schema or generated file
|
|
53
|
+
- `ARCHITECTURE.md` and `README.md` now describe the single execution engine (config → `CycleRunService` → engine → framework adapters → reporting/persistence) with a system diagram, layer table and the typed Pydantic-to-React contract
|
|
54
|
+
- `testo_core/run_history.py` is replaced by the `testo_core/history/` package: `views` (typed run views), `read_model` (queries), `report_links`, `snapshots` and `maintenance`. All of it goes through the run repository, which gains `merge_run_metadata()`; `STATIC_HISTORY_ROOT` moves to `testo_core.paths`
|
|
55
|
+
- GitHub Action and GitLab template now run `testo run --ci` (they called `uqo run --config … --ghost`, which v1.0's `uqo` alias no longer accepted). Action inputs are `config-path`, `cycle`, `ci-mode`, `persist`, `python-version`; `ghost-mode`, `stream-json`, `runner-image`, `runner-prebuilt` and the `run_id` output are gone. GitLab variables are now `TESTO_CONFIG_PATH`, `TESTO_CYCLE`, `TESTO_PERSIST`
|
|
56
|
+
- The React UI names runs by cycle and start time (`fake-api · Oct 7 03:21`) with the short run id as secondary text, on the Dashboard, Runs, Run detail and Compare pages; `GET /api/v1/dashboard/runs/recent` items now include `cycle`. Compare shows Reliability/Performance as tables with coloured deltas and state badges instead of raw `key=value` strings, and its run pickers are grouped and filterable by cycle
|
|
57
|
+
- CI's `format` job now blocks on `mypy testo_core` and `ruff format --check` (both were advisory); the codebase was reformatted once with `ruff format`, and a `ruff-format` pre-commit hook was added
|
|
58
|
+
- A stage's `workers` now does what it says, or says it doesn't: pytest stages get `-n <workers>` when pytest-xdist is installed for the `pytest` on PATH (otherwise one warning and a serial run), `workers:` on a behave or command stage logs a warning, and the API/UI only show workers for frameworks that use them
|
|
59
|
+
- CI's `test` job now enforces coverage (it ran `--no-cov`): `pytest.ini` measures `testo_core` and `testo_api` with branch coverage and fails below 65% (was 50%, `testo_core` only), and `coverage.xml` is uploaded as an artifact. `nightly-external`, `release-gate` and `pr-heavy` pass `--no-cov`: their few marker-selected tests could never meet that project-wide gate, which is why `nightly-external` failed every night. `nightly-external` also reads `TESTO_E2E_*` secrets instead of `UQO_E2E_*` and skips with a notice when none are set
|
|
60
|
+
- Renamed the remaining UQO names in code and UI to Testosterone: tab title, OpenAPI title (`Testosterone API`), and env vars `UQO_*` → `TESTO_*` (`TESTO_SHARED_ALLURE_RESULTS_DIR`, `TESTO_ARTIFACTS_ROOT`, `TESTO_LAST_TEST_TYPE`, `TESTO_RUN_ID`, `TESTO_E2E_*`, runner image build args) with no aliases for the old names. Defaults changed too: `PROMETHEUS_JOB_NAME` is `testo`, metrics are `testo_*` / `testo_test_run`, the default SQLite history file is `testo_history.db`, and the compose Postgres is `testo-postgres` / `testo_admin` / `testo_history`
|
|
61
|
+
|
|
62
|
+
### Removed
|
|
63
|
+
- MinIO support: the `s3` readiness check (`/api/v1/health/ready` reported "degraded" without MinIO credentials), `testo_core/s3_client.py`, `history/s3_snapshots.py` (pre-v1.1 snapshot reads), the pre-v1.1 record shape in `history/views.py`, the `boto3` dependency, and the `minio`, `minio-init`, `allure-sync` and `allure` compose services. `docker-compose.yml` now only provides Postgres
|
|
64
|
+
- The second, Docker-based execution stack: `HeadlessEngineService`, `testo_core/runners.py`, `command_builders.py`, `multi_run.py`, `event_drain.py`, `config_loader.py`, `audit_service.py`, `ghost_policy.py`, `result_management.py`, and the pluggy `orchestrator.py` / `specs.py` / `plugins_builtin.py`. Every run now goes through the cycle engine
|
|
65
|
+
- The v1.0 `uqo run --config <runs.yaml>` contract (`--ghost`, `--no-ghost`, `--json`, `--stream-json`, summary JSON); use `testo run --cycle <name> --ci`
|
|
66
|
+
- The `uqo` console script (`testo_core/cli/deprecated.py`) and the frontend's legacy route redirects (`/history`, `/runner`, `/execution`, `/advanced/execution`); use `testo` and the current routes. Unknown frontend paths now show a not-found page
|
|
67
|
+
- `POST /api/v1/executions`, `GET /api/v1/executions/{id}` and `GET /api/v1/executions/{id}/events`; use `POST /api/v1/adhoc-executions` or `POST /api/v1/cycles/{cycle}/executions`
|
|
68
|
+
- The Streamlit UI (`testo_ui/`, `testo-ui` script, `ui` extra), as scheduled in 1.0.0
|
|
69
|
+
- The `docker` extra and the `pluggy` runtime dependency
|
|
70
|
+
- Run-history writer functions in `run_history.py` (`create_run`, `record_completed_run`, MinIO uploads), the unused `compare_latest_two()` and the `db_path` arguments on history queries
|
|
71
|
+
- Generated run output that was committed by mistake (`artifacts/allure-report*`, `artifacts/allure-results-archive/`, `artifacts/metrics.json`); these paths are now ignored
|
|
72
|
+
- `testo_core/reporting/allure_delta_transform.py`, `allure_history_serve.py` and `allure_summary_widgets.py`: unreferenced modules that could not be imported (they depended on functions no longer in `services/report_archive_diff.py`)
|
|
73
|
+
- Dead code and test-failure injection: `.streamlit/`, `drop_in_hooks/`, `requirements.txt`, `deploy/nginx/`, `examples/gitlab/`, the unused GitLab tier templates, `sample_target_repo/random_fail.py` and the `sample-all-frameworks-stochastic` cycle, and the `UQO_FLAKY_DEMO` / `SANDBOX_API_FLAKY_P` switches in testosterone's own suite. `testo_core/sandbox_api.py` (a uvicorn launcher for the sample mock API, used only by one black-box test on a fixed port) is gone with that test, so it no longer ships in the wheel
|
|
74
|
+
|
|
75
|
+
### Fixed
|
|
76
|
+
- Dashboard and Compare badges say "1 improvement" / "1 regression" instead of "1 improvements"
|
|
77
|
+
- `release-gate.yml` reads the `TESTO_E2E_*` repository secrets, matching the nightly job, instead of the old `UQO_E2E_*` names
|
|
78
|
+
- Errors in I/O and reporting paths are no longer swallowed silently: `except Exception: pass` sites in `testo_core/` and `testo_api/` now catch the specific exceptions they expect and log with the module logger, and the deliberate catch-alls (orchestrator, reporter factory, API routes) log with a traceback. A failed BehaveX HTML report now sets the stage's `error` and is written to `run.log`, and a failed Git trigger evaluation logs a warning and says so in the trigger `reason` (exit codes unchanged)
|
|
79
|
+
- The frontend's top nav overflowed the page at phone width. Below 640px the nav links and the Advanced menu now collapse into a menu button (`aria-expanded`, closes on navigation and Escape), and page gutters shrink to 16px; no page of the demo scrolls sideways at 390px any more
|
|
80
|
+
- Dashboard trends and "Compare latest two" (dashboard and Runs page) compared the latest run with whatever ran before it, even another cycle; the baseline is now the previous run of the same cycle, and the dashboard names it. A cycle whose stage crashed without producing results no longer reports the other stages' pass rate (often 100%) as its health
|
|
81
|
+
- The API's execution registry kept every execution in memory forever and each SSE viewer held a worker thread while polling `events.ndjson` every 0.2 s. Finished executions beyond `TESTO_MAX_FINISHED_EXECUTIONS` (default 200) are now evicted (their status/events endpoints return 404 pointing to `/api/v1/runs`); the SSE tail is an async generator with poll backoff (0.1 s to 2 s) that closes right after the run's own last event (not the next run's, which shares `events.ndjson`) or when the client disconnects, and no longer drops a line caught mid-write
|
|
82
|
+
- The test pyramid (`testo report pyramid`, `/api/v1/runs/{id}/pyramid`) bucketed a run by the tiers in the *current* `testosterone.yaml`, so renaming a stage re-counted old runs as "unit". Run records now store each stage's `tier`; only older records without one fall back to the YAML
|
|
83
|
+
- A `command` stage's `junit_xml:` reports were never imported by `testo run` or the API, so the stage showed 0 tests and PASS. Cycle resolution and the `--workers` override rebuilt each stage without its `junit_xml` and `tier`; they now copy the stage with `dataclasses.replace`
|
|
84
|
+
- Pytest stages ignored the target repo's own pytest config (`pythonpath`, markers) when the target sat inside another pytest project, such as a repo cloned into the testosterone checkout in CI, so tests failed to import the target's code. The adapter passed `--alluredir <path>` as two tokens, and pytest counted the results path when choosing its rootdir; it now passes `--alluredir=<path>`
|
|
85
|
+
- Compare's test-level changes were always empty for two runs of the same cycle, and a run's artifact download returned whichever run of that cycle came last. Run records pointed `snapshot_dir` at the shared `artifacts/<cycle>/` tree, which every run overwrites; each run now keeps its own copy at `static/history/<run_id>/artifacts/`
|
|
86
|
+
- Frontend typecheck errors surfaced by the generated types: `/health/ready` is typed `"ready" | "degraded"` as the API returns, and `StatusPill` handles a `null` status
|
|
87
|
+
- `mypy testo_core` reports 0 errors, down from 59: reporters take a typed Rich `Console`, `testo report` narrows its optional open path before use, and the persistence, repository and CLI UI code is fully annotated
|
|
88
|
+
- `equipment: behavex`: every BehaveX stage failed at startup with `OSError: AF_UNIX path too long`, because BehaveX points `TEMP` at its output folder and the multiprocessing socket landed there; the adapter now pins `TMPDIR` to the system temp dir
|
|
89
|
+
- API errors surfaced in the UI as `API error <status>`; the client now shows the message the API returned, and the Run detail page reports a failed AI-summary request instead of swallowing it
|
|
90
|
+
- Run detail, dashboard and compare showed a wall duration of 0 ms for every cycle run; engine-sourced records store `duration_s`, which the history view now falls back to
|
|
91
|
+
|
|
92
|
+
---
|
|
93
|
+
|
|
94
|
+
## [1.0.0] - 2026-09-27
|
|
95
|
+
|
|
96
|
+
First public release. Published to PyPI (`testo-core`), GHCR (`testo-runner`), and JFrog Artifactory.
|
|
97
|
+
|
|
98
|
+
### Deprecated
|
|
99
|
+
- `testo-ui` / Streamlit interface: prints a deprecation notice on stderr and is scheduled for removal in v1.1. The React frontend (`frontend/`) is the official UI.
|
|
100
|
+
- `uqo` CLI alias: continues to forward to `testo`; removal in a future release.
|
|
101
|
+
|
|
102
|
+
### Added
|
|
103
|
+
- `.pre-commit-config.yaml`: local `ruff`, changelog-format, and whitespace/YAML/TOML hooks (`pre-commit install` to enable)
|
|
104
|
+
- `mypy` type-check tooling: `[tool.mypy]` config in `pyproject.toml`, advisory step in `ci.yml`'s `format` job
|
|
105
|
+
- Extended `[tool.ruff.lint]` selection (added `UP`, `B`) and made `ruff check` blocking in `ci.yml` now that the tree is clean
|
|
106
|
+
- `changelog_required` CI gate in `ci.yml`: fails PRs with non-doc changes that don't touch `CHANGELOG.md` (escape hatch: `no-changelog` label)
|
|
107
|
+
- `commitlint` CI check (`.github/workflows/commitlint.yml`, `commitlint.config.js`) enforcing Conventional Commits on PR commit messages
|
|
108
|
+
- `changelog-on-main.yml`: AI-drafted `CHANGELOG.md [Unreleased]` entries on push to `main`, gated by `scripts/check_changelog_format.py` — see `docs/changelog_automation_policy.md` for the review-step tradeoff and required secrets/branch-protection setup
|
|
109
|
+
- `CONTRIBUTING.md`, `.github/PULL_REQUEST_TEMPLATE.md`, `.github/ISSUE_TEMPLATE/` (bug report, feature request), and `CODEOWNERS`
|
|
110
|
+
- Root-level `CLAUDE.md` pointing any directly-invoked AI agent at `docs/Index.md` and the Agent Context Guide
|
|
111
|
+
- Persistence module with `PersistenceBackend` protocol, JSON and DB backends
|
|
112
|
+
- Single-sourced `EngineExitCode` across modern and legacy execution stacks
|
|
113
|
+
- Contract tests asserting exit code consistency between stacks
|
|
114
|
+
- Execution stack boundary documentation in Architecture Overview
|
|
115
|
+
- `_SENSITIVE_KEY_PATTERN` in `redaction.py` to detect sensitive mapping keys (#35)
|
|
116
|
+
- `_redacted_context_text()` in `failure_context_builder.py` for structured metadata redaction (#35)
|
|
117
|
+
- Allure failure context wiring in `record_completed_run()` for run recording (#35)
|
|
118
|
+
- `equipment: command`: run any test runner (Jest, Playwright, Maestro, `go test`, ...) as a stage. `args` is the full argv
|
|
119
|
+
- Stage key `junit_xml` (glob or list, relative to `target_repo`): JUnit XML written by the stage is converted into Allure results after it exits, so non-Allure runners count in summaries, health % and every reporter (`testo_core/reporting/junit_import.py`)
|
|
120
|
+
- `artifactory-publish.yml`: mirrors the release to JFrog Artifactory (PyPI + Docker repos), inert until `ARTIFACTORY_URL` is set — see `docs/Processes & Guides/Publishing to Artifactory.md`
|
|
121
|
+
|
|
122
|
+
### Changed
|
|
123
|
+
- `--no-persist` / `--persist` CLI flags with clarified semantics
|
|
124
|
+
- `classify_exit_code` consolidated into `engine/exit_codes.py`
|
|
125
|
+
- Literal exit code constants in CLI replaced with `EngineExitCode` enum
|
|
126
|
+
|
|
127
|
+
### Fixed
|
|
128
|
+
- Sprint 2 release gate execution across all 4 phases
|
|
129
|
+
- Contract test assertion mismatch (`--plan` vs `--cycle`)
|
|
130
|
+
- Allure CLI unit test mock for `resolve_allure_command`
|
|
131
|
+
- `publish.yml`: post-publish verification installed `testo-core==v1.0.0` from the raw git tag, which is not a valid version specifier; the leading `v` is now stripped
|
|
132
|
+
- `docker-publish.yml`: Trivy scan and verify steps referenced an image tag that never existed (`docker/metadata-action` strips the `v`); both now use the resolved metadata version
|
|
133
|
+
- `docker-publish.yml`: the `latest` tag was gated on `is_default_branch`, which is never true for a release event, so `latest` would never have been published
|
|
134
|
+
- `.gitattributes`: GitHub reported the repository as HTML because the generated 3.2 MB `artifacts/allure-report/index.html` outweighed all authored Python and TypeScript; generated and vendored paths are now excluded from language statistics
|
|
135
|
+
- `Dockerfile.testo-runner`: the image ran as root, which fails the release workflow's blocking Trivy config scan (DS002, HIGH); it now runs as an unprivileged `testo` user, and the entrypoint is `testo` instead of the deprecated `uqo` alias
|
|
136
|
+
|
|
137
|
+
---
|
|
138
|
+
|
|
139
|
+
## [0.1.0] — Phase 1–4 Feature Complete
|
|
140
|
+
|
|
141
|
+
### Phase 4: BYOK AI Failure Summaries
|
|
142
|
+
|
|
143
|
+
*AI-powered test failure analysis with bring-your-own-key provider support.*
|
|
144
|
+
|
|
145
|
+
#### Added
|
|
146
|
+
- `testo_core/services/failure_analysis_service.py` — context-aware AI failure summary generation
|
|
147
|
+
- `PUT /api/v1/ai/config` — runtime AI provider/model configuration (memory-only key storage)
|
|
148
|
+
- `GET /api/v1/runs/{run_id}/ai-summary` — cached AI summary retrieval
|
|
149
|
+
- `POST /api/v1/runs/{run_id}/ai-summary:generate` — on-demand summary generation for failed runs
|
|
150
|
+
- `GET /api/v1/ai/config/status` — non-secret AI configuration status endpoint
|
|
151
|
+
- React AI Settings page (`/settings/ai`) — provider config, key management, model selection
|
|
152
|
+
- AI summary display on Run Detail page (`/runs/:runId`)
|
|
153
|
+
- AI summary caching — generate once, retrieve cached on refresh
|
|
154
|
+
- AI failure context capture tests
|
|
155
|
+
- Passing-run AI summary skip regression test
|
|
156
|
+
|
|
157
|
+
#### Security
|
|
158
|
+
- Raw API keys never returned by backend responses
|
|
159
|
+
- Runtime key input memory-only by default (not persisted to DB/files)
|
|
160
|
+
- Token-like values redacted from internal error surfaces before transport
|
|
161
|
+
- AI integration explicit opt-in (`enabled=false` by default)
|
|
162
|
+
|
|
163
|
+
#### Fixed
|
|
164
|
+
- AI summary refresh data loss on forced refresh failure (#32)
|
|
165
|
+
- AI failure summary and context builder regression coverage (#33, #34)
|
|
166
|
+
|
|
167
|
+
---
|
|
168
|
+
|
|
169
|
+
### Phase 3: Unified Dashboard, Delta Engine, Frontend Migration
|
|
170
|
+
|
|
171
|
+
*React frontend, run comparison analytics, and unified dashboard.*
|
|
172
|
+
|
|
173
|
+
#### Added
|
|
174
|
+
- FastAPI backend (`testo_api/`) — thin adapter over `HeadlessEngineService`
|
|
175
|
+
- React frontend (`frontend/`) — Vite + React + Tailwind dashboard
|
|
176
|
+
- Dashboard overview page (`/`) — KPI cards, trend badges, drill-down links
|
|
177
|
+
- Delta comparison engine (`testo_core/services/delta_service.py`) — regression/improvement classification
|
|
178
|
+
- Compare page (`/compare`) — run selection and delta visualization
|
|
179
|
+
- SSE client (`frontend/src/lib/sse-client.ts`) — real-time execution log streaming
|
|
180
|
+
- `GET /api/v1/dashboard/overview` — unified dashboard payload endpoint
|
|
181
|
+
- `GET /api/v1/analytics/delta` — core-owned run delta comparison endpoint
|
|
182
|
+
- `POST /api/v1/executions` — create run execution job endpoint
|
|
183
|
+
- `GET /api/v1/executions/{id}/events` — SSE stream for log/result/summary events
|
|
184
|
+
- Health probes: `GET /api/v1/health/live`, `GET /api/v1/health/ready`
|
|
185
|
+
- Degraded-data behavior (n/a display, degraded banner, missing report links)
|
|
186
|
+
- Report DB archives, diff CLI, Allure history, hybrid cycles
|
|
187
|
+
- Report archive extraction path hardening (#28, #30)
|
|
188
|
+
- Report archive diff regression tests (#27, #29)
|
|
189
|
+
- Execution accepted-status regression test (#26)
|
|
190
|
+
- Frontend unit tests (Vitest) and E2E test harness
|
|
191
|
+
|
|
192
|
+
#### Fixed
|
|
193
|
+
- Race condition in 202 Accepted response status for `/executions`
|
|
194
|
+
|
|
195
|
+
---
|
|
196
|
+
|
|
197
|
+
### Phase 2: CI Integrations, Ghost Mode, Runner Image
|
|
198
|
+
|
|
199
|
+
*CI wrappers, headless ghost execution, and prebuilt Docker runner.*
|
|
200
|
+
|
|
201
|
+
#### Added
|
|
202
|
+
- GitHub Action wrapper (`ariel-evn/uqo-action@v1`) with typed inputs/outputs
|
|
203
|
+
- GitLab CI template (`ci/gitlab/testo.gitlab-ci.yml`)
|
|
204
|
+
- Ghost mode — CI auto-detection for GitHub, GitLab, Buildkite, CircleCI, Jenkins, Azure Pipelines
|
|
205
|
+
- `--ghost` / `--no-ghost` / `--ci` CLI flags with precedence rules
|
|
206
|
+
- `Dockerfile.testo-runner` — prebuilt runner image for CI execution
|
|
207
|
+
- Configurable runner image path (`UQO_RUNNER_IMAGE`)
|
|
208
|
+
- NDJSON event streaming (`--stream-json`) for CI log consumption
|
|
209
|
+
- Ghost summary and NDJSON contract tests
|
|
210
|
+
- CI provenance unit tests
|
|
211
|
+
- GitHub Action and GitLab wrapper contract tests
|
|
212
|
+
|
|
213
|
+
#### Changed
|
|
214
|
+
- Renamed `uqo`-prefixed CI files to `testo`-prefixed
|
|
215
|
+
|
|
216
|
+
---
|
|
217
|
+
|
|
218
|
+
### Phase 1: Foundation
|
|
219
|
+
|
|
220
|
+
*Core engine, CLI, packaging, database adapters, Allure reporting.*
|
|
221
|
+
|
|
222
|
+
#### Added
|
|
223
|
+
- `testo_core/` — config-driven orchestration engine reading `testosterone.yaml`
|
|
224
|
+
- `testo` CLI entrypoint (via Typer) with `run`, `report`, `cycles`, `config` subcommands
|
|
225
|
+
- `uqo` legacy CLI alias (deprecated)
|
|
226
|
+
- Framework adapters: `PytestAdapter`, `BehaveAdapter`, `BehaveXAdapter`
|
|
227
|
+
- Repository pattern (`testo_core/repository/`) — SQLite default, Postgres/MySQL optional
|
|
228
|
+
- Allure reporting pipeline with per-framework isolation and unified reports
|
|
229
|
+
- MinIO S3 artifact storage (`testo_core/s3_client.py`)
|
|
230
|
+
- Docker-based ephemeral test execution (`testo_core/runners.py`)
|
|
231
|
+
- Dockerless local fallback when Docker is unavailable
|
|
232
|
+
- Streamlit UI (`testo_ui/`) for interactive execution and history
|
|
233
|
+
- Pluggy-based plugin system for drop-in runner extensions
|
|
234
|
+
- Shared headless engine service (`testo_core/services/headless_engine.py`)
|
|
235
|
+
- Hatchling-based packaging (`pyproject.toml`) with extras: `ui`, `api`, `db`, `docker`, `metrics`, `dev`
|
|
236
|
+
- Stable exit codes: 0 (success), 1 (test failure), 2 (invalid input), 3 (infra failure), 4 (internal error)
|
|
237
|
+
- Crash recovery: orphaned `RUNNING` rows auto-marked `FAILED` on startup
|
|
238
|
+
- Container timeout safety net (`UQO_CONTAINER_TIMEOUT_S`)
|
|
239
|
+
- Docker Compose infrastructure: Postgres, MinIO, Allure static host, Allure sync
|
|
240
|
+
|
|
241
|
+
#### Fixed
|
|
242
|
+
- Docker runner path mapping
|
|
243
|
+
- Mock API and built-in Pluggy hooks restoration
|
|
244
|
+
- Multi-run batch locking until complete
|
|
245
|
+
- Multi-run polling active until batch ends
|
|
246
|
+
|
|
247
|
+
---
|
|
248
|
+
|
|
249
|
+
[Unreleased]: https://github.com/taltal-beep/testosterone/compare/v1.1.0...HEAD
|
|
250
|
+
[1.1.0]: https://github.com/taltal-beep/testosterone/compare/v1.0.0...v1.1.0
|
|
251
|
+
[1.0.0]: https://github.com/taltal-beep/testosterone/compare/v0.1.0...v1.0.0
|
|
252
|
+
[0.1.0]: https://github.com/taltal-beep/testosterone/releases/tag/v0.1.0
|
testo_core-1.1.1/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Testosterone contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|