Skip to content

Merge 'infrahub-develop' into 'stable'#966

Merged
wvandeun merged 108 commits intostablefrom
infrahub-develop
Apr 24, 2026
Merged

Merge 'infrahub-develop' into 'stable'#966
wvandeun merged 108 commits intostablefrom
infrahub-develop

Conversation

@ogenstad
Copy link
Copy Markdown
Contributor

Why

Prepare for version 1.20.0 to go with Infrahub 1.9.0

What changed

  • Everything from infrahub-develop into stable

ogenstad and others added 30 commits March 13, 2026 15:42
Merge stable into develop
Merge develop into infrahub-develop
Merge stable into develop
* update schemas related to CoreKeyValue object

* putting the value of KeyValue object into generic schema

* updated schema since the CoreEnvironmentVariableKeyValue has been renamed CoreEnvKeyValue

---------

Co-authored-by: polmichel <pol@opsmill.com>
This parameter has been deprecated for a while and should not be used
anymore.
Clean up logic to load repository config items
Merge stable into develop
Merge stable into develop
Add GraphQL fragment support in .infrahub.yml
Merge stable into develop
Introduce artifact_content, file_object_content, from_json, and from_yaml
Jinja2 filters to enable modular configuration pipelines where templates
can reference and inline rendered content from other artifacts.

Replace FilterDefinition.trusted boolean with a flag-based ExecutionContext
model (CORE, WORKER, LOCAL) for context-aware template validation.
Jinja2Template gains an optional client parameter and a set_client() method
for deferred client injection.
Merge develop into infrahub-develop
Merge stable into develop
Merge stable into develop
Merge stable into develop
Merge develop into infrahub-develop
…overy

Add a new `infrahub` command as a separate entry point alongside `infrahubctl`.
While `infrahubctl` targets developers building on top of Infrahub, the new
`infrahub` command targets end users who need to query, create, update, and
delete data in the Infrahub database.

Commands:
- `infrahub get <kind> [identifier]` — list or detail view with table/JSON/CSV/YAML output
- `infrahub create <kind>` — create objects via --set flags or --file (JSON/YAML)
- `infrahub update <kind> <identifier>` — update objects via --set flags or --file
- `infrahub delete <kind> <identifier>` — delete with confirmation prompt (--yes to skip)
- `infrahub schema list/show` — discover available kinds and their attributes

Key features:
- Four output formats: table (default TTY), JSON (default piped), CSV, YAML
- YAML output uses Infrahub Object format (apiVersion/kind/spec) for round-tripping
- Unified --set flag for both attributes and relationships
- Reuses existing SDK client, config, and AsyncTyper infrastructure
- 87 unit tests, 16 integration tests
- Fix MD060 table column style in plan.md and quickstart.md
- Fix MD032 blanks-around-lists in research.md
- Fix MD050 strong-style (escaped __init__.py underscores) in tasks.md
- Split integration test class to stay under PLR0904 method limit
- Make CLI runner tests sync to avoid asyncio.run() nested loop error
- Add 47 new tests (134 total, up from 87)
- schema.py: test list/show with mocked client, filter, branch, empty schema
- create.py: test --set inline, --file, invalid field, multiple args, branch
- update.py: test --set attributes/relationships, --file, branch
- delete.py: test --yes, -y, branch, confirmation abort/accept
- formatters/__init__.py: test detect_output_format TTY/non-TTY, get_formatter
- yaml/csv/table: test many-cardinality rels, empty peers, None values
- Fix MD032 blanks-around-lists in cli-commands.md and data-model.md
- Revert SDK ref docs to match stable (CI regenerates with its own mdxify version)
- Add type coercion in parse_set_args (int, float, bool, null) so
  --set height=190 sends an integer instead of string "190"
- Fix MD032 blanks-around-lists in cli-commands.md and data-model.md
- Revert SDK ref docs to stable baseline (CI regenerates with its own
  mdxify version)
- Add error output to integration test assertions for debugging
Instead of a separate `infrahub` entry point, register get, create,
update, and delete as top-level commands on the existing `infrahubctl`
CLI. Add schema list and schema show as subcommands of the existing
`infrahubctl schema` group alongside load, check, and export.

- Remove infrahub entry point from pyproject.toml
- Remove enduser_cli.py and enduser_commands.py
- Register commands in cli_commands.py
- Merge schema list/show into ctl/schema.py
- Update all tests to use cli_commands.app
ogenstad and others added 23 commits April 8, 2026 15:19
Merge stable into develop
Merge 'stable' into 'develop'
Merge 'develop' into 'infrahub-develop'
…api_token

When username/password are explicitly provided, clear any api_token from environment variables to allow password authentication to take precedence. This resolves the issue where users with INFRAHUB_API_TOKEN in their environment couldn't use password authentication.

Co-authored-by: ogenstad <6694669+ogenstad@users.noreply.github.com>
Fix authentication validation to allow password auth to override env api_token
The get, create, update, and delete commands were registered at the
root of infrahubctl, which felt out of place next to unrelated
top-level commands like check, render, and transform. They naturally
belong under `infrahubctl object` alongside load and validate, since
they all operate on Infrahub objects. Tests updated accordingly.
Merge stable into develop
The CRUD command files (create, delete, get, update) and their shared
utilities lived in a generic "commands" directory that didn't convey
what they were for. Since they all belong to the "infrahubctl object"
subgroup, it makes sense to colocate them as an "object" package.

Test files follow the same restructuring.
Merge develop into infrahub-develop
Signed-off-by: Fatih Acar <fatih@opsmill.com>
The point of upserting an object is to let the API server in charge of
deciding what to do. Trying to find if a node is going to be created or
updated just for a `print()` seems to be excessive.

The node not found error should be raised without needing to call `get`
and trigger an API server query/response.
Merge develop into infrahub-develop
Raise a new file not found error when loading queries
Add an optional `description` field to `InfrahubPythonTransformConfig`
to achieve parity with `InfrahubJinja2TransformConfig`. This allows users
to set descriptions for Python transforms in `.infrahub.yml`.

Closes opsmill/infrahub#6382

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The SDK constructed URLs under /api/files/* for the three
file_object_content* Jinja2 filters, but the Infrahub backend serves
these endpoints under /api/storage/files/*. Every call 404ed. Updated
all six URLs (async + sync) in object_store.py to the correct prefix.

Added happy-path unit tests for file_object_content_by_id and
file_object_content_by_hfid (string and list forms) so similar
contract drift with the backend router is caught in CI.

Fixes #954

* Remove changelog entry for unreleased code fix

The bug was introduced in the same release cycle, so a changelog
record would appear as a fix for something that was never released.

---------

Co-authored-by: Phillip Simonds <phillip@opsmill.com>
Co-authored-by: Guillaume Mazoyer <guillaume@opsmill.com>
render_jinja2_template in the CLI constructed a Jinja2Template and
called .render() without ever calling .validate(). Today that is
accidentally safe: WORKER-only filters like artifact_content fail with
"requires an InfrahubClient" because infrahubctl render does not pass
one. But the moment a future change threads a client through — a
natural thing to do to enable iterative transform development — those
filters would silently run locally, bypassing the WORKER-only gate.

Add jinja_template.validate(context=ExecutionContext.LOCAL) before
.render() so the context gate is enforced regardless of client state.

Incidental: Jinja2Template.validate() did not handle
jinja2.TemplateNotFound from env.loader.get_source() the way .render()
does — a missing file-based template raised raw TemplateNotFound that
escaped callers expecting JinjaTemplateError. Wrapped it in
JinjaTemplateNotFoundError to match render()'s behavior and added a
unit test for the case.

Added a fixture template using artifact_content plus a parametrised
CLI test asserting infrahubctl render rejects it with the expected
violation message. Updated the invalid-filter test: missing filters
are now caught at validate() time with the standard filter-gating
error message rather than at render time.

Fixes #955

---------

Co-authored-by: Phillip Simonds <phillip@opsmill.com>
Co-authored-by: Guillaume Mazoyer <guillaume@opsmill.com>
#959)

ObjectStore.get() and ObjectStore.upload() (async + sync) caught
httpx.HTTPStatusError in an except block that only converted 401/403
to AuthenticationError. For any other status code (404, 500, etc.)
the exception was silently dropped and execution fell through to the
return statement — `return resp.text` for get() and `return resp.json()`
for upload(). Callers received the error body as if it were valid
content.

The downstream impact surfaced during INFP-504 testing: the new
`artifact_content` Jinja2 filter calls `object_store.get()`; when the
filter was passed a non-existent storage_id, the backend correctly
returned HTTP 404 with a GraphQL-shaped error body, but the SDK
silently returned that body as a string, which became the artifact's
content. The artifact was marked Ready with a corrupt payload.

Fix: add a trailing `raise` at the end of the
`except httpx.HTTPStatusError` block in all four places, matching the
pattern already used in `_get_file()` (lines 99 and 185). Non-401/403
HTTP errors now propagate to callers.

Added unit tests covering:
- get() raises httpx.HTTPStatusError on 404
- upload() raises httpx.HTTPStatusError on 500
- get() still converts 401/403 to AuthenticationError (unchanged)
Both parametrised for async and sync clients.

Fixes #958

---------

Co-authored-by: Phillip Simonds <phillip@opsmill.com>
Co-authored-by: Guillaume Mazoyer <guillaume@opsmill.com>
Merge stable into develop
Merge stable into develop
…observability (#965)

* IHS-219: Add query_name parameter to all(), filters(), and get() for observability

* update docs

* update getting kind as string logic

* update docs

* update docs

* update docs
Merge develop into infrahub-develop
@github-actions github-actions Bot added the type/documentation Improvements or additions to documentation label Apr 24, 2026
@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 24, 2026

Codecov Report

❌ Patch coverage is 85.04202% with 178 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
infrahub_sdk/ctl/telemetry.py 29.72% 52 Missing ⚠️
infrahub_sdk/object_store.py 59.42% 26 Missing and 2 partials ⚠️
infrahub_sdk/ctl/object/update.py 75.78% 15 Missing and 8 partials ⚠️
infrahub_sdk/ctl/formatters/csv.py 79.54% 6 Missing and 3 partials ⚠️
infrahub_sdk/ctl/formatters/base.py 82.22% 5 Missing and 3 partials ⚠️
infrahub_sdk/ctl/formatters/table.py 85.10% 5 Missing and 2 partials ⚠️
infrahub_sdk/ctl/formatters/yaml.py 87.75% 3 Missing and 3 partials ⚠️
infrahub_sdk/node/node.py 82.35% 3 Missing and 3 partials ⚠️
infrahub_sdk/ctl/object/get.py 86.48% 3 Missing and 2 partials ⚠️
infrahub_sdk/template/infrahub_filters.py 93.58% 3 Missing and 2 partials ⚠️
... and 13 more
@@            Coverage Diff             @@
##           stable     #966      +/-   ##
==========================================
+ Coverage   81.08%   81.41%   +0.33%     
==========================================
  Files         131      134       +3     
  Lines       10895    11347     +452     
  Branches     1647     1703      +56     
==========================================
+ Hits         8834     9238     +404     
- Misses       1513     1566      +53     
+ Partials      548      543       -5     
Flag Coverage Δ
integration-tests 41.84% <43.19%> (-1.03%) ⬇️
python-3.10 54.34% <74.45%> (+0.72%) ⬆️
python-3.11 54.36% <74.45%> (+0.74%) ⬆️
python-3.12 54.36% <74.45%> (+0.76%) ⬆️
python-3.13 54.36% <74.45%> (+0.76%) ⬆️
python-3.14 54.34% <74.51%> (+0.72%) ⬆️
python-filler-3.12 22.74% <11.09%> (-0.07%) ⬇️

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

Files with missing lines Coverage Δ
infrahub_sdk/ctl/cli_commands.py 72.33% <100.00%> (+0.55%) ⬆️
infrahub_sdk/ctl/formatters/__init__.py 100.00% <100.00%> (ø)
infrahub_sdk/ctl/formatters/json.py 100.00% <100.00%> (ø)
infrahub_sdk/ctl/object/__init__.py 44.44% <100.00%> (ø)
infrahub_sdk/ctl/schema.py 61.72% <100.00%> (ø)
infrahub_sdk/ctl/utils.py 68.53% <100.00%> (ø)
infrahub_sdk/ctl/validate.py 52.11% <ø> (ø)
infrahub_sdk/protocols.py 100.00% <100.00%> (ø)
infrahub_sdk/protocols_generator/generator.py 95.00% <100.00%> (ø)
infrahub_sdk/template/exceptions.py 96.96% <100.00%> (+0.96%) ⬆️
... and 25 more

... and 1 file with indirect coverage changes

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

@ogenstad ogenstad marked this pull request as ready for review April 24, 2026 11:55
@ogenstad ogenstad requested a review from a team as a code owner April 24, 2026 11:55
@wvandeun wvandeun merged commit a501ee6 into stable Apr 24, 2026
20 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

type/documentation Improvements or additions to documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.