Orchestrata Ultimate › Tests › Reference › deploy
Tests reference — tests/deploy
tests/deploy — 37 test modules, 246 test functions. Source tree: tests/deploy at commit 8a2cb42ad. Generated from the tests AST snapshot by scripts/gen-data-pages.py.
Prose pending.
Modules
| Module | Tests | Covers |
|---|---|---|
_bolt_peer.py |
0 | 0 |
_install_orchestrata_support.py |
0 | 0 |
_ship_support.py |
0 | 0 |
test_ast_daemon_unit.py |
7 | 0 |
test_claude_env_install.py |
6 | 0 |
test_deploy_assets.py |
9 | 0 |
test_deploy_script.py |
12 | 0 |
test_deploy_verification.py |
7 | 0 |
test_envrc_toolchain.py |
6 | 0 |
test_gitlab_runner_executor_deploy.py |
19 | 0 |
test_install_gitlab_runner_executor.py |
5 | 0 |
test_install_orchestrata.py |
5 | 0 |
test_install_orchestrata_cc.py |
2 | 0 |
test_install_orchestrata_rollback.py |
3 | 0 |
test_install_orchestrata_secrets.py |
4 | 0 |
test_install_orchestrata_toolchain.py |
3 | 0 |
test_install_orchestrata_units.py |
3 | 0 |
test_install_orchestrata_version.py |
1 | 2 |
test_install_tools.py |
9 | 0 |
test_kg_ready.py |
11 | 0 |
test_kg_ready_e2e.py |
7 | 0 |
test_kg_ready_routing.py |
5 | 0 |
test_prod_profile_gateway_bind.py |
3 | 0 |
test_provisioner_tarball_default.py |
3 | 0 |
test_repoint_venv.py |
5 | 0 |
test_restart_tool_instances.py |
7 | 0 |
test_retire_plain_units.py |
16 | 0 |
test_ship.py |
9 | 0 |
test_ship_evidence.py |
6 | 0 |
test_ship_gates.py |
11 | 1 |
test_ship_master.py |
9 | 0 |
test_ship_merge_master.py |
10 | 0 |
test_ship_push_state.py |
2 | 0 |
test_ship_source_id.py |
9 | 0 |
test_systemd_install.py |
15 | 0 |
test_toolchain_sh.py |
10 | 0 |
test_tools_vendor_manifest.py |
7 | 0 |
Module details
tests/deploy/_bolt_peer.py
source · 0 tests · 212 lines
Real Bolt-peer fixtures for tests/deploy/test_kg_ready.py, built from
tests/deploy/_install_orchestrata_support.py
source · 0 tests · 141 lines
Shared fixtures/helpers for the
deploy/install-orchestrata.shtests
tests/deploy/_ship_support.py
source · 0 tests · 88 lines
Shared fixtures/helpers for the
deploy/ship.shtests (U-SIZE-D split of
tests/deploy/test_ast_daemon_unit.py
source · 7 tests · 144 lines
The two daemon systemd templates execute DEPLOYED code only (ADR-0067 P3).
| Kind | Name | Line | Description |
|---|---|---|---|
| function | test_exec_start_runs_the_deployed_launcher |
42 | |
| function | test_unit_text_never_references_a_checkout_venv |
49 | |
| function | test_working_directory_is_the_deployment_never_the_checkout |
56 | |
| function | test_an_instance_for_a_vanished_checkout_fails_loudly |
62 | |
| function | test_memory_ceiling_is_set_and_high_stays_below_it |
69 | |
| function | test_every_instance_specifier_keeps_its_leading_slash |
78 | %I alone drops the leading / (systemd-escape --path strips it). |
| function | test_a_rendered_instance_passes_systemd_analyze_verify |
89 | The template, pointed at a tmp deployment prefix, verifies cleanly. |
tests/deploy/test_claude_env_install.py
source · 6 tests · 169 lines
Tests for
claude-env/install.sh— the fresh-machine entry point.
| Kind | Name | Line | Description |
|---|---|---|---|
| function | test_the_duplicate_bundle_is_gone |
54 | A regression fence against the second source of truth coming back. |
| function | test_it_delegates_the_config_layer_to_the_verifying_installer |
63 | The delegation itself — the whole point of the change. |
| function | test_CLAUDE_HOME_reaches_the_delegate_as_a_prefix |
74 | A bug caught before it shipped, and worth a permanent test. |
| function | test_a_missing_free_threaded_interpreter_fails_with_the_remedy |
90 | Convention 1, checked where the fix is expensive. |
| function | test_the_preflight_lists_every_missing_tool_at_once |
139 | SPEC-108 FR-002: fail fast, before any mutation, naming them ALL. |
| function | test_each_required_tool_is_checked |
158 | The list is what the DELEGATE needs, which is not what this script needed |
tests/deploy/test_deploy_assets.py
source · 9 tests · 271 lines
Smoke floor for the deploy assets that no Python imports: every shell
| Kind | Name | Line | Description |
|---|---|---|---|
| function | test_the_asset_inventory_is_not_empty |
116 | A glob that silently matches nothing would turn every test below into |
| function | test_shell_asset_parses |
126 | |
| function | test_service_unit_is_structurally_a_service |
138 | |
| function | test_a_kg_gated_unit_declares_the_prod_profile |
155 | Since ADR-0066 .env is secrets-only, so a unit that gates on |
| function | test_gateway_kernel_probe_uses_the_deployed_venv_interpreter |
176 | D42 (2026-10-12): the gateway unit's kernel-ready ExecStartPre must |
| function | test_timer_unit_triggers_and_targets_timers |
199 | |
| function | test_python_asset_compiles |
208 | compile(), not import: the committed shebang of a deploy-side asset |
| function | test_gitlab_runner_unit_renders_without_placeholders_or_a_hardcoded_binary |
215 | Floor for U-T17: the rendered unit must not still be a template, and |
| function | test_enroll_orchgraph_answers_help |
257 |
tests/deploy/test_deploy_script.py
source · 12 tests · 272 lines
U-T16: close the reviewer-confirmed deploy-script findings that
ship
| Kind | Name | Line | Description |
|---|---|---|---|
| function | test_touched_deploy_script_is_syntactically_valid_bash |
51 | bash -n parses without executing -- catches the crash class (an |
| function | test_provision_environments_with_no_argument_exits_2_with_usage_on_stderr |
68 | No default target: the old TARGET="${1:-all}" meant a forgotten |
| function | test_provision_environments_no_longer_defaults_target_to_all |
89 | Static guard against the exact regression: TARGET="${1:-all}" must |
| function | test_deploy_sh_passes_ref_to_install_tools |
102 | --ref pinned ~/.claude and the fleet but not /opt/orchestrata-tools -- |
| function | test_deploy_sh_calls_the_gitlab_runner_executor_installer |
112 | install-gitlab-runner-executor.sh existed but deploy.sh -- the ONE |
| function | test_deploy_sh_never_reinvokes_itself_via_bash_dollar_zero |
126 | bash "$0" --ref "$SHA" --verify reinvokes whatever file happened to |
| function | test_no_committed_shebang_under_deploy_names_a_workspace_checkout |
155 | A shebang that names a developer's own checkout (e.g. |
| function | test_kernel_ready_shebang_is_portable |
173 | The specific file the finding named: it used to point at the |
| function | test_shebang_rewrite_uses_an_exact_match_not_a_prefix_match |
187 | The old grep -rl '^#!$REPO' matched by PREFIX: a sibling checkout |
| function | test_gateway_overrides_printf_binds_wildcard_and_owns_gateway_host |
218 | D43 (measured 2026-10-12, container app, project orchestrata-test): |
| function | test_kernel_and_gateway_are_restarted_not_just_enabled_now |
242 | systemctl enable --now is a no-op on a unit that is already |
| function | test_restart_happens_after_the_code_and_version_are_in_place |
261 | Ordering guard: the restart must come after the VERSION promote and |
tests/deploy/test_deploy_verification.py
source · 7 tests · 180 lines
A deploy must not claim to have happened before it has been verified.
| Kind | Name | Line | Description |
|---|---|---|---|
| function | test_the_deploy_record_is_staged_then_promoted_after_verifying |
47 | |
| function | test_nothing_writes_the_deploy_record_directly |
74 | Staging is only worth anything if it is the ONLY way VERSION appears. |
| function | test_the_plugin_check_compares_bytes_not_just_the_pin |
92 | installed_plugins.json is metadata; the cache content is what runs. |
| function | test_the_plugin_content_check_refuses_a_vacuous_pass |
112 | Zero files compared must fail, not pass. |
| function | test_verify_mode_does_not_mutate_the_thing_it_judges |
123 | --verify is documented as "change nothing" and must be. |
| function | test_the_tools_installer_does_not_execute_the_pytest_plugin |
145 | /opt/orchestrata-tools ships neo4j + watchfiles and no pytest. |
| function | test_the_tools_installer_proves_the_reader_runs_without_pytest |
167 | The reader IS the code path the deployed tools execute, so run it. |
tests/deploy/test_envrc_toolchain.py
source · 6 tests · 160 lines
.envrc + env/toolchain.env — the shell side of the ONE toolchain declaration.
| Kind | Name | Line | Description |
|---|---|---|---|
| function | test_envrc_exports_no_compiler |
45 | A bare export CC=/export CXX= in .envrc is the defect this change |
| function | test_envrc_loads_the_toolchain_declaration_last |
56 | The declaration is dotenv'd LAST: .env and the profile overlay are |
| function | test_the_declaration_names_absolute_executables |
68 | The tracked declaration, parsed through the production reader, names |
| function | test_the_declared_swipl_is_the_profile_link_not_a_store_path |
79 | ADR-0091: the declared SWI-Prolog is the Guix PROFILE's bin/swipl, |
| function | test_envrc_exports_UV_NO_EDITABLE |
97 | RUL-040: UV_NO_EDITABLE=1 must be exported so a bare uv sync in a |
| function | test_installed_packages_are_non_editable |
109 | STATE-based canary for the proper-install ruling (Mohamed 2026-10-20, |
tests/deploy/test_gitlab_runner_executor_deploy.py
source · 19 tests · 468 lines
CI must run a DEPLOYMENT, not this checkout.
| Kind | Name | Line | Description |
|---|---|---|---|
| function | test_no_executor_script_invokes_the_system_interpreter |
49 | A bare python3 is the system interpreter, forbidden by rule 1. |
| function | test_the_interpreter_is_resolved_beside_the_executor |
62 | GLR_PYTHON must come from the running copy's own sibling venv. |
| function | test_there_is_no_silent_fallback_to_system_python |
77 | A missing venv must FAIL, not quietly reach for /usr/bin/python3. |
| function | test_register_does_not_wire_ci_to_a_checkout |
125 | register.sh was the generator of the deploy-in-place violation. |
| function | test_register_refuses_when_nothing_is_deployed |
138 | Writing four paths that do not exist would fail every job at prepare. |
| function | test_the_unit_template_runs_the_deployed_sweep_script |
146 | |
| function | test_the_unit_template_keeps_the_optional_environment_file |
155 | Carried over from the hand-written unit; dropping it silently changes |
| function | test_the_installer_deploys_from_a_pinned_ref_not_the_working_tree |
164 | |
| function | test_version_is_staged_then_verified_then_promoted |
172 | Stage, verify, promote — pinned at the CALL SITE. |
| function | test_the_installer_refuses_a_hook_left_outside_the_prefix |
192 | The verification must fail on a config.toml that still points elsewhere. |
| function | test_the_installer_resolves_unit_scope_instead_of_assuming_user |
203 | The conventions forbid hardcoding --user. |
| function | test_ship_runs_every_installer_that_exists_in_deploy |
215 | The enumeration in ship.sh must cover deploy/ as it actually is. |
| function | test_the_unenumerated_installer_check_is_unconditional |
237 | It must not be nested under DEPLOYED_ANY -eq 0 again. |
| function | test_the_registry_token_goes_in_on_stdin_never_argv |
313 | An argv password is world-readable in ps for the life of the call. |
| function | test_the_token_is_sent_only_to_the_registry_gitlab_names |
337 | The host comes from CI_REGISTRY, never from the job's image:. |
| function | test_a_missing_credential_is_reported_and_not_fatal |
357 | Public-image jobs carry no registry credential and must still run. |
| function | test_the_job_environment_round_trips_through_the_env_file |
392 | Generate, source in a fresh shell, and compare — byte for byte. |
| function | test_run_does_not_put_job_variables_on_the_command_line |
441 | Only HOME and USER may travel as --env, and neither is a secret. |
| function | test_prepare_authenticates_before_it_launches |
458 | Order is the whole point: a login after the pull fixes nothing. |
tests/deploy/test_install_gitlab_runner_executor.py
source · 5 tests · 244 lines
U-T17: the GitLab Runner unit's binary is RESOLVED from the host, never
| Kind | Name | Line | Description |
|---|---|---|---|
| function | test_render_only_produces_a_byte_exact_execstart_line |
111 | |
| function | test_render_only_refuses_a_binary_that_is_not_executable |
135 | |
| function | test_installer_refuses_without_a_resolvable_binary_before_writing_anything |
154 | |
| function | test_wait_active_fails_on_a_crash_looping_unit_and_names_nrestarts |
177 | |
| function | test_wait_active_waits_through_activating_and_only_succeeds_once_settled |
199 |
tests/deploy/test_install_orchestrata.py
source · 5 tests · 225 lines
Tests for
deploy/install-orchestrata.sh— the pinned-ref /opt bootstrap.
| Kind | Name | Line | Description |
|---|---|---|---|
| function | test_bootstrap_stages_a_pinned_checkout_and_promotes_version |
43 | The whole happy path: clone, venv, sync, secrets, VERSION promoted last. |
| function | test_a_second_run_is_idempotent |
96 | Re-running against an already-bootstrapped prefix changes nothing that |
| function | test_a_ref_not_on_origin_master_is_refused |
139 | A commit that never reached origin/master must never reach production. |
| function | test_verify_fails_loud_when_the_identity_verifier_is_absent |
174 | Until U-T6 lands scripts/verify_deployment_identity.py, --verify must |
| function | test_missing_secrets_file_is_refused |
204 |
tests/deploy/test_install_orchestrata_cc.py
source · 2 tests · 317 lines
Tests for the CC/CXX compiler wiring in
deploy/install-orchestrata.sh.
| Kind | Name | Line | Description |
|---|---|---|---|
| function | test_sync_stage_uses_the_declared_compilers |
205 | No CC/CXX in the installer's environment and an unshadowed gcc on |
| function | test_sync_stage_refuses_an_unusable_declaration |
268 | A missing, bare-named or non-executable declaration is refused — one |
tests/deploy/test_install_orchestrata_rollback.py
source · 3 tests · 285 lines
Rollback tests for
deploy/install-orchestrata.sh(U-SIZE-C split of the
| Kind | Name | Line | Description |
|---|---|---|---|
| function | test_version_is_promoted_before_the_verifier_runs |
30 | D1: VERSION is staged-then-promoted BEFORE the verifier is invoked -- |
| function | test_a_failed_verification_rolls_back_to_the_previous_version_and_tree |
67 | D1 rollback: a second deploy whose verification fails restores the |
| function | test_a_failed_verify_rolls_back_the_tree_and_restarts_the_units |
151 | [U-T6 attempt-4 finding 7a, tightened by attempt-5 finding 4]: |
tests/deploy/test_install_orchestrata_secrets.py
source · 4 tests · 279 lines
Tests for the CHANGEME-placeholder fail-closed check in
| Kind | Name | Line | Description |
|---|---|---|---|
| function | test_placeholder_secrets_file_is_refused_before_any_write |
147 | A secrets file that still carries CHANGEME placeholders is refused |
| function | test_default_secrets_path_is_xdg_config_home_orchestrata_env |
191 | With no --secrets-env flag, the installer defaults to |
| function | test_missing_default_secrets_file_is_refused_with_adr_0066_message |
219 | With no --secrets-env flag and an XDG_CONFIG_HOME that holds |
| function | test_real_secrets_file_installs_exactly_as_before |
251 | A secrets file with no CHANGEME placeholders proceeds past the new |
tests/deploy/test_install_orchestrata_toolchain.py
source · 3 tests · 302 lines
Tests for the toolchain-pin + post-sync importability proof in
| Kind | Name | Line | Description |
|---|---|---|---|
| function | test_a_shadowing_gcc_on_path_does_not_change_the_compiler |
182 | A shadowing gcc leads PATH and C_INCLUDE_PATH leaks into the |
| function | test_an_inherited_bare_cc_is_overridden_by_the_declaration |
227 | An inherited bare CC=gcc/CXX=g++ — exactly what .envrc exported until |
| function | test_sync_stage_fails_closed_when_a_locked_path_package_does_not_import |
268 | uv sync exits 0 but fixture-native never landed in the venv: the |
tests/deploy/test_install_orchestrata_units.py
source · 3 tests · 245 lines
restart_units() skip-rule tests for
deploy/install-orchestrata.sh
| Kind | Name | Line | Description |
|---|---|---|---|
| function | test_a_timer_driven_oneshot_is_skipped_not_restarted |
81 | A .service with a REAL, loaded sibling .timer is a job the |
| function | test_an_unloadable_requires_is_skipped_and_the_run_continues |
131 | A unit whose Requires= names something this host cannot load must |
| function | test_the_literal_canvas_unit_is_skipped_without_being_queried |
183 | orchestrata-canvas.service (ruling R8: its own app under |
tests/deploy/test_install_orchestrata_version.py
source · 1 tests · 66 lines
VERSION-vs-real-parser test for
deploy/install-orchestrata.sh(U-SIZE-C
Covers: promotion.identity, promotion.identity_core
| Kind | Name | Line | Description |
|---|---|---|---|
| function | test_the_real_installer_written_version_is_accepted_by_the_real_parser |
25 | [U-T6 attempt-4 finding 7b]: don't just trust a Python-side mimicry of |
tests/deploy/test_install_tools.py
source · 9 tests · 562 lines
deploy/install-tools.sh deploys both daemons and proves them (ADR-0067 P2).
| Kind | Name | Line | Description |
|---|---|---|---|
| function | test_installer_smoke_leaves_no_socket_litter_under_tmp |
266 | The smoke daemons' sockets (and their .lock/.pid siblings) are reaped on exit. |
| function | test_installer_deploys_both_entry_points_at_head |
281 | |
| function | test_installed_ast_daemon_answers_identity_from_outside_any_repo |
301 | |
| function | test_installed_codemod_daemon_answers_identity_with_native_codemod_fast |
339 | |
| function | test_verify_arm_refuses_a_daemon_that_does_not_report_its_commit |
377 | The smoke is not vacuous: a daemon whose /health lacks deployed_commit fails the install. |
| function | test_cleanup_removes_the_stage_with_the_same_privilege_that_built_in_it |
399 | The EXIT trap must reap root-owned build artefacts for the real prefix. |
| function | test_installer_puts_daemon_templates_under_the_prefix_and_leaves_user_units_alone |
448 | A non-default PREFIX writes the templates to $PREFIX/systemd-user only. |
| function | test_installer_fails_hard_when_systemd_analyze_rejects_a_template |
510 | The verify arm is not vacuous: a template with a relative ExecStart fails the install. |
| function | test_restart_call_follows_the_version_promotion_on_the_default_prefix_only |
545 | The call's shape, pinned: restart-tool-instances.sh runs AFTER the VERSION |
tests/deploy/test_kg_ready.py
source · 11 tests · 272 lines
In-process unit tests for
deploy/orchestrata-kg-ready.py(U-T2/U-T2b,
| Kind | Name | Line | Description |
|---|---|---|---|
| function | test_load_env_file_parses_skips_comments_and_changeme |
87 | |
| function | test_load_env_file_is_silent_about_a_missing_file |
105 | |
| function | test_resolve_endpoint_reads_the_configured_uri |
122 | |
| function | test_resolve_endpoint_exits_2_when_the_uri_is_unusable |
142 | |
| function | test_resolve_database_prefers_the_process_environment |
159 | |
| function | test_resolve_database_exits_2_without_a_configured_database |
173 | |
| function | test_handshake_ok_true_for_a_real_listener_that_replies |
186 | |
| function | test_handshake_ok_false_for_a_closed_port |
195 | |
| function | test_main_in_process_returns_0_and_prints_ready |
200 | |
| function | test_main_in_process_returns_1_on_timeout |
226 | No peer at all -- main()'s plain "did not answer" branch. |
| function | test_main_in_process_returns_1_with_a_reason_naming_the_query |
246 | main()'s distinct failure branch: handshake ok, query never answers. |
tests/deploy/test_kg_ready_e2e.py
source · 7 tests · 214 lines
Subprocess (ExecStartPre-shaped) tests for
deploy/orchestrata-kg-ready.py.
| Kind | Name | Line | Description |
|---|---|---|---|
| function | test_ready_via_a_coordinator_and_its_discovered_main |
81 | The full U-T2b path: a coordinator peer answers SHOW INSTANCES |
| function | test_not_ready_when_the_peer_only_completes_the_handshake |
109 | A peer that answers the Bolt magic but never speaks HELLO/LOGON/RUN/ |
| function | test_exit_1_when_nothing_listens_within_the_timeout |
135 | |
| function | test_exit_2_when_no_endpoint_is_configured |
156 | |
| function | test_exit_2_when_no_database_is_configured |
169 | |
| function | test_quiet_suppresses_the_waiting_and_ready_lines |
183 | |
| function | test_exit_2_when_the_uri_has_no_host_or_port |
204 |
tests/deploy/test_kg_ready_routing.py
source · 5 tests · 183 lines
In-process unit tests for the ROUTING behavior of
| Kind | Name | Line | Description |
|---|---|---|---|
| function | test_routed_query_ok_true_via_a_coordinator_and_its_discovered_main |
81 | SHOW INSTANCES (real captured bytes) names a second real peer as |
| function | test_routed_query_ok_false_when_the_peer_never_answers_past_handshake |
101 | |
| function | test_routed_query_ok_false_when_a_direct_data_node_returns_the_wrong_value |
115 | The probe checks the VALUE of the row, not merely that a RECORD |
| function | test_routed_query_ok_false_when_the_discovered_main_returns_the_wrong_value |
135 | Same check, through the coordinator's two-hop discovery. |
| function | test_resolve_credentials |
163 |
tests/deploy/test_prod_profile_gateway_bind.py
source · 3 tests · 43 lines
ADR-0065 (ruling R15): the prod gateway's WS control plane binds loopback
| Kind | Name | Line | Description |
|---|---|---|---|
| function | test_prod_profile_pins_gateway_host_to_loopback |
30 | |
| function | test_test_profile_pins_gateway_host_to_loopback |
35 | |
| function | test_prod_and_test_profiles_agree_on_gateway_host |
40 |
tests/deploy/test_provisioner_tarball_default.py
source · 3 tests · 58 lines
Pins ADR-0064 (Accepted, ruling R13 -- the deployed orchgraph package
| Kind | Name | Line | Description |
|---|---|---|---|
| function | test_both_provisioners_default_to_the_mage_tarball |
42 | |
| function | test_both_provisioners_agree_on_the_same_default |
48 | |
| function | test_default_tarball_and_its_sha256_sibling_exist_on_this_host |
54 |
tests/deploy/test_repoint_venv.py
source · 5 tests · 152 lines
D41/p1: real-execution tests for deploy/orchestrata-test/repoint_venv.sh.
| Kind | Name | Line | Description |
|---|---|---|---|
| function | test_t1_shebangs_and_pth_are_repointed_to_the_new_root |
56 | Both the versionless and the uv 0.12.6 versioned ('python3') shebang |
| function | test_t2_a_tree_with_nothing_to_rewrite_exits_0 |
76 | Regression for D41: the old inline logic piped grep into a while |
| function | test_t3_a_sibling_prefix_shebang_is_never_rewritten |
94 | U-T16: whole-line fixed-string matching, never prefix matching — a |
| function | test_t4_an_unknown_checkout_shebang_fails_the_proof_naming_the_file |
109 | A first line beginning '#!<old>/' that is NOT one of the four known |
| function | test_t5_the_provisioner_invokes_the_repoint_before_the_promote |
129 | Text assertion (the full script needs Incus and the test fleet): |
tests/deploy/test_restart_tool_instances.py
source · 7 tests · 209 lines
deploy/restart-tool-instances.sh restarts ACTIVE tool-tree instances and nothing else
| Kind | Name | Line | Description |
|---|---|---|---|
| function | test_only_active_instances_of_the_two_templates_restart_in_listing_order |
106 | |
| function | test_a_failed_restart_refuses_with_the_post_promotion_message |
127 | |
| function | test_dry_run_lists_and_restarts_nothing |
138 | |
| function | test_a_glob_that_matches_nothing_is_a_quiet_success |
150 | |
| function | test_an_unknown_argument_is_a_usage_failure |
160 | |
| function | test_a_listing_failure_refuses |
167 | |
| function | test_a_real_transient_instance_is_restarted_and_nothing_else_is_reached |
186 |
tests/deploy/test_retire_plain_units.py
source · 16 tests · 488 lines
deploy/retire-plain-units.sh retires the two checkout-bound plain units (ADR-0067 P5).
| Kind | Name | Line | Description |
|---|---|---|---|
| function | test_retire_stops_and_removes_both_units_and_a_second_run_is_a_noop |
175 | |
| function | test_retire_disables_an_enabled_unit_and_removes_its_wants_symlink |
203 | The real plain units are ENABLED (WantedBy=default.target); a static |
| function | test_retire_stops_a_unit_whose_file_was_removed_while_it_is_still_loaded |
227 | The unit file is gone (removed by hand, no daemon-reload) but the manager |
| function | test_verify_fails_while_a_unit_is_running_even_with_its_file_gone |
258 | Isolates the is-active arm of verify: systemctl cat is allowed to |
| function | test_retire_with_one_unit_already_gone_retires_only_the_other |
275 | |
| function | test_retire_refuses_while_a_client_holds_the_codemod_socket |
288 | A REAL AF_UNIX server on the fixture socket with a REAL connected client: |
| function | test_a_listening_socket_with_no_client_does_not_block_retire |
330 | Only a CLIENT holding the socket is a refusal: a bound listener with no |
| function | test_verify_fails_while_either_plain_unit_is_still_installed |
347 | |
| function | test_a_unit_left_failed_is_retired_once_and_the_second_run_is_a_noop |
368 | A unit that exits non-zero stays failed after disable --now; without |
| function | test_a_failed_unit_whose_file_is_gone_is_not_live |
394 | File removed and the manager reloaded, but the unit is still remembered as |
| function | test_verify_fails_when_the_unit_file_is_present_and_the_manager_is_unreachable |
412 | With the manager unreachable systemctl cat fails and is-active |
| function | test_verify_fails_when_the_manager_cannot_be_queried |
433 | No unit file anywhere, but the manager is unreachable: absence of an answer |
| function | test_verify_passes_once_retire_has_run |
446 | |
| function | test_an_unknown_arm_is_a_usage_error |
457 | |
| function | test_the_script_defaults_to_the_two_real_plain_units |
464 | The defaults are the contract with the installer and the plan: the two |
| function | test_installer_retires_then_verifies_on_the_default_prefix_only |
472 | The installer cannot run with the default PREFIX from a test (it would |
tests/deploy/test_ship.py
source · 9 tests · 218 lines
Tests for
deploy/ship.sh's dirty-tree check — the gate that decides
| Kind | Name | Line | Description |
|---|---|---|---|
| function | test_a_clean_tree_passes_the_dirty_check |
63 | Baseline: with nothing modified, ship gets past the check. |
| function | test_the_thirty_minute_live_data_refresh_does_not_block_ship |
71 | The defect that shut ship down: only machine-refreshed pages changed. |
| function | test_a_hand_written_page_beside_the_live_data_still_blocks |
91 | The exclusion must not swallow its neighbours. |
| function | test_changed_source_still_blocks_even_amid_live_data_churn |
109 | Churn must not become cover for an uncommitted source change. |
| function | test_an_unknown_project_refuses_rather_than_shipping_unverified |
127 | A project with no declared gate must stop, not ship on a guess. |
| function | test_it_hands_off_to_the_repos_own_ship_script |
148 | The fix for the self-bootstrap trap. |
| function | test_the_arguments_survive_the_handoff |
173 | A handoff that dropped --dry-run would turn a rehearsal into a real ship. |
| function | test_running_the_repos_own_copy_does_not_hand_off_to_itself |
189 | The termination proof. |
| function | test_a_detached_head_refuses |
211 | Detached HEAD is a deliberate state, and there is no branch to push. |
tests/deploy/test_ship_evidence.py
source · 6 tests · 152 lines
Tests for
deploy/ship.sh's authoritative-suite blast radius and its
| Kind | Name | Line | Description |
|---|---|---|---|
| function | test_the_blast_radius_is_not_measured_from_the_push_state |
59 | origin/master...HEAD is empty once pushed, and an empty base is vacuous. |
| function | test_the_stamp_carries_the_commit_the_suite_passed_at |
71 | |
| function | test_a_stamp_with_no_commit_yields_no_base |
80 | The pre-2026-08-19 one-field stamp must read as 'no verified ancestor'. |
| function | test_a_green_run_from_another_commit_is_not_evidence |
111 | run-tests-latest.json is a single mutable slot — bind it to the commit. |
| function | test_a_green_run_from_the_stamped_commit_is_evidence |
130 | And the skip must still fire when the evidence genuinely is this run. |
| function | test_no_verified_ancestor_runs_the_whole_suite |
144 | With no base at all there is no honest subset — run everything. |
tests/deploy/test_ship_gates.py
source · 11 tests · 268 lines
Tests for
deploy/ship.sh's per-repo formatter gates, its installer
Covers: core.threading.pytest_live_observer
| Kind | Name | Line | Description |
|---|---|---|---|
| function | test_each_repo_gates_on_its_own_formatter |
43 | The defect this pins cost a gate that had never passed. |
| function | test_no_repo_gates_on_both_formatters |
61 | black and ruff format disagree, so demanding both is unsatisfiable. |
| function | test_every_gated_repo_runs_a_format_check |
74 | dr-hannah had none until 2026-08-14, and the reason is worth keeping. |
| function | test_a_repo_with_its_own_installer_actually_deploys |
88 | The defect: ship pushed dr-hannah and printed "nothing to deploy". |
| function | test_an_unrecognised_installer_refuses_rather_than_skipping |
110 | "Nothing to deploy" has to be a FINDING, not a fall-through. |
| function | test_a_repo_that_genuinely_installs_nothing_still_says_so |
133 | The refusal must not fire on repos with no deploy/ at all. |
| function | test_orchestrata_runs_the_authoritative_suite_before_pushing |
150 | The suite must run in ship's OWN verify, not inside the pre-push hook. |
| function | test_no_verify_is_only_used_where_the_suite_already_ran |
165 | --no-verify must never skip a gate that has not happened. |
| function | test_attribution_gate_range_survives_a_branch_without_upstream |
186 | The RUL-007 gate must scan commits, not fail on an unresolvable range. |
| function | test_a_plain_pytest_gate_runs_its_suite_past_the_rul038_observer |
206 | A ship gate's pytest is a sanctioned runner, so its multi-file suite runs. |
| function | test_every_plain_pytest_gate_goes_through_the_stamp |
259 | dr-hannah's arm runs its suite under uv run, which this suite cannot |
tests/deploy/test_ship_master.py
source · 9 tests · 210 lines
Tests for
deploy/ship.sh's merge-to-master and promote-prod steps
| Kind | Name | Line | Description |
|---|---|---|---|
| function | test_a_green_ship_fast_forwards_master |
45 | A feature branch that is pushed is still invisible to prod. |
| function | test_a_branch_behind_master_refuses_rather_than_merging |
57 | --ff-only, and it says why. |
| function | test_master_already_containing_the_branch_is_not_an_error |
86 | |
| function | test_shipping_orchestrata_promotes_prod |
100 | The step that was missing entirely. |
| function | test_the_prod_gate_record_is_written_before_promoting |
112 | The gate reads the promotion ledger, not the suite's own report. |
| function | test_promotion_verifies_the_tree_and_the_units |
128 | Exit code 0 from the promoter is not evidence the product moved. |
| function | test_promotion_can_be_skipped_deliberately |
146 | --no-promote, so a tooling-only ship need not touch the product. |
| function | test_only_orchestrata_promotes |
166 | dr-hannah deploys through its own installer and has no prod tree here. |
| function | test_a_dry_run_leaves_the_verified_stamp_untouched |
180 | --dry-run must not write reports/.ship-verified. |
tests/deploy/test_ship_merge_master.py
source · 10 tests · 286 lines
Tests for
deploy/ship-merge-master.sh— ship's merge-to-master step.
| Kind | Name | Line | Description |
|---|---|---|---|
| function | test_it_fast_forwards_master_from_a_worktree_while_primary_holds_master |
98 | THE regression: master is checked out elsewhere, and that is normal. |
| function | test_the_primary_checkout_is_advanced_in_place_with_its_files |
119 | Local master follows — ref AND working tree, in the worktree holding it. |
| function | test_a_long_worktree_listing_does_not_kill_the_step_after_master_landed |
140 | The silent exit 141, measured 2026-10-11. |
| function | test_a_dirty_primary_checkout_does_not_fail_the_ship_or_lose_the_edit |
174 | Advancing local master is a convenience, never a gate. |
| function | test_master_not_checked_out_anywhere_has_its_ref_moved_directly |
200 | The single-checkout case the old step did handle must still work. |
| function | test_a_moved_origin_master_is_refused_and_never_forced |
219 | ff-only is now enforced by the remote — so prove the remote refuses. |
| function | test_it_refuses_to_merge_master_into_itself |
243 | |
| function | test_it_refuses_a_branch_that_does_not_exist |
254 | |
| function | test_it_requires_exactly_one_branch_argument |
265 | |
| function | test_ship_calls_the_helper_and_no_longer_checks_master_out |
274 | The wiring: a helper nothing calls would fix nothing. |
tests/deploy/test_ship_push_state.py
source · 2 tests · 160 lines
Regression test for the AHEAD recompute in
deploy/ship.sh.
| Kind | Name | Line | Description |
|---|---|---|---|
| function | test_the_last_ahead_assignment_before_push_is_recomputed_after_the_evidence_commit |
116 | Structural: the push step must read a post-evidence-commit AHEAD. |
| function | test_ahead_recompute_reflects_the_evidence_commit_the_banner_missed |
137 | Behavioural: the banner's AHEAD and the recompute disagree on purpose. |
tests/deploy/test_ship_source_id.py
source · 9 tests · 202 lines
Tests for
deploy/ship.sh'sship_source_id()skip and its stamp
| Kind | Name | Line | Description |
|---|---|---|---|
| function | test_writing_the_run_report_does_not_change_the_source_id |
61 | A passing run rewrites this file, so counting it would self-invalidate. |
| function | test_writing_the_stamp_does_not_change_the_source_id |
72 | The first implementation failed exactly here, and silently. |
| function | test_an_evidence_only_commit_does_not_change_the_source_id |
89 | ship commits the evidence and then pushes; the id must survive that. |
| function | test_a_source_edit_changes_the_source_id |
107 | The half that keeps the skip honest. |
| function | test_a_new_untracked_file_changes_the_source_id |
116 | An untracked module can change what the suite collects. |
| function | test_the_source_id_is_content_addressed_not_index_addressed |
125 | Identical content must hash identically, staged or committed. |
| function | test_the_gate_consults_the_stamp_before_running_the_suite |
147 | The whole point: the expensive step is guarded, not unconditional. |
| function | test_a_red_report_can_never_authorise_a_skip |
157 | A stamp is not evidence on its own — the run it points at must be green. |
| function | test_the_two_dirty_checks_agree_on_what_counts_as_source |
169 | ship.sh's pre- and post-gate checks must exclude the same paths. |
tests/deploy/test_systemd_install.py
source · 15 tests · 331 lines
Tests for
deploy/systemd/install.sh-- U-T2 (ADR-0062): it must skip
| Kind | Name | Line | Description |
|---|---|---|---|
| function | test_dry_run_touches_nothing |
137 | |
| function | test_a_template_unit_is_skipped_and_never_enabled |
147 | |
| function | test_a_unit_whose_execstart_is_not_under_opt_orchestrata_is_skipped |
157 | |
| function | test_a_unit_resolves_user_scope_by_default |
169 | |
| function | test_a_scope_system_header_resolves_sudo_systemctl |
178 | |
| function | test_an_unchanged_unit_is_reported_unchanged |
187 | |
| function | test_a_changed_unit_would_be_installed |
201 | |
| function | test_a_unit_whose_requires_is_not_loadable_is_skipped |
214 | U-UNIT1: Requires= naming a unit systemd cannot load must not be |
| function | test_a_unit_whose_requires_is_loadable_is_not_skipped |
231 | U-UNIT1: a hard dependency systemd CAN load (here, a target systemd |
| function | test_only_selects_the_matching_units_and_nothing_else |
256 | |
| function | test_only_composes_with_dry_run_in_either_order_and_touches_nothing |
271 | |
| function | test_only_is_repeatable_and_a_unit_matching_any_glob_is_kept |
285 | |
| function | test_only_that_matches_no_unit_selects_nothing |
306 | |
| function | test_only_without_a_glob_is_a_usage_error |
316 | |
| function | test_an_unknown_argument_is_a_usage_error |
325 |
tests/deploy/test_toolchain_sh.py
source · 10 tests · 187 lines
deploy/toolchain.sh — the one loader of the declared toolchain.
| Kind | Name | Line | Description |
|---|---|---|---|
| function | test_loads_the_declared_tools_and_drops_the_guix_include_path |
72 | |
| function | test_an_inherited_bare_name_does_not_override_the_declaration |
88 | .envrc exported CC=gcc until 2026-10-11 and env/test.env still |
| function | test_refuses_a_missing_declaration |
101 | |
| function | test_refuses_a_declaration_without_cxx |
107 | |
| function | test_refuses_a_declaration_without_swipl |
116 | ADR-0091: SWIPL is a declared key like CC/CXX — a declaration that |
| function | test_refuses_a_bare_compiler_name |
128 | A bare name is resolved from PATH — the defect the declaration removes. |
| function | test_refuses_a_bare_swipl_name |
138 | SWIPL=swipl is the shape env/test.env carries: under the systemd PATH |
| function | test_refuses_a_compiler_that_is_not_executable |
152 | |
| function | test_refuses_a_swipl_that_is_not_executable |
162 | |
| function | test_the_tracked_declaration_loads_on_this_host |
172 | The committed env/toolchain.env names real, absolute, executable tools |
tests/deploy/test_tools_vendor_manifest.py
source · 7 tests · 94 lines
deploy/tools-vendor-manifest.txt is the COMPUTED closure, and the installer uses it.
| Kind | Name | Line | Description |
|---|---|---|---|
| function | test_manifest_equals_the_computed_all_scopes_closure |
57 | |
| function | test_the_old_inline_list_is_provably_short_by_verification_and_openspec |
61 | |
| function | test_manifest_only_grows_the_old_list |
70 | |
| function | test_every_manifest_path_exists_in_the_tree |
74 | |
| function | test_installer_archives_the_manifest_not_an_inline_list |
79 | |
| function | test_installer_derives_its_pip_line_from_the_closure |
86 | |
| function | test_installer_smoke_runs_a_default_review |
91 |