tests.test_sync_ops moduleΒΆ
Conformance tests for the dependency-updater registry.
Each test enumerates SYNC_OPERATIONS and asserts a
shared invariant, so a new operation that breaks a convention fails by name.
- tests.test_sync_ops.test_sync_deps_and_family_are_registered()[source]ΒΆ
sync-depsand every updater it drives are CLI commands.- Return type:
- tests.test_sync_ops.test_operation_identity_is_coherent(op)[source]ΒΆ
Command, branch, and template names are identical (naming rule 3).
- Return type:
- tests.test_sync_ops.test_operation_has_pr_body_template(op)[source]ΒΆ
Each updater ships a PR-body template under its own name.
- Return type:
- tests.test_sync_ops.test_operation_config_flag_exists(op)[source]ΒΆ
Each
config_flagnames a real boolean field on the Config schema.- Return type:
- tests.test_sync_ops.test_operation_job_name_is_descriptive(op)[source]ΒΆ
Each CI job name embeds the operationβs bare noun and an emoji.
- Return type:
The bumper label and the labellerβs rules name the same label.
The bumpers apply it to the PRs they open, and the labeller applies it to anyone elseβs PR touching a lockfile or
pyproject.toml. Both spellings are hand-written (workflow YAML cannot import Python), so one renamed without the other silently splits the family across two labels, and the single filter this constant exists for stops finding half of it.- Return type:
- tests.test_sync_ops.test_write_domains_justify_serial_apply()[source]ΒΆ
Three updaters share the workflow files; the uv pair stays out of them.
This is the invariant behind the serial apply phase: the workflow-file rewriters cannot write concurrently, while
sync-uv-lockandsync-dep-sources(uv.lock,pyproject.toml) never touch workflow files and resolve in parallel with them, serialized only against each other through the uv-project mutex.- Return type:
- tests.test_sync_ops.test_is_enabled_reads_the_config_flag(op)[source]ΒΆ
is_enabledmirrors the operationβs Config boolean.- Return type:
- tests.test_sync_ops.test_selected_operations_drops_disabled()[source]ΒΆ
A disabled flag removes its operation;
here_only=Falseskips probes.- Return type:
- tests.test_sync_ops.test_selected_operations_by_name_runs_a_subset_in_registry_order()[source]ΒΆ
Naming operations restricts to them, in registry order, not input order.
- Return type:
- tests.test_sync_ops.test_selected_operations_by_name_still_honors_config_flags()[source]ΒΆ
A named-but-disabled operation is dropped (feature flags are authoritative).
- Return type:
- tests.test_sync_ops.test_run_sync_operations_applies_in_input_order()[source]ΒΆ
Resolves run concurrently; applies run in the order passed in.
- Return type:
- tests.test_sync_ops.test_run_sync_operations_dry_run_skips_apply()[source]ΒΆ
dry_runresolves but never applies.- Return type:
- tests.test_sync_ops.test_run_sync_operations_isolates_a_failing_resolve()[source]ΒΆ
One operationβs resolve failure yields a
Noneplan, not a crash.- Return type:
- tests.test_sync_ops.test_operation_order_follows_the_registry()[source]ΒΆ
operation_orderrestores canonical order regardless of input order.- Return type:
- tests.test_sync_ops.test_sync_deps_reports_nothing_to_do_in_an_empty_tree(tmp_path, monkeypatch)[source]ΒΆ
With no lockfile, workflows, or source, no updater applies.
- Return type:
- tests.test_sync_ops.test_consolidated_job_covers_every_operation()[source]ΒΆ
Every registered operation has a step group in the job hosting it.
The drift guard: a new
SyncOperationadded toSYNC_OPERATIONSwithout wiring its sync command, PR body, and PR into a CI job fails here by name. Each operation is checked against its ownworkflowandjob, so moving one out of the consolidated job keeps the guard rather than dropping it.- Return type:
- tests.test_sync_ops.test_consolidated_job_passes_ci_flags(op)[source]ΒΆ
Each operationβs
ci_flagsreach its sync step in the autofix job.The drift guard: an updater that declares a CI capability (like
--release-notes) whose consolidated-job step never passes it silently drops the feature from the PR body. Fails by name when the registry and the YAML disagree.- Return type:
- tests.test_sync_ops.test_consolidated_job_uses_full_history()[source]ΒΆ
The job checks out full history so repeated create-pull-request calls in one checkout do not trip gitβs βshallow file has changedβ race.
- Return type:
- tests.test_sync_ops.test_consolidated_job_labels_every_pr_consistently()[source]ΒΆ
Every PR the consolidated job opens carries the shared dependency label.
- Return type:
- tests.test_sync_ops.test_consolidated_job_resets_tree_before_each_operation()[source]ΒΆ
Each shared-job operation resets the tree first, so PR diffs never bleed.
Only the consolidated operations need this: one with a job to itself starts from a clean checkout, so a reset there would be dead weight.
- Return type:
- tests.test_sync_ops.test_pinned_with_packages_covers_every_registry_pin()[source]ΒΆ
Every
package==versionin the registry reaches the bumper.The drift guard: a plugin set added to a toolβs
with_packagesbut never scanned ages out silently, which is how mdformatβs ownruff==pin sat four minor versions behind the top-level ruff.- Return type:
- tests.test_sync_ops.test_pinned_with_packages_keeps_the_lowest_of_two_pins(monkeypatch)[source]ΒΆ
Two tools pinning one package resolve against the older of the two.
- Return type:
- tests.test_sync_ops.test_no_standalone_dependency_jobs_remain()[source]ΒΆ
The four bumpers live only in the consolidated job, not as separate jobs.
- Return type:
- tests.test_sync_ops.test_sync_tool_versions_routes_npm_tools_to_the_npm_registry(monkeypatch)[source]ΒΆ
npm-backed tools resolve versions through the npm registry datasource.
awesome-lint is the only npm tool, so recording the argument
npm_candidatesreceives proves theelif spec.npmbranch routes it away from PyPI/GitHub. Empty candidate lists mean nothing is bumped, sotool_registry.pystays put.- Return type:
- tests.test_sync_ops.test_widest_changes(changes, expected)[source]ΒΆ
A name repeated across files collapses onto its lowest starting version.
- Return type:
- tests.test_sync_ops.test_bypass_only_plan_counts_as_changed_and_renders()[source]ΒΆ
A run that only edits cooldown bypasses still produces a PR report.
Pruning or freezing an
exclude-newer-packageentry rewritespyproject.tomleven when no package version moves; without this the sync PR would carry that hunk with an empty body.- Return type:
- tests.test_sync_ops.test_render_plan_markdown_closes_on_the_held_back_section()[source]ΒΆ
What the run did comes first; what it left alone closes the body.
The held-back section is the only forward-looking one, so it sits below the bypass table. A bypass-only run moves no version, and the old order opened its PR on releases it had not adopted.
- Return type:
- tests.test_sync_ops.test_render_plan_markdown_places_the_upgrade_invite_after_the_notes()[source]ΒΆ
The invitation follows the notes it asks the maintainer to work through.
- Return type:
- tests.test_sync_ops.SWAP_PYPROJECT = '[project]\nname = "basket"\nversion = "1.0.0"\ndependencies = [\n "cherry>=1.2",\n "mango>=2.1.0.dev0",\n]\n\n[tool.uv]\nexclude-newer = "1 week"\nexclude-newer-package = { mango = "2026-01-05T00:00:00Z" }\n\n[tool.uv.sources]\nmango = { git = "https://github.com/acme/mango", branch = "main" }\n'ΒΆ
A project tracking
mangoβs main branch while awaiting its2.1.0release.
- tests.test_sync_ops.SWAP_PRE_LOCK = 'version = 1\nrequires-python = ">=3.10"\n\n[options]\nexclude-newer = "0001-01-01T00:00:00Z"\nexclude-newer-span = "P1W"\n\n[[package]]\nname = "cherry"\nversion = "1.2.0"\nsource = { registry = "https://pypi.org/simple" }\nsdist = { url = "https://example.test/cherry.tar.gz", upload-time = "2026-06-01T10:00:00Z" }\n\n[[package]]\nname = "mango"\nversion = "2.1.0.dev0"\nsource = { git = "https://github.com/acme/mango?branch=main#abcdef12" }\n'ΒΆ
The lock before the swap:
mangoresolved from git, no upload time.
- tests.test_sync_ops.SWAP_POST_LOCK = 'version = 1\nrequires-python = ">=3.10"\n\n[options]\nexclude-newer = "0001-01-01T00:00:00Z"\nexclude-newer-span = "P1W"\n\n[[package]]\nname = "cherry"\nversion = "1.2.0"\nsource = { registry = "https://pypi.org/simple" }\nsdist = { url = "https://example.test/cherry.tar.gz", upload-time = "2026-06-01T10:00:00Z" }\n\n[[package]]\nname = "mango"\nversion = "2.1.0"\nsource = { registry = "https://pypi.org/simple" }\nsdist = { url = "https://example.test/mango.tar.gz", upload-time = "2026-07-10T09:00:00Z" }\n'ΒΆ
The lock a successful
uv lockproduces after the swap.
- tests.test_sync_ops.test_resolve_dep_sources_swaps_and_freezes(tmp_path, monkeypatch)[source]ΒΆ
The happy path: override dropped, floor tightened, release frozen.
- Return type:
- tests.test_sync_ops.test_resolve_dep_sources_dry_run_restores(tmp_path, monkeypatch)[source]ΒΆ
A dry run reports the full swap but leaves the project untouched.
- Return type:
- tests.test_sync_ops.test_resolve_dep_sources_is_all_or_nothing(tmp_path, monkeypatch, lock_outcome)[source]ΒΆ
A failed or wrong-version lock restores the project untouched.
- Return type:
- tests.test_sync_ops.test_resolve_dep_sources_noop_before_release(tmp_path, monkeypatch)[source]ΒΆ
With no qualifying release, the resolve never touches the project.
- Return type:
- tests.test_sync_ops.SELF_PIN_WORKFLOW = 'env:\n UV_EXCLUDE_NEWER: "1 week"\n uvx --no-progress \'repomatic==7.11.0\' metadata\n'ΒΆ
A downstream workflow whose self-pin is current but carries no exemption.
- tests.test_sync_ops.test_plan_file_rewrites_backfills_exemption_without_a_version_bump(tmp_path)[source]ΒΆ
A splice-only rewrite is still a change, and still gets written.
The exemption backfill reports no
(name, old, new)triple, since it names a package rather than moving a version. Gating the write on that list threw the rewrite away, so a downstream repo already pinned at the newest release never got the flag and its whole test workflow stayed unresolvable.
- tests.test_sync_ops.test_plan_file_rewrites_reports_nothing_when_already_exempt(tmp_path)[source]ΒΆ
An exemption already in place leaves the plan empty, not endlessly dirty.
- tests.test_sync_ops.test_plan_file_rewrites_keeps_version_bumps_out_of_the_exemption_list(tmp_path)[source]ΒΆ
A file that also moved a version reports through
changes, not twice.
- tests.test_sync_ops.test_resolve_action_pins_and_init_owned_files(monkeypatch, tmp_path, in_source_repo)[source]ΒΆ
sync-action-pinsskips init-owned files downstream, bumps them upstream.The
publish-pypicomposite action is copied byte-for-byte from a bundled template, so downstream itssetup-uvpin is owned byrepomatic initand a bump would ping-pong with the nextsync-repomatic. In the source repo the bundled template is a symlink to this very file, so the pin is a normal source-of-truth ref and stays bumpable. A downstream-authored workflow pinning the same action always bumps.- Return type:
- tests.test_sync_ops.test_bundled_pin_bearing_files_are_excluded_from_pin_scan()[source]ΒΆ
Every init-owned file carrying a
uses:SHA pin is excluded from bumping.Generic guard for the ping-pong fix: any
BundledComponent.github/target that ships a pinneduses:ref (today only thepublish-pypiaction) must be listed inBUNDLED_VERBATIM_TARGETS, so_pinnable_filesdrops it and neithersync-action-pinsnorsync-workflow-pinsfights the verbatim init deploy.- Return type:
- tests.test_sync_ops.test_apply_file_writes_rebases_on_current_text(tmp_path)[source]ΒΆ
A sibling operationβs apply landing between plan and write survives.
Both
.github/pin updaters plan whole-file rewrites from the same pre-apply snapshot; writing the planned text verbatim would revert whichever sibling applied first.
- tests.test_sync_ops.test_apply_file_writes_verbatim_without_rebase(tmp_path)[source]ΒΆ
A plan carrying no rebase closure still writes its planned text.
- tests.test_sync_ops.UV_CANDIDATES = [('0.12.2', '2026-08-05', '0.12.2'), ('0.12.3', '2026-08-07', '0.12.3'), ('0.12.4', '2026-08-13', '0.12.4')]ΒΆ
Three uv releases, all clear of the cooldown on
GATE_TODAY.
- tests.test_sync_ops.SETUP_UV_PIN = {PosixPath('lint.yaml'): 'jobs:\n lint:\n steps:\n - uses: astral-sh/setup-uv@aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa # v10.0.0\n with:\n version: "0.12.3"\n'}ΒΆ
A workflow pinning both halves: the action commit and the uv it installs.
- tests.test_sync_ops.test_uv_gate_drops_unverifiable_releases()[source]ΒΆ
A uv the pinned action cannot checksum is not a candidate.
Without this,
sync-workflow-pinswalks uv past the table on its own schedule and CI installs it without a pinned hash.
- tests.test_sync_ops.test_uv_gate_reads_the_action_pin_out_of_the_scanned_files()[source]ΒΆ
The commit the table is fetched at comes from the files being synced.
The gateβs two halves are wired through the scanned text: miss the pin and it silently degrades to ungated, which is the failure it exists to prevent.
- tests.test_sync_ops.test_uv_gate_holds_the_pin_when_the_table_is_unknown(caplog)[source]ΒΆ
An unreadable table keeps out every release newer than the pin.
A blind bump can overshoot the table, and the next run that reads it steps the pin back again.
- tests.test_sync_ops.test_uv_gate_passes_everything_through_without_a_setup_uv_pin()[source]ΒΆ
With no action pinned there is no table to wait for, so nothing holds.
- tests.test_sync_ops.test_uv_gate_reports_a_pin_above_the_table()[source]ΒΆ
A pin past the table is signalled back, so the caller can step it down.
Reported rather than silently gated, because the sync only walks a version backwards on this one condition.
- tests.test_sync_ops.test_uv_gate_warns_when_the_pinned_uv_is_unverified(caplog)[source]ΒΆ
The pin on disk is audited too, not just the one about to replace it.
- tests.test_sync_ops.test_uv_gate_stays_quiet_when_the_pinned_uv_is_verified(caplog)[source]ΒΆ
A covered pin is the normal state and earns no warning.
- tests.test_sync_ops.test_uv_gate_reports_a_release_it_withheld(caplog)[source]ΒΆ
A newer uv the action cannot verify is announced, at info level.
uv ships weekly against
setup-uvβs monthly cadence, so this is the ordinary state between action bumps: a warning every run would train the reader to ignore the ones that mean something.
- tests.test_sync_ops.test_workflow_pins_step_a_uv_pin_back_onto_the_checksum_table(caplog)[source]ΒΆ
The repair is the pin move itself, not the warning beside it.
A repository whose uv pin overtook the table has no forward move left when the newest
setup-uvis the one it already pins, so the sync walks uv down to the newest release that action can verify.
- tests.test_sync_ops.test_workflow_pins_label_a_uv_step_back_in_the_table()[source]ΒΆ
A pin moving down says so in its own row, and links to why.
The arrow alone renders a step back like any bump, so without the label the repair reads as an update to an older release.
- tests.test_sync_ops.test_workflow_pins_label_nothing_on_a_forward_uv_bump()[source]ΒΆ
An ordinary uv bump inside the table carries no label.
- tests.test_sync_ops.test_workflow_pins_hold_the_uv_pin_on_an_unreadable_table()[source]ΒΆ
An unreadable table moves the uv pin neither forward nor back.
0.12.4cleared the cooldown, so only the hold keeps it out.
- tests.test_sync_ops.test_workflow_pins_invite_the_upgrade_review_on_a_repomatic_bump()[source]ΒΆ
A lockstep bump of the upstream pin carries the review launcher.
The
uses:refs already moved by hand, so realigning the inline pin is the pull request where a maintainer learns the repository now runs a newer release, and the one where both versions are known.- Return type: