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.sh tests

tests/deploy/_ship_support.py

source · 0 tests · 88 lines

Shared fixtures/helpers for the deploy/ship.sh tests (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's ship_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