Skip to content

Release 1.24.0 - #1503

Open
danipl wants to merge 297 commits into
stablefrom
dp-20261109-release-sdk-1-24-0-ifc-3589
Open

danipl wants to merge 297 commits into
stablefrom
dp-20261109-release-sdk-1-24-0-ifc-3589

Conversation

@danipl

@danipl danipl commented Nov 9, 2026 •

Copy link
Copy Markdown

Releases the Python SDK 1.24.0, the SDK version for Infrahub 1.12.0 (IFC-3589). Until now, only the betas v1.24.0b0 and v1.24.0b1 were published.

This pull request brings infrahub-release-1.12 (commit 1b19c283) into stable, as the 1.23.0 release did in #1259. It adds one commit to the release branch:

  • Adds the 1.24.0 section to CHANGELOG.md, built by towncrier from 58 changelog fragments.
  • Deletes those 58 fragments.
  • Deletes 14 more fragments without listing them under 1.24.0. The 1.23.0 release had already used them on stable (commit c7313d54), but infrahub-release-1.12 still had copies with identical text.

Merge with a merge commit

Merge this pull request with a merge commit, not a squash. A squash would break the shared history between stable and infrahub-release-1.12.

Next steps after the merge

  • Tag the merge commit as v1.24.0 and publish the GitHub release. The release workflow then publishes the package to PyPI.
  • Bring the changelog commit back into infrahub-release-1.12 and infrahub-develop.

🤖 Generated with Claude Code

View guided diff Turn on auto-fix

polmichel and others added 30 commits July 13, 2026 10:53
Merge stable into develop
Merge develop into infrahub-develop
Switch infrahub-sdk from a static [project].version to a build-time version
resolved from v* git tags via hatch-vcs (fallback: static sentinel
0.0.0.dev0). Removes version-bump churn and the recurring pyproject/uv.lock
merge conflicts between stable and develop.

- pyproject: dynamic version + hatch-vcs + version-file infrahub_sdk/_version.py;
  git_describe_command without --dirty so the version derives from committed
  state only
- .gitignore: ignore the generated infrahub_sdk/_version.py
- uv.lock: regenerated (no version recorded for the dynamic member)
- release.yml: fetch tags on checkout; read version via importlib.metadata
  instead of `uv version --short`; add publish guards (tag-match + reject
  unreleased fallback)
- publish-pypi.yml: fetch tags so `uv build` stamps the real tag version

Port of infrahub PR 9711 + 9860 (INFP-566), adapted to the SDK (single
package, v* tags, no Docker/compose/Helm).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Merge develop into infrahub-develop
Merge stable into develop
Merge develop into infrahub-develop
Merge stable into develop
Merge develop into infrahub-develop
Merge stable into develop
Phase 1 (Specify) of speckit prep: spec.md + requirements checklist for
the SDK X-Priority feature — client-wide default + per-request override,
zero behaviour change when unconfigured, async/sync parity.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Phase 2 (Plan): plan.md, research.md, data-model.md, quickstart.md, and
API + wire contracts. Approach grounded in the existing X-Infrahub-Tracker
prior art — default injected into base self.headers, per-request override
applied in execute_graphql/_execute_graphql_with_file only.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…-259)

Phase 3 (Critique): dual-lens (product + engineering) review — verdict
PROCEED WITH UPDATES, no blockers. Applied low-risk recommendations:
- SC-002 reworded (X-Priority absent vs literal byte-for-byte)
- new SC-006 (batch/blob inherit the client default)
- scoped the manual-header edge case to low-level _get/_post
- plan/research notes: pagination forwards priority per page; multipart
  sets X-Priority after the content-type pop

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…259)

Phase 4 (Tasks): 35 tasks organized by user story (US1 MVP → US5 parity)
plus setup, foundational, and polish. Tests included per PRD testing
decisions; critique follow-ups (pagination, multipart ordering,
batch/blob inheritance) captured as explicit test tasks.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Phase 5: verdict ALIGNED against the IHS-259 PRD. All FRs, SCs, user
stories, edge cases, and out-of-scope items carried over; only expansions
(FR-009, SC-006) and one testability clarification (SC-002). 0 remediation
passes.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add a case-insensitive Priority(str, Enum) in constants.py, re-export it
from the SDK public namespace, and add a Config.priority field
(auto-binding to INFRAHUB_PRIORITY, default None). Foundational prereqs
T002-T004 for the X-Priority request header feature.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Inject the client-wide default priority once in BaseClient.__init__ so it
rides GraphQL, multipart, and raw blob transports via the shared
self.headers merge. Add unit tests covering GraphQL query/mutation,
object-store blob download/upload, multipart upload, batched requests,
and the always-emitted normal default, for both async and sync clients.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Lock backwards compatibility (US3): an unconfigured client emits no
X-Priority header across GraphQL, multipart, and blob transports, and
its baseline SDK headers (content-type, X-Infrahub-Tracker) are
unchanged. Both async and sync clients.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…S-259]

Add a `priority: Priority | None = None` keyword to the GraphQL execute
funnels (execute_graphql, _execute_graphql_with_file) and thread it through
the high-level client methods (get, all, filters, create_diff,
get_diff_summary, get_diff_tree) and node methods (save, create, update,
delete) on both the async and sync clients. Resolution is
`per_request if per_request is not None else client_default`.

Per-request headers now take precedence over self.headers in the transport
helpers (_post/_get/_get_streaming/_post_multipart) so an explicit override
is not clobbered by the client-wide default.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
… unknown [IHS-259]

Lock the Priority enum + pydantic validation for Config.priority (US4):
- unknown value ("lowe") raises ValidationError at config load (no request)
- "LOW"/"Low"/"low"/Priority.LOW all resolve to Priority.LOW (and HIGH/NORMAL)
- INFRAHUB_PRIORITY env-var path resolves case-insensitively
- default Config() leaves priority None (header omitted)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…le [IHS-259]

Add a data-driven parity test encoding the resolution truth table from
data-model.md (8 default x override rows), run against both the async and
sync clients (16 param cases) asserting identical emitted X-Priority
headers. Audited T006-T012 and T021-T024: all already parametrized over
["standard","sync"], no change needed.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
… [IHS-259]

Phase 8 polish for the X-Priority feature:
- Add priority kwarg mention to get_diff_tree docstrings (async + sync)
- Regenerate SDK docs (new Config.priority field in config.mdx; priority
  kwarg across client/node reference), also picking up pre-existing
  generator whitespace drift so docs-validate passes
- Add changelog fragment 1151.added.md describing the Priority enum,
  Config.priority, and per-request priority= surface

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…rge [IHS-259]

The X-Priority feature flipped the transport-helper header merge so a
per-request snapshot wins over the client base headers. For password-auth
clients this regressed the automatic relogin retry: handle_relogin refreshes
self.headers["Authorization"] to a new token, but the retry re-sent the SAME
stale snapshot, which then overwrote the fresh token -> the retry used the
expired token and auth failed.

Introduce BaseClient._merge_request_headers, used at every transport-helper
merge site (async/sync _post, _get, _get_streaming, _post_multipart). It lets
per-request headers win (preserving the X-Priority override) but then
re-asserts Authorization / X-INFRAHUB-KEY from self.headers so a mid-flight
refreshed token always beats a stale snapshot.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
… override [IHS-259]

Add per-request X-Priority override tests for node.delete(), the save() update
path on an existing node, and get_diff_summary()/get_diff_tree() (create_diff was
already covered). All parametrized over async and sync clients.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Final report for the implement + review tail: 35/35 tasks done, 1 HIGH
review finding (relogin auth-header regression) fixed inline, 3 test-gap
findings closed. SDK suite 1145 passed; 8 pre-existing unrelated failures.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…HS-259]

Re-run docs-generate on top of develop so the committed generated docs
(config.mdx priority field, client/node method priority kwarg) match the
current generator and markdown lint rules.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
rumdl (MD022/MD058) flagged missing blank lines around headings and
tables in the auto-generated critique. Apply rumdl auto-fix so the
markdown-lint CI job passes.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The file is gitignored on develop but was committed on this branch before
that rule; untrack it while keeping the local working copy.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
… [IHS-259]

Address review feedback: a per-request priority now rides consistently
across a whole operation.

- count() (both clients) accepts priority and forwards it; all(parallel=True)
  passes priority to its preliminary count query (previously sent at the
  client default while the pages used the override).
- Resource-pool peer fetch after node create/update/save now inherits the
  operation's priority via _process_mutation_result -> RelatedNode.fetch.

Tests cover count (direct + parallel all) and RelatedNode.fetch forwarding,
both async and sync.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
… [IHS-259]

- Changelog: concise entry, no longer enumerates every method.
- contracts/priority-api.md: remove the incorrect client.create(priority=)
  signature (it issues no request); document count/filters and the
  intentional exclusion; note peer-fetch inherits priority.
- data-model.md: add node create() + resource-pool peer fetch to the
  coverage table; note client.create is n/a.
- Regenerate SDK reference docs for the new count/fetch priority params.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
danipl and others added 24 commits October 27, 2026 09:04
…ratio [IFC-3420]

feat(ctl): add infrahubctl commands for the temporary trace sampling ratio [IFC-3420]
Adds the role of stable, develop, infrahub-release-x.y and
infrahub-develop, which Infrahub branch pins each one, and the order in
which the bot syncs them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
docs(agents): describe the SDK branches and how they sync [IFC-3497]
…#1463)

* feat(node): attach a held number to a number pool or detach it [IFC-3333]

Number attributes have attach_to_pool() and detach_from_pool(), sent on the
next save. An attribute built with both value and from_pool now sends both,
so the pool tracks the given number instead of allocating a new one. A pool
write is sent once: a pending flag is cleared after a successful mutation,
while _from_pool stays set.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* feat(node): list a pool's allocations with their provenance [IFC-3367]

Resource pool nodes have get_pool_allocations(), which returns PoolAllocation
entries: the node id, kind, branch, display label, identifier and whether the
pool allocated the number or a user provided it (None for IP pools). It needs
Infrahub 1.12 or later. get_pool_allocated_resources() shares the paging loop
but still leaves provenance out of its query, so it keeps working on older
servers.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* feat(node): declare a number pool's ranges on create and upsert [IFC-3369]

A relationship whose peer kind is CoreNumberPoolRange takes the peer's fields
as mutation input instead of a reference, as Infrahub's NumberPoolRangeInput
does. A CoreNumberPool can therefore be created with ranges given as dicts of
start, end and allocation_weight, and an upsert sets an existing pool's ranges
to the declared list. Before, each range was sent as an empty object, which
Infrahub read as one range without a start or an end.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* test(integration): number pool ranges, attach/detach and provenance on Infrahub 1.12

Covers creating a pool with declared ranges and setting them by upsert,
attaching and detaching numbers (including a detach before the first save),
the provenance get_pool_allocations reports, and the attribute's source after
an attach. The class is skipped unless INFRAHUB_TESTING_IMAGE_VER is 1.12 or
later.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* docs(changelog): split the from_pool fix and shorten the provenance entry

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* refactor(node): move the detach comment onto the branch it describes

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* test(node): check a detached attribute keeps its number

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Aaron McCarty <19253956+ajtmccarty@users.noreply.github.com>
update_group() returned early whenever a run tracked zero members, so it never
diffed the previous membership against the empty set. A generator that
legitimately produced nothing, or a repository whose last object file was
removed, left every previously tracked node behind as an orphan. With
delete_unused_nodes=True a run that tracks nothing now prunes an existing
group; one with no group creates none, and an already-empty group is not
re-saved. A context reused without finding a group has nothing to reap.

The reap deletes on the tracking context's branch rather than the client's
default branch, and both context-manager exits reset the client mode in a
finally block so a raising update_group() cannot leave the client tracking.

delete_unused() attempts every candidate and returns a ReapResult instead of
raising. A failure about the member is recorded against it and the rest are
still attempted; the refused members stay in the group so a later run retries
them, and update_group() reports them together as TrackingGroupCleanupError,
again on every run until whatever blocks the deletion is removed. A failure
about the request stops the reap and is re-raised as itself rather than
recorded against each remaining member. That includes a timeout and an
unreachable server, and also the coded failures the GraphQL path raises as a
GraphQLError: an expired or missing token, and a branch that is gone, merged,
needs a rebase or is locked by a merge.

The group write is attempted first, listing this run's nodes plus the refused
members and the ones never reached, so an interrupted reap cannot leave the
nodes the run created in no group at all. The member whose delete was
interrupted is kept only when the server answered: without an answer the
delete may have gone through, and a write naming a node that no longer exists
is rejected. When the write fails too, the error that stopped the reap is
raised with the write's failure as its cause.

A member already removed by another member's cascade is tolerated through the
catalogue's NodeNotFoundError, with the legacy message check kept only for
servers that report no code. The async and sync contexts share the decisions
around the reap and the write, keeping only their own calls.

TrackingGroupCleanupError is exported from infrahub_sdk.exceptions, survives
pickling, and infrahubctl renders it as a table of each member and the
server's reason rather than a traceback. The changed contract of
delete_unused() and the new exception type get a changed fragment of their
own.
fix(tracking): reconcile tracking groups on runs that save no nodes
)

Only the server's schema synchronizer assigns the pool of a NumberPool
attribute. A schema file that carries the id, for example one exported
from another instance, now validates with a read-only warning and the
server ignores the value instead of storing an id that points to no pool.

Regenerated from the Infrahub generator (tasks/backend.py).

Co-authored-by: Aaron McCarty <19253956+ajtmccarty@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…t creates

GitRepo copies its source directory, which keeps the source's permissions,
and creates the repository as the user that runs the tests. When the
Infrahub containers run as another user, they cannot read a repository
copied from a private directory, such as one from pytest's tmp_path, and
cannot push to any of them.

With shared=True, GitRepo sets core.sharedRepository so that Git creates
later files with the same access, and gives every user read and write
access to the files that exist already. The default, False, keeps the
current behavior.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…pool (#1469)

* fix(node): refuse every edit of a relationship that takes its peers as fields

The mutation of such a relationship takes the fields of a peer, not a reference to
one, so add(), extend() and remove() could not reach Infrahub: add() and extend()
dropped the peer without an error, and remove() sent the remaining peers as
references, which Infrahub refused. They now raise FeatureNotSupportedError and name
the ways out that work. The relationships concerned are listed as (name, peer) pairs,
so another relationship to the same kind of node stays editable.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* chore(docs): regenerate the relationship reference

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* fix(ctl): tell --set apart on object create and object update

A relationship whose mutation takes the peers' fields does reach Infrahub on a
create, so object create refuses only a value that names peers by reference and
lets a JSON list of their fields through. An update sends the peers the node was
fetched with, so object update refuses every value and names the create that
upserts the node. Both report the refusal before any change is applied, and the
reason they give comes from the constant the SDK message is built from.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* test(spec): reproduce the ranges an object file declares being created on their own

The two tests fail: loading the file sends a CoreNumberPoolRange mutation of its own
next to the pool, which Infrahub refuses as overlapping the range the pool holds.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* fix(spec): send the ranges an object file declares with the pool itself

A relationship whose mutation takes the peers' fields now travels in the payload of
the node that declares it, in both forms an object file accepts for a list of
objects. A list of references stays a list of references.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* fix(spec): expand the peers a file's parameters expand before sending them

The branch that sends the peers' fields with their node read the list under `data`
as it stands, while the validation pass runs it through the processors first. A file
with `parameters: {expand_range: true}` was therefore validated expanded and saved
unexpanded. Both passes now read the same peers.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* fix(ctl): refuse an object that names a peer in --set

The create guard read a list of objects as the fields of the peers, so an object
holding an id, an hfid or a node went through and failed against the server instead
of reporting the refusal. The keys that name a peer now have one definition, which
the node side reads as well.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* fix(spec): expand the peers with the parameters of the whole file

The branch that sends the peers' fields read the parameters of the relationship
alone, while the validation pass falls back to the parameters of the file. A file
that sets expand_range for everything it holds was therefore validated expanded and
saved unexpanded.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* docs(python-sdk): state that editing the peer list is not supported

Describing what each save path does with an edit invited readers to rely on one of
them. The guide and the docstring now name the complete list as the way to set the
ranges.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* chore(docs): regenerate the relationship reference

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* chore(spec): shorten the comments on the inline-peer branch

Each one now carries only what the code does not say: why these peers do not go
through the deferred branch, and why the parameters fall back to the file's.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* refactor(node): move the inline-peer rule out of the constants

The table, the message and the predicate that reads them now live in a module of
their own, keyed by peer kind so a kind can have more than one such relationship.
The predicate loses its leading underscore: four modules in three packages read it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* refactor(ctl): give the --set refusals their own module

Both guards sat in a module named for everything the object commands share, and
their tests in a test module named after it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* chore(changelog): fold the object file into the entry that adds the ranges

Nothing was released without it, so it is part of what the release adds rather than
a fix. The integration test says why it processes the same file twice.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* test(spec): drop the range expansion tests on a number pool

Expansion turns a start into a string, which the Number attribute of a range does
not take, so the tests pinned a payload Infrahub has no reason to accept. The
parameters still travel, so validating and saving read the same peers.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
feat(testing): let GitRepo give every user access to the repository it creates
Merge stable into develop
Python 3.10 is end of life. infrahub-sdk 1.24.0 is the last release
that supports Python 3.10.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…-infrahub-release-1.12

# Conflicts:
#	infrahub_sdk/spec/object.py
… branch in object.py

develop sends cardinality-one references through _clean_reference so that
HFID references to a generic peer are resolved. infrahub-release-1.12 adds
a branch that passes inline peer fields in the mutation. The two handle
different relationship formats, so both are kept: the ONE_REF branch takes
develop's body and release's peers_are_inline_fields branch follows it.
The imports keep both peers_are_inline_input and NodeSchemaAPI.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Merge stable into develop
…ease-1.12

Merge develop into infrahub-release-1.12
Merge stable into develop
Merge develop into infrahub-release-1.12
Merge stable into develop
Merge develop into infrahub-release-1.12
Merge stable into develop
Merge develop into infrahub-release-1.12
Also removes the 14 changelog fragments that the 1.23.0 release had
already used on stable, so they are not listed again under 1.24.0.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@danipl
danipl requested a review from a team as a code owner November 9, 2026 15:31
@github-actions github-actions Bot added group/ci Issue related to the CI pipeline type/documentation Improvements or additions to documentation labels Nov 9, 2026
@cloudflare-workers-and-pages

Copy link
Copy Markdown

Deploying infrahub-sdk-python with  Cloudflare Pages  Cloudflare Pages

Latest commit: 53cdfdd
Status: ✅  Deploy successful!
Preview URL: https://cbce2007.infrahub-sdk-python.pages.dev
Branch Preview URL: https://dp-20261109-release-sdk-1-24.infrahub-sdk-python.pages.dev

View logs

@codecov

codecov Bot commented Nov 9, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 97.50701% with 80 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
infrahub_sdk/query_groups.py 89.91% 6 Missing and 6 partials ⚠️
infrahub_sdk/exceptions/base.py 95.52% 7 Missing and 4 partials ⚠️
infrahub_sdk/protocols_generator/generator.py 76.31% 6 Missing and 3 partials ⚠️
infrahub_sdk/ctl/utils.py 84.90% 6 Missing and 2 partials ⚠️
infrahub_sdk/node/relationship.py 93.25% 1 Missing and 5 partials ⚠️
infrahub_sdk/protocols_base.py 25.00% 0 Missing and 6 partials ⚠️
infrahub_sdk/ctl/cli_commands.py 42.85% 4 Missing ⚠️
infrahub_sdk/ctl/troubleshooting.py 93.33% 3 Missing and 1 partial ⚠️
infrahub_sdk/spec/object.py 77.77% 3 Missing and 1 partial ⚠️
infrahub_sdk/testing/repository.py 86.36% 1 Missing and 2 partials ⚠️
... and 8 more
@@            Coverage Diff             @@
##           stable    #1503      +/-   ##
==========================================
- Coverage   85.18%   83.78%   -1.41%     
==========================================
  Files         148      157       +9     
  Lines       13368    15656    +2288     
  Branches     1975     2114     +139     
==========================================
+ Hits        11388    13117    +1729     
- Misses       1412     1979     +567     
+ Partials      568      560       -8     
Flag Coverage Δ
integration-tests ?
python-3.10 62.91% <80.95%> (+4.58%) ⬆️
python-3.11 62.91% <80.95%> (+4.58%) ⬆️
python-3.12 62.90% <80.95%> (+4.56%) ⬆️
python-3.13 62.91% <80.95%> (+4.57%) ⬆️
python-3.14 62.91% <80.95%> (+4.57%) ⬆️
python-3.15 62.91% <80.95%> (+4.57%) ⬆️
python-filler-3.12 23.03% <16.57%> (-0.67%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
infrahub_sdk/constants.py 94.44% <100.00%> (+1.11%) ⬆️
infrahub_sdk/ctl/object/create.py 93.18% <100.00%> (-4.44%) ⬇️
infrahub_sdk/ctl/object/inline_peers.py 100.00% <100.00%> (ø)
infrahub_sdk/exceptions/__init__.py 100.00% <100.00%> (ø)
infrahub_sdk/exceptions/catalogue.py 100.00% <100.00%> (ø)
infrahub_sdk/file_handler.py 87.56% <100.00%> (ø)
infrahub_sdk/graph_traversal/query.py 100.00% <100.00%> (ø)
infrahub_sdk/node/__init__.py 100.00% <100.00%> (ø)
infrahub_sdk/node/_only.py 100.00% <100.00%> (ø)
infrahub_sdk/node/attribute.py 100.00% <100.00%> (ø)
... and 32 more

... and 18 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

20 issues found across 181 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="pyproject.toml">

<violation number="1" location="pyproject.toml:69">
P2: Custom agent: **Detect conflicting package versions across dependency files**

This adds a second `pytest` specifier in `pyproject.toml`: the `testing` extra allows `pytest>=7.0`, while the `tests` group requires `pytest>=9.0,<9.1`. Align the specifiers to satisfy the dependency-version consistency rule.</violation>
</file>

<file name="infrahub_sdk/transfer/importer/json.py">

<violation number="1" location="infrahub_sdk/transfer/importer/json.py:199">
P2: Custom agent: **Flag AI Slop and Fabricated Changes**

This `continue_on_error` rendering change has no regression coverage: the importer tests never enable `continue_on_error` or exercise `execute_batches`. Add assertions for empty `GraphQLError.errors` and entries without `message` so both fallback behaviors stay protected.</violation>
</file>

<file name="docs/docs/python-sdk/sdk_ref/infrahub_sdk/node/related_node.mdx">

<violation number="1" location="docs/docs/python-sdk/sdk_ref/infrahub_sdk/node/related_node.mdx:129">
P3: The new `is_loaded` Returns text is split into separate bullets, so the sentence reads as fragments when rendered. The continuation lines should be plain text, not `- ` items. This comes from the doc generator, so the fix may belong there rather than in this file.</violation>
</file>

<file name=".github/workflows/ci.yml">

<violation number="1" location=".github/workflows/ci.yml:359">
P2: The install matrix omits Python 3.15 even though the project supports it, so this new plain-wheel install check does not cover every supported interpreter. Add 3.15 to the matrix.</violation>
</file>

<file name="infrahub_sdk/exceptions/base.py">

<violation number="1" location="infrahub_sdk/exceptions/base.py:102">
P3: An explicit empty `message` is replaced by the generated default here. Use an `is not None` check, as `GraphQLError` does, so a deliberate empty message is kept. The same pattern appears in the other optional-message constructors in this file.</violation>

<violation number="2" location="infrahub_sdk/exceptions/base.py:209">
P2: Pickling and unpickling these three exceptions fails with a TypeError because their constructors take more than the message. Add a `__reduce__` that returns `(_rebuild_error, (type(self), self.args, self.__dict__))`, as `FieldNotLoadedError` already does, to `RateLimitError`, `VersionNotSupportedError`, and `ObjectValidationError`. Round-trip coverage in tests/unit/sdk/test_exceptions.py does not include them.</violation>

<violation number="3" location="infrahub_sdk/exceptions/base.py:456">
P3: This docstring is copied from `UninitializedError`, so it describes the wrong failure. Replace it with a sentence about an invalid server response.</violation>
</file>

<file name="infrahub_sdk/trace_context.py">

<violation number="1" location="infrahub_sdk/trace_context.py:19">
P2: When OTEL_PROPAGATORS is invalid, this import fails on every request, because the failed module is not cached and the `ValueError` path only caches the warning. Cache the failure result too, so the import is not re-attempted per request.</violation>
</file>

<file name="AGENTS.md">

<violation number="1" location="AGENTS.md:65">
P3: The new Branches section says Infrahub pins `python_sdk` to the matching branch, but the release flow in this PR moves the `infrahub-release-1.12` pin to the `v1.24.0` tag. Add a note that pins move to the release tag after a final release.</violation>

<violation number="2" location="AGENTS.md:65">
P3: `python_sdk` is a git submodule, so Infrahub pins a commit rather than tracking an SDK branch; this wording can make readers expect branch-following behavior. Say that the submodule points to a commit from the matching SDK branch.</violation>
</file>

<file name="infrahub_sdk/ctl/cli_commands.py">

<violation number="1" location="infrahub_sdk/ctl/cli_commands.py:247">
P3: The comment above this `except` is inaccurate. The GraphQLError clause below already prints the message when `errors` is empty, so that is not why these lookup misses are re-raised. The real reason is that `catch_exception` renders them with the `Error:` prefix, which the tests check. Rewrite the comment so a maintainer does not remove the branch on the belief that it is redundant.</violation>
</file>

<file name="docs/docs/python-sdk/topics/error_handling.mdx">

<violation number="1" location="docs/docs/python-sdk/topics/error_handling.mdx:196">
P3: This claims every fallback is logged at debug level. On the authentication path, a response with a code that has no class raises `AuthenticationError` without a log line, because the logging only runs when no code was resolved. Narrow the claim to the cases that actually log.</violation>
</file>

<file name="infrahub_sdk/node/attribute.py">

<violation number="1" location="infrahub_sdk/node/attribute.py:220">
P2: `detach_from_pool()` sets `_has_data = True`, which marks the attribute as loaded even when its value was never fetched. A later `.value` read on a node from `only` then returns `None` silently instead of raising `FieldNotLoadedError`. The detach only needs to send `from_pool: None`, so drop the `_has_data` assignment here.</violation>
</file>

<file name="infrahub_sdk/yaml.py">

<violation number="1" location="infrahub_sdk/yaml.py:180">
P2: Errors from `spec` models are reported with a path relative to `spec`, but the message omits the `spec` prefix. With a file whose top-level `kind: Object` is valid, `spec` missing `kind` reads as `kind | Field required (missing)`, which looks like the top-level field is absent. Prefix the spec-level location, for example by passing ("spec",) into `_content_error` from the `spec` callers in `spec/object.py` and `spec/menu.py`.</violation>
</file>

<file name="CHANGELOG.md">

<violation number="1" location="CHANGELOG.md:54">
P3: This release note claims to list all new catalogue exception classes but omits the exported `WorkerTimeoutError`. Add `WorkerTimeoutError` to the list so users can discover the new `WORKER_TIMEOUT` exception.</violation>
</file>

<file name="docs/docs/python-sdk/guides/installation.mdx">

<violation number="1" location="docs/docs/python-sdk/guides/installation.mdx:36">
P2: This description points users to the wrong file: the plugin reads `.infrahub.yml` as repository configuration and discovers `infrahub_tests` only in `test_*.yml`/`test_*.yaml` files. Document the test-file naming and location instead.</violation>
</file>

<file name="infrahub_sdk/query_groups.py">

<violation number="1" location="infrahub_sdk/query_groups.py:37">
P2: `WORKER_TIMEOUT` is missing from `_REQUEST_FAILURE_CODES`, so a server-side worker timeout is recorded as a refusal of the current member and cleanup continues against the remaining members. Add it to the request-level codes so the timeout stops the reap and is re-raised unchanged.</violation>
</file>

<file name="infrahub_sdk/testing/repository.py">

<violation number="1" location="infrahub_sdk/testing/repository.py:91">
P2: `core.sharedRepository` does not make future checked-out worktree files world-writable, so files added after `_share()` runs can revert to the container user's umask and remain unwritable by another Infrahub container user. Apply the shared mode whenever the worktree is updated, or use a mechanism that enforces shared permissions for future worktree files.</violation>
</file>

<file name="infrahub_sdk/ctl/troubleshooting.py">

<violation number="1" location="infrahub_sdk/ctl/troubleshooting.py:74">
P3: These new troubleshooting commands cross the Infrahub server boundary, but coverage only verifies mocked HTTP responses. Add a functional or integration test against a compatible Infrahub server to verify the endpoint contract and response handling.

(Based on your team's feedback about requiring real-server coverage for server-bound SDK and CLI behavior.) [ID: 8542b3a4-57c4-4f1c-abe8-ef576231d2c1]</violation>
</file>

<file name="docs/docs/python-sdk/sdk_ref/infrahub_sdk/node/inline_peers.mdx">

<violation number="1" location="docs/docs/python-sdk/sdk_ref/infrahub_sdk/node/inline_peers.mdx:2">
P3: This SDK reference exposes the internal `peers_are_inline_input` predicate as a public API. Remove this page, or document the supported `RelationshipManager` behavior instead; keep internal implementation helpers out of the SDK reference.</violation>
</file>

Reply with feedback, questions, or to request a fix.

View guided diff | Turn on auto-fix | Re-trigger cubic

Comment thread pyproject.toml
# The bundled `pytest-infrahub` plugin and the schemas under `infrahub_sdk.testing`, for writing
# tests against your own Transforms, Queries and Checks.
testing = [
"pytest>=7.0",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Custom agent: Detect conflicting package versions across dependency files

This adds a second pytest specifier in pyproject.toml: the testing extra allows pytest>=7.0, while the tests group requires pytest>=9.0,<9.1. Align the specifiers to satisfy the dependency-version consistency rule.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At pyproject.toml, line 69:

<comment>This adds a second `pytest` specifier in `pyproject.toml`: the `testing` extra allows `pytest>=7.0`, while the `tests` group requires `pytest>=9.0,<9.1`. Align the specifiers to satisfy the dependency-version consistency rule.</comment>

<file context>
@@ -43,38 +52,48 @@ infrahubctl = "infrahub_sdk.ctl.cli:app"
+# The bundled `pytest-infrahub` plugin and the schemas under `infrahub_sdk.testing`, for writing
+# tests against your own Transforms, Queries and Checks.
+testing = [
+    "pytest>=7.0",
+]
+
</file context>
Suggested change
"pytest>=7.0",
"pytest>=9.0,<9.1",

if isinstance(result, GraphQLError):
# Keyed on there being server errors to render rather than on the class: a
# lookup miss is a GraphQLError too, and carries its reason in its message.
if isinstance(result, GraphQLError) and result.errors:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Custom agent: Flag AI Slop and Fabricated Changes

This continue_on_error rendering change has no regression coverage: the importer tests never enable continue_on_error or exercise execute_batches. Add assertions for empty GraphQLError.errors and entries without message so both fallback behaviors stay protected.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At infrahub_sdk/transfer/importer/json.py, line 199:

<comment>This `continue_on_error` rendering change has no regression coverage: the importer tests never enable `continue_on_error` or exercise `execute_batches`. Add assertions for empty `GraphQLError.errors` and entries without `message` so both fallback behaviors stay protected.</comment>

<file context>
@@ -194,9 +194,13 @@ async def execute_batches(
-                    if isinstance(result, GraphQLError):
+                    # Keyed on there being server errors to render rather than on the class: a
+                    # lookup miss is a GraphQLError too, and carries its reason in its message.
+                    if isinstance(result, GraphQLError) and result.errors:
                         error_name = type(result).__name__
-                        error_msgs = [err["message"] for err in result.errors]
</file context>

Comment thread .github/workflows/ci.yml
install-matrix:
strategy:
matrix:
python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"]

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: The install matrix omits Python 3.15 even though the project supports it, so this new plain-wheel install check does not cover every supported interpreter. Add 3.15 to the matrix.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At .github/workflows/ci.yml, line 359:

<comment>The install matrix omits Python 3.15 even though the project supports it, so this new plain-wheel install check does not cover every supported interpreter. Add 3.15 to the matrix.</comment>

<file context>
@@ -310,6 +310,215 @@ jobs:
+  install-matrix:
+    strategy:
+      matrix:
+        python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"]
+    if: |
+      always() && !cancelled() &&
</file context>
Suggested change
python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"]
python-version: ["3.10", "3.11", "3.12", "3.13", "3.14", "3.15"]

return (self.__class__, (self.failures,))


class VersionNotSupportedError(Error):

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Pickling and unpickling these three exceptions fails with a TypeError because their constructors take more than the message. Add a __reduce__ that returns (_rebuild_error, (type(self), self.args, self.__dict__)), as FieldNotLoadedError already does, to RateLimitError, VersionNotSupportedError, and ObjectValidationError. Round-trip coverage in tests/unit/sdk/test_exceptions.py does not include them.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At infrahub_sdk/exceptions/base.py, line 209:

<comment>Pickling and unpickling these three exceptions fails with a TypeError because their constructors take more than the message. Add a `__reduce__` that returns `(_rebuild_error, (type(self), self.args, self.__dict__))`, as `FieldNotLoadedError` already does, to `RateLimitError`, `VersionNotSupportedError`, and `ObjectValidationError`. Round-trip coverage in tests/unit/sdk/test_exceptions.py does not include them.</comment>

<file context>
@@ -0,0 +1,522 @@
+        return (self.__class__, (self.failures,))
+
+
+class VersionNotSupportedError(Error):
+    """Raised when a feature is used against an Infrahub server version that does not support it."""
+
</file context>

return {}

try:
from opentelemetry import propagate # noqa: PLC0415

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: When OTEL_PROPAGATORS is invalid, this import fails on every request, because the failed module is not cached and the ValueError path only caches the warning. Cache the failure result too, so the import is not re-attempted per request.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At infrahub_sdk/trace_context.py, line 19:

<comment>When OTEL_PROPAGATORS is invalid, this import fails on every request, because the failed module is not cached and the `ValueError` path only caches the warning. Cache the failure result too, so the import is not re-attempted per request.</comment>

<file context>
@@ -0,0 +1,54 @@
+        return {}
+
+    try:
+        from opentelemetry import propagate  # noqa: PLC0415
+    except ImportError:
+        return {}
</file context>

| A server predating the catalogue, or an error with no `extensions` | `exc.code` is `None`, and the message is the one that version of the SDK has always produced |
| A payload that does not match what the catalogue declares | The generic class for the transport, with the code still readable |

Every fallback is logged at debug level on the `infrahub_sdk` logger, naming the code where the

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3: This claims every fallback is logged at debug level. On the authentication path, a response with a code that has no class raises AuthenticationError without a log line, because the logging only runs when no code was resolved. Narrow the claim to the cases that actually log.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At docs/docs/python-sdk/topics/error_handling.mdx, line 196:

<comment>This claims every fallback is logged at debug level. On the authentication path, a response with a code that has no class raises `AuthenticationError` without a log line, because the logging only runs when no code was resolved. Narrow the claim to the cases that actually log.</comment>

<file context>
@@ -0,0 +1,212 @@
+| A server predating the catalogue, or an error with no `extensions` | `exc.code` is `None`, and the message is the one that version of the SDK has always produced |
+| A payload that does not match what the catalogue declares | The generic class for the transport, with the code still readable |
+
+Every fallback is logged at debug level on the `infrahub_sdk` logger, naming the code where the
+response carried one, so an SDK meeting a newer server is diagnosable without a debugger.
+
</file context>

Comment thread AGENTS.md
Comment on lines +65 to +66
The Infrahub repository pins `python_sdk` to the branch that matches its own: `stable` to `stable`,
`release-x.y` to `infrahub-release-x.y`, `develop` to `infrahub-develop`.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3: python_sdk is a git submodule, so Infrahub pins a commit rather than tracking an SDK branch; this wording can make readers expect branch-following behavior. Say that the submodule points to a commit from the matching SDK branch.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At AGENTS.md, line 65:

<comment>`python_sdk` is a git submodule, so Infrahub pins a commit rather than tracking an SDK branch; this wording can make readers expect branch-following behavior. Say that the submodule points to a commit from the matching SDK branch.</comment>

<file context>
@@ -53,6 +53,22 @@ infrahub_sdk/
+| `infrahub-release-x.y` | The SDK that ships with Infrahub `x.y`; created from `infrahub-develop` when Infrahub cuts `release-x.y` |
+| `infrahub-develop` | SDK changes that need the next Infrahub version |
+
+The Infrahub repository pins `python_sdk` to the branch that matches its own: `stable` to `stable`,
+`release-x.y` to `infrahub-release-x.y`, `develop` to `infrahub-develop`.
+
</file context>
Suggested change
The Infrahub repository pins `python_sdk` to the branch that matches its own: `stable` to `stable`,
`release-x.y` to `infrahub-release-x.y`, `develop` to `infrahub-develop`.
The Infrahub repository's `python_sdk` submodule points to a commit from the SDK branch that matches its own: `stable` to `stable`,
`release-x.y` to `infrahub-release-x.y`, `develop` to `infrahub-develop`.

Comment thread CHANGELOG.md
print("some other failure:", exc.code)
```

The new classes are `AttributeConstraintViolationError`, `AttributeInvalidTypeError`, `AttributeRequiredError`, `BranchAlreadyMergedError`, `BranchNeedsRebaseError`, `MergeInProgressError`, `MergeRecoveryRequiredError`, `UndefinedError`, and `UniquenessViolationError`. Each is typed exactly as the catalogue declares the payload, so a required field is never optional and needs no guard. They all descend from `GraphQLError`, so no `except` clause stops catching what it catches today. `NODE_NOT_FOUND`, `BRANCH_NOT_FOUND` and `SCHEMA_NOT_FOUND` reach the classes the SDK already had for them, listed under Changed.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3: This release note claims to list all new catalogue exception classes but omits the exported WorkerTimeoutError. Add WorkerTimeoutError to the list so users can discover the new WORKER_TIMEOUT exception.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At CHANGELOG.md, line 54:

<comment>This release note claims to list all new catalogue exception classes but omits the exported `WorkerTimeoutError`. Add `WorkerTimeoutError` to the list so users can discover the new `WORKER_TIMEOUT` exception.</comment>

<file context>
@@ -11,6 +11,192 @@ This project uses [*towncrier*](https://towncrier.readthedocs.io/) and the chang
+      print("some other failure:", exc.code)
+  ```
+
+  The new classes are `AttributeConstraintViolationError`, `AttributeInvalidTypeError`, `AttributeRequiredError`, `BranchAlreadyMergedError`, `BranchNeedsRebaseError`, `MergeInProgressError`, `MergeRecoveryRequiredError`, `UndefinedError`, and `UniquenessViolationError`. Each is typed exactly as the catalogue declares the payload, so a required field is never optional and needs no guard. They all descend from `GraphQLError`, so no `except` clause stops catching what it catches today. `NODE_NOT_FOUND`, `BRANCH_NOT_FOUND` and `SCHEMA_NOT_FOUND` reach the classes the SDK already had for them, listed under Changed.
+
+  `exc.http_status` reads the status the envelope declares. Where the envelope omits one, a generated class supplies the status the catalogue gives its code; the three lookup-miss classes declare none, since they are also raised with no server behind them, and stay `None` there.
</file context>
Suggested change
The new classes are `AttributeConstraintViolationError`, `AttributeInvalidTypeError`, `AttributeRequiredError`, `BranchAlreadyMergedError`, `BranchNeedsRebaseError`, `MergeInProgressError`, `MergeRecoveryRequiredError`, `UndefinedError`, and `UniquenessViolationError`. Each is typed exactly as the catalogue declares the payload, so a required field is never optional and needs no guard. They all descend from `GraphQLError`, so no `except` clause stops catching what it catches today. `NODE_NOT_FOUND`, `BRANCH_NOT_FOUND` and `SCHEMA_NOT_FOUND` reach the classes the SDK already had for them, listed under Changed.
The new classes are `AttributeConstraintViolationError`, `AttributeInvalidTypeError`, `AttributeRequiredError`, `BranchAlreadyMergedError`, `BranchNeedsRebaseError`, `MergeInProgressError`, `MergeRecoveryRequiredError`, `UndefinedError`, `UniquenessViolationError`, and `WorkerTimeoutError`. Each is typed exactly as the catalogue declares the payload, so a required field is never optional and needs no guard. They all descend from `GraphQLError`, so no `except` clause stops catching what it catches today. `NODE_NOT_FOUND`, `BRANCH_NOT_FOUND` and `SCHEMA_NOT_FOUND` reach the classes the SDK already had for them, listed under Changed.

async def get_trace_sample_ratio(_: str = CONFIG_PARAM) -> None:
"""Show the trace sampling ratio of the API server that answers."""
client = initialize_client()
response = await client._get(url=f"{client.address}{TRACE_SAMPLE_RATIO_PATH}")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3: These new troubleshooting commands cross the Infrahub server boundary, but coverage only verifies mocked HTTP responses. Add a functional or integration test against a compatible Infrahub server to verify the endpoint contract and response handling.

(Based on your team's feedback about requiring real-server coverage for server-bound SDK and CLI behavior.) [ID: 8542b3a4-57c4-4f1c-abe8-ef576231d2c1]

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At infrahub_sdk/ctl/troubleshooting.py, line 74:

<comment>These new troubleshooting commands cross the Infrahub server boundary, but coverage only verifies mocked HTTP responses. Add a functional or integration test against a compatible Infrahub server to verify the endpoint contract and response handling.

(Based on your team's feedback about requiring real-server coverage for server-bound SDK and CLI behavior.) [ID: 8542b3a4-57c4-4f1c-abe8-ef576231d2c1]</comment>

<file context>
@@ -0,0 +1,102 @@
+async def get_trace_sample_ratio(_: str = CONFIG_PARAM) -> None:
+    """Show the trace sampling ratio of the API server that answers."""
+    client = initialize_client()
+    response = await client._get(url=f"{client.address}{TRACE_SAMPLE_RATIO_PATH}")
+    _print_state(response)
+
</file context>

@@ -0,0 +1,18 @@
---

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3: This SDK reference exposes the internal peers_are_inline_input predicate as a public API. Remove this page, or document the supported RelationshipManager behavior instead; keep internal implementation helpers out of the SDK reference.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At docs/docs/python-sdk/sdk_ref/infrahub_sdk/node/inline_peers.mdx, line 2:

<comment>This SDK reference exposes the internal `peers_are_inline_input` predicate as a public API. Remove this page, or document the supported `RelationshipManager` behavior instead; keep internal implementation helpers out of the SDK reference.</comment>

<file context>
@@ -0,0 +1,18 @@
+---
+title: inline_peers
+sidebarTitle: inline_peers
+---
</file context>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

group/ci Issue related to the CI pipeline type/documentation Improvements or additions to documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

10 participants