Skip to content

feat(cli): convert the CLI and Python surface to Sync HTTP API clients - #199

Merged
estivate merged 16 commits into
feature/v3-developfrom
feature/client-cli-conversion-restack
Sep 1, 2026
Merged

feat(cli): convert the CLI and Python surface to Sync HTTP API clients#199
estivate merged 16 commits into
feature/v3-developfrom
feature/client-cli-conversion-restack

Conversation

@estivate

@estivate estivate commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

Summary

The CLI and public Python surface become clients of the Sync HTTP API. Every command reaches the
service through one shared SyncClient; the CLI no longer opens a product store, loads an
adapter, resolves an execution credential, or invokes the internal execution core. This restacks
the previously reviewed conversion (evidence head 04b51b3) onto the merged runtime-model base,
which resolved the sequencing stop that blocked its first publication: the worker now builds model
classes at runtime, so removing generate no longer strands it.

Before and after

Before: infrahub-sync diff --name from-netbox --directory examples/   (local store + adapters)
After:  infrahub-sync configs register examples/netbox_to_infrahub/package.yml
        infrahub-sync diff --config-id <id> --version <n> --reason "..."
        infrahub-sync runs plan <run-id> [--detail] [--kind KIND]
        infrahub-sync apply <run-id> --expected-checksum <sha> --reason "..."

Key changes

  • New configs command group (register, version, list, show, versions, validate) over the
    shipped configuration routes; run verbs diff, sync, apply create and follow service runs.
  • Root list and generate and all standalone-only execution options are removed; runs plan
    replaces diff --from-plan as the supported re-review path.
  • On a failed apply, the CLI reports the recorded failure class from the run's retained results
    (apply failed: PlanSchemaChangedError) with a recovery hint for schema drift; runs plan
    shows a registered plan's recorded schema_fingerprint.
  • wait_for_run accepts an optional on_observation callback (caller-owned failure semantics)
    so interrupted waits report the last observed state.
  • The code generator is retained as internal test-oracle tooling for the runtime-model
    equivalence suite; generated-file banners are neutral and name no command.
  • Dependency note: pyyaml joins the base dependency set (the CLI reads YAML/JSON package files
    at its input boundary); HTTPX remains the only HTTP client runtime dependency.

User-visible behavior and limits

Every removed option is listed in the migration table in the docs; no removed option is silently
translated into new server behavior. The CLI reads the API token from the environment only. List
routes expose no pagination arguments yet. CLI cancellation is out of scope.

Validation

At final HEAD 7fe4f7555a243ed569e2ac70454d3521bad25e04:

  • uv run invoke format / uv run invoke lint — clean
  • uv run pytest -q3278 passed, 23 skipped, 1 xfailed
  • CLI help sanity: root, configs, runs plan, diff, sync, apply
  • uv run invoke docs.generate and docs.docusaurus — clean
  • Independent complete-diff review (Opus 5) and bounded correction verification — record posted
    as a PR comment
  • Closure evidence for the envelope's route matrix, error taxonomy, wait matrix, and removal
    manifest rows (focused suites)

🤖 Generated with Claude Code

estivate and others added 14 commits September 1, 2026 11:24
Seat: lead-developer
Assignment: cli-conversion-restack
Co-Authored-By: GPT-5.6 Sol <noreply@openai.com>
Seat: lead-developer
Assignment: cli-conversion-restack
Co-Authored-By: GPT-5.6 Sol <noreply@openai.com>
Seat: lead-developer
Assignment: cli-conversion-restack
Co-Authored-By: GPT-5.6 Sol <noreply@openai.com>
Seat: lead-developer
Assignment: cli-conversion-restack
Co-Authored-By: GPT-5.6 Sol <noreply@openai.com>
Seat: lead-developer
Assignment: cli-conversion-restack
Co-Authored-By: GPT-5.6 Sol <noreply@openai.com>
Seat: lead-developer
Assignment: cli-conversion-restack
Co-Authored-By: GPT-5.6 Sol <noreply@openai.com>
Seat: lead-developer
Assignment: cli-conversion-restack
Co-Authored-By: GPT-5.6 Sol <noreply@openai.com>
Seat: lead-developer
Assignment: cli-conversion-restack
Co-Authored-By: GPT-5.6 Sol <noreply@openai.com>
Seat: lead-developer
Assignment: cli-conversion-restack
Co-Authored-By: GPT-5.6 Sol <noreply@openai.com>
Seat: lead-developer
Assignment: cli-conversion-restack
Co-Authored-By: GPT-5.6 Sol <noreply@openai.com>
Seat: lead-developer
Assignment: cli-conversion-restack
Co-Authored-By: GPT-5.6 Sol <noreply@openai.com>
Seat: lead-developer
Assignment: cli-conversion-restack
Co-Authored-By: GPT-5.6 Sol <noreply@openai.com>
Seat: lead-developer
Assignment: cli-conversion-restack
Co-Authored-By: GPT-5.6 Sol <noreply@openai.com>
Seat: lead-developer
Assignment: cli-conversion-restack
Co-Authored-By: GPT-5.6 Sol <noreply@openai.com>
@estivate estivate added the type/feature New feature or request label Sep 1, 2026
@estivate

estivate commented Sep 1, 2026

Copy link
Copy Markdown
Contributor Author

Agentic review record

Envelope: the accepted HTTP client conversion envelope §16 restack addendum (independent readiness review: SEND BACK → corrected → READY, GPT-5.6 Sol; three contract decisions accepted by Blake Ellis 2026-09-01).

Implementation: GPT-5.6 Sol; 7 evidence commits restacked onto feature/v3-develop@5986d85 plus scoped closure commits; test-first pairs preserved.

Independent complete-diff review: Claude Opus 5, different model family, no implementer transcript. First pass over 5986d85..1d9559c: SEND BACK — 3 blockers (documented registration examples pointed at refused sync configs; a live Invoke task invoked retired options; an unguarded diagnostic call could replace the terminal apply verdict), 3 should-fixes, 8 nits. All adjudicated by the lead-developer with independent reproduction before acceptance.

Corrections: one batched round (c13f65b, 7d36a91) + one pre-push micro-batch (7fe4f75: orphaned bench harnesses deleted, closure scan widened to scripts/**, port guidance fixed). Bounded verification by the same reviewer: READY — every finding closed and re-verified at head, including both writer judgment calls (forced by registry declared-content rules, not preference).

Exact-head gates at 7fe4f75: format clean, lint clean (ty 0 new), uv run pytest -q = 3,278 passed / 23 skipped / 1 xfailed, CLI help sanity, docs generate + Docusaurus build, git diff --check clean. All test deletions audited against the envelope's removal manifest; one non-CLI engine test restored.

Disclosed manifest delta: pyyaml joins base dependencies (CLI reads YAML/JSON package files at its input boundary); HTTPX remains the only HTTP client runtime dependency.

Seat: lead-developer
🤖 Generated with Claude Code

@coderabbitai

coderabbitai Bot commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Too many files!

This PR contains 129 files, which is 29 over the limit of 100.

To get a review, reduce the PR to 100 files or fewer by splitting it into smaller PRs or changing its base branch.

Upgrade to a paid plan to raise the limit.

This review couldn't start because sufficient usage credits or metered capacity aren't available. Add credits or update usage-based reviews in the billing tab, then retry.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Team

Run ID: 635ee7ed-747b-48a5-8374-d2dbc7d3fae3

📥 Commits

Reviewing files that changed from the base of the PR and between 5986d85 and 7fe4f75.

⛔ Files ignored due to path filters (1)
  • uv.lock is excluded by !**/*.lock
📒 Files selected for processing (129)
  • .gitignore
  • README.md
  • changelog/+cli-core-migration.changed.md
  • changelog/+continue-on-error-source-references.changed.md
  • changelog/+saved-plan-review-and-apply.added.md
  • docs/docs/adapters/aci.mdx
  • docs/docs/adapters/infrahub.mdx
  • docs/docs/adapters/prometheus.mdx
  • docs/docs/contributing.mdx
  • docs/docs/creating-a-sync-project.mdx
  • docs/docs/migrating-from-netbox-or-nautobot.mdx
  • docs/docs/orchestration.mdx
  • docs/docs/readme.mdx
  • docs/docs/reference/cache-layout.mdx
  • docs/docs/reference/cli.mdx
  • docs/docs/reference/config.mdx
  • docs/docs/reference/durable-product-records.mdx
  • docs/docs/reference/incremental-extraction.mdx
  • docs/docs/reference/schema-mapping.mdx
  • docs/docs/running-a-sync.mdx
  • docs/docs/tutorials/netbox-demo-to-infrahub.mdx
  • examples/aci_to_infrahub/aci/sync_adapter.py
  • examples/aci_to_infrahub/aci/sync_models.py
  • examples/aci_to_infrahub/config.yml
  • examples/aci_to_infrahub/infrahub/sync_adapter.py
  • examples/aci_to_infrahub/infrahub/sync_models.py
  • examples/aci_to_infrahub/package.yml
  • examples/custom_adapter/README.md
  • examples/custom_adapter/config.yml
  • examples/custom_adapter/infrahub/sync_adapter.py
  • examples/custom_adapter/infrahub/sync_models.py
  • examples/custom_adapter/mockdb/sync_adapter.py
  • examples/custom_adapter/mockdb/sync_models.py
  • examples/custom_adapter/package.yml
  • examples/device42_to_infrahub/genericrestapi/sync_adapter.py
  • examples/device42_to_infrahub/genericrestapi/sync_models.py
  • examples/device42_to_infrahub/infrahub/sync_adapter.py
  • examples/device42_to_infrahub/infrahub/sync_models.py
  • examples/infrahub_to_peering-manager/infrahub/sync_adapter.py
  • examples/infrahub_to_peering-manager/infrahub/sync_models.py
  • examples/infrahub_to_peering-manager/peeringmanager/sync_adapter.py
  • examples/infrahub_to_peering-manager/peeringmanager/sync_models.py
  • examples/ipfabric_to_infrahub/infrahub/sync_adapter.py
  • examples/ipfabric_to_infrahub/infrahub/sync_models.py
  • examples/ipfabric_to_infrahub/ipfabricsync/sync_adapter.py
  • examples/ipfabric_to_infrahub/ipfabricsync/sync_models.py
  • examples/librenms_to_infrahub/genericrestapi/sync_adapter.py
  • examples/librenms_to_infrahub/genericrestapi/sync_models.py
  • examples/librenms_to_infrahub/infrahub/sync_adapter.py
  • examples/librenms_to_infrahub/infrahub/sync_models.py
  • examples/librenms_to_infrahub/librenms/sync_adapter.py
  • examples/librenms_to_infrahub/librenms/sync_models.py
  • examples/nautobot-v1_to_infrahub/infrahub/sync_adapter.py
  • examples/nautobot-v1_to_infrahub/infrahub/sync_models.py
  • examples/nautobot-v1_to_infrahub/nautobot/sync_adapter.py
  • examples/nautobot-v1_to_infrahub/nautobot/sync_models.py
  • examples/nautobot-v2_to_infrahub/infrahub/sync_adapter.py
  • examples/nautobot-v2_to_infrahub/infrahub/sync_models.py
  • examples/nautobot-v2_to_infrahub/nautobot/sync_adapter.py
  • examples/nautobot-v2_to_infrahub/nautobot/sync_models.py
  • examples/netbox_to_infrahub/README.md
  • examples/netbox_to_infrahub/config.yml
  • examples/netbox_to_infrahub/infrahub/sync_adapter.py
  • examples/netbox_to_infrahub/infrahub/sync_models.py
  • examples/netbox_to_infrahub/netbox/sync_adapter.py
  • examples/netbox_to_infrahub/netbox/sync_models.py
  • examples/netbox_to_infrahub/package.yml
  • examples/observium_to_infrahub/genericrestapi/sync_adapter.py
  • examples/observium_to_infrahub/genericrestapi/sync_models.py
  • examples/observium_to_infrahub/infrahub/sync_adapter.py
  • examples/observium_to_infrahub/infrahub/sync_models.py
  • examples/observium_to_infrahub/observium/sync_adapter.py
  • examples/observium_to_infrahub/observium/sync_models.py
  • examples/peering-manager_to_infrahub/infrahub/sync_adapter.py
  • examples/peering-manager_to_infrahub/infrahub/sync_models.py
  • examples/peering-manager_to_infrahub/peeringmanager/sync_adapter.py
  • examples/peering-manager_to_infrahub/peeringmanager/sync_models.py
  • examples/peeringdb_to_infrahub/genericrestapi/sync_adapter.py
  • examples/peeringdb_to_infrahub/genericrestapi/sync_models.py
  • examples/peeringdb_to_infrahub/infrahub/sync_adapter.py
  • examples/peeringdb_to_infrahub/infrahub/sync_models.py
  • examples/prometheus_to_infrahub (node_exporter)/infrahub/sync_adapter.py
  • examples/prometheus_to_infrahub (node_exporter)/infrahub/sync_models.py
  • examples/prometheus_to_infrahub (node_exporter)/package.yml
  • examples/prometheus_to_infrahub (node_exporter)/prometheus/sync_adapter.py
  • examples/prometheus_to_infrahub (node_exporter)/prometheus/sync_models.py
  • examples/slurpit_to_infrahub/infrahub/sync_adapter.py
  • examples/slurpit_to_infrahub/infrahub/sync_models.py
  • examples/slurpit_to_infrahub/slurpitsync/sync_adapter.py
  • examples/slurpit_to_infrahub/slurpitsync/sync_models.py
  • infrahub_sync/cli.py
  • infrahub_sync/client/__init__.py
  • infrahub_sync/client/client.py
  • infrahub_sync/client/models.py
  • infrahub_sync/generator/templates/diffsync_adapter.j2
  • infrahub_sync/generator/templates/diffsync_models.j2
  • infrahub_sync/managed/models.py
  • infrahub_sync/utils.py
  • pyproject.toml
  • scripts/bench-clean-nautobot.sh
  • scripts/bench-incremental-only.sh
  • tasks/__init__.py
  • tasks/bench.py
  • tasks/preview.py
  • tests/cache/test_cli_sync_cache.py
  • tests/cli/__init__.py
  • tests/cli/test_client_commands.py
  • tests/cli/test_parity_and_closure.py
  • tests/client/test_client.py
  • tests/client/test_public_surface.py
  • tests/client/test_wait.py
  • tests/integration/test_saved_plan_apply_integration.py
  • tests/managed/test_http_api.py
  • tests/preview/conftest.py
  • tests/preview/test_cli_cycle.py
  • tests/preview/test_preview_configuration.py
  • tests/test_cli_adapter_load_failures.py
  • tests/test_cli_execution_mapping.py
  • tests/test_cli_full_extract.py
  • tests/test_cli_parallel.py
  • tests/test_cli_plan_review.py
  • tests/test_credential_canary.py
  • tests/test_execution_cli_parity.py
  • tests/test_execution_surface.py
  • tests/test_generated_examples.py
  • tests/test_logging.py
  • tests/test_no_prefect_import.py
  • tests/test_potenda_plan_artifact.py
  • tests/test_sc010_credential_canary.py

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Sep 1, 2026

Copy link
Copy Markdown

Deploying infrahub-sync with  Cloudflare Pages  Cloudflare Pages

Latest commit: a25ed21
Status: ✅  Deploy successful!
Preview URL: https://bf60d0bc.infrahub-sync.pages.dev
Branch Preview URL: https://feature-client-cli-conversio.infrahub-sync.pages.dev

View logs

estivate and others added 2 commits September 1, 2026 12:46
The tutorial's macOS serve guidance uses the standard networking term.

Seat: lead-developer
Assignment: cli-conversion-restack
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Rich force-enables color on CI runners, splitting option tokens with
escape sequences so presence checks fail and absence checks pass
vacuously.

Seat: lead-developer
Assignment: cli-conversion-restack
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@estivate
estivate merged commit aebaa06 into feature/v3-develop Sep 1, 2026
19 checks passed
@estivate
estivate deleted the feature/client-cli-conversion-restack branch September 1, 2026 17:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

type/feature New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant