Skip to content

Commit 2ff8ae9

Browse files
authored
Merge pull request #8628 from opsmill/release-1.8-to-develop
Release 1.8 to develop
2 parents 6a1cbe1 + a17d15b commit 2ff8ae9

File tree

103 files changed

+2972
-652
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

103 files changed

+2972
-652
lines changed

.github/labeler.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,7 @@
1414
"type/documentation":
1515
- changed-files:
1616
- any-glob-to-any-file: ["docs/**"]
17+
18+
"type/spec":
19+
- changed-files:
20+
- any-glob-to-any-file: ["dev/specs/**"]

.github/labels.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,10 @@
8282
description: "Topic for brainstorming, discussions"
8383
color: "e19e0f"
8484

85+
- name: "type/spec"
86+
description: "A specification for an upcoming change to the project"
87+
color: "8b5cf6"
88+
8589
- name: "type/user-centric"
8690
description: "Issue that would improve the overall experience of our users"
8791
color: "ff8c00"

.markdownlint-cli2.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,3 +34,5 @@ config:
3434
# Files to ignore within docs/docs/
3535
ignores:
3636
- "docs/docs/reference/**"
37+
- "docs/docs/release-notes/**"
38+
- "**/AGENTS.md"

.vale/styles/spelling-exceptions.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ bool
2525
boolean
2626
booleans
2727
Buildkite
28+
Ceph
2829
changelog
2930
check_color_tags_name
3031
check_definitions
@@ -133,6 +134,7 @@ namespaces
133134
nats
134135
Nautobot
135136
Neo4j
137+
NGINX
136138
Netbox
137139
Netutils
138140
Newsfragment
@@ -210,7 +212,9 @@ Terraform
210212
Toml
211213
TOML
212214
toolchain
215+
tooltip
213216
Towncrier
217+
Traefik
214218
TypeScript
215219
uniqueness_constraints
216220
unoptimized
@@ -242,3 +246,4 @@ Yaml
242246
YAML
243247
yamllint
244248
YouTube
249+
AIOps

CHANGELOG.md

Lines changed: 200 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,206 @@ This project uses [*towncrier*](https://towncrier.readthedocs.io/) and the chang
1111

1212
<!-- towncrier release notes start -->
1313

14+
## [Infrahub - v1.8.0](https://github.com/opsmill/infrahub/tree/infrahub-v1.8.0) - 2026-03-16
15+
16+
We're excited to announce the release of Infrahub, v1.8.0!
17+
18+
This release introduces a file objects feature, adds stronger branch life-cycle controls with automatic freeze-on-merge, and adds support for resource pools in object templates. The Infrahub Backup tool now fully supports Kubernetes deployments.
19+
20+
## Main changes
21+
22+
### File Object: Upload and attach files to Infrahub objects
23+
24+
Infrahub can now store files -- Text files, PDFs, images, spreadsheets, KMZ files, and any other format -- directly as objects in the database. With the new `CoreFileObject` generic, you can define custom file types in your schema. Object files behave as all other objects in Infrahub, you can fully customize the schema and relate (or attach) them to other objects.
25+
26+
The contents of the file will be rendered in Infrahub's web interface, if the file has one of the following file types:
27+
28+
- application/json
29+
- application/yaml
30+
- application/x-yaml
31+
- application/hcl
32+
- application/graphql
33+
- application/pdf
34+
- image/svg+xml
35+
- text/plain
36+
- text/markdown
37+
- application/xml
38+
- text/csv;
39+
- image/png
40+
- image/jpeg
41+
- image/gif
42+
- image/webp
43+
- image/bmp
44+
- image/x-icon
45+
46+
To use this feature, create a schema node that inherits from `CoreFileObject`:
47+
48+
```yaml
49+
nodes:
50+
- name: ContractDocument
51+
namespace: Custom
52+
inherit_from:
53+
- CoreFileObject
54+
attributes:
55+
- name: contract_number
56+
kind: Text
57+
```
58+
59+
The `CoreFileObject` generic automatically provides read-only attributes for file metadata: `file_name`, `checksum` (SHA-1), `file_size`, `file_type` (MIME type), and `storage_id`.
60+
61+
**Upload** files through GraphQL mutations -- a `file` argument is automatically added to Create, Update, and Upsert mutations for any node inheriting from `CoreFileObject`.
62+
63+
**Download** files through the UI or these REST API endpoints:
64+
- `/api/files/{node_id}` -- by node UUID
65+
- `/api/files/by-hfid/{kind}` -- by human-friendly ID
66+
- `/api/files/by-storage-id/{storage_id}` -- by internal storage ID
67+
68+
The maximum file size defaults to 50 MB and is configurable via the `INFRAHUB_STORAGE_MAX_FILE_SIZE` environment variable.
69+
70+
### Freeze branch after merge
71+
72+
When a branch is merged -- either through a direct branch merge or via a Proposed Change -- it now transitions to a frozen state where no further mutations are allowed. This prevents a class of data integrity issues that could occur when a branch was modified or merged a second time after its initial merge.
73+
74+
Both the backend API and the frontend UI enforce this freeze:
75+
- GraphQL mutations (Create, Upsert, Update, Delete) are blocked on merged branches
76+
- The UI disables editing controls and shows a visual indication that the branch is frozen
77+
- Creating a new Proposed Change for an already-merged branch is prevented
78+
79+
### Resource pool references in object templates
80+
81+
Object templates can now reference resource pools (IP Address, IP Prefix, and Number pools). Previously, adding a resource pool to a template would allocate a resource to the template itself -- not the intended behavior. In 1.8, pool references on templates are stored as metadata. When an object is created from the template, the resource is allocated from the specified pool at creation time.
82+
83+
This applies to all pool types:
84+
- IP Address pools
85+
- IP Prefix pools
86+
- Number pools
87+
88+
The feature introduces a new `relationship_properties` field in the GraphQL schema for template relationships, which stores the pool source reference alongside the standard `edges` field. Template inheritance (subtemplates) correctly propagates pool references.
89+
90+
A database migration is included to convert any existing template-IP relationships that incorrectly have pool sources into the new `_from_resource_pool` relationship format.
91+
92+
### Consult the diff of a proposed change after branch deletion
93+
94+
The data and schema diff of a Proposed Change is now preserved and accessible even after the associated branch has been deleted. This is essential for audit and compliance workflows -- during incident investigation or regulatory review, users need to inspect what changes were made, by whom, and when, regardless of whether the source branch still exists.
95+
96+
The diff data is now tied to the Proposed Change itself rather than solely to the branch. The Files and Artifacts tabs on a Proposed Change also handle deleted branches gracefully, showing a user-friendly message instead of an error.
97+
98+
This feature is a prerequisite for a future capability to automatically delete branches after merge, which will help prevent stale branches that can cause Git synchronization issues.
99+
100+
### Read-only repository: Update to Latest button
101+
102+
Managing read-only Git repositories is now simpler. A new "Update to Latest" button fetches and imports the latest commit from the tracked branch directly from the UI. Previously, users had to manually copy and paste commit hashes from an external source to update what Infrahub was tracking. The existing reimport action has been renamed to "Reimport Current Commit" to clearly distinguish between re-processing the current commit and pulling the latest.
103+
104+
Repositories now also support providing a Git Tag as the reference (ref) to track for a repository.
105+
106+
### Infrahub Backup: Kubernetes support
107+
108+
The `infrahub-backup` CLI tool now fully supports Kubernetes deployments for both backup and restore operations. The tool automatically detects whether Infrahub is running on Docker Compose or Kubernetes and adjusts its behavior accordingly.
109+
110+
For Kubernetes deployments we can now install `infrahub-backup` using the Infrahub Helm Chart. This is now the recommended installation method for Kubernetes deployments.
111+
See the [installation instructions](https://docs.infrahub.app/backup/guides/install#enable-via-infrahub-helm-chart-recommended) for more details
112+
113+
Key new capabilities:
114+
- `infrahub-backup create --k8s-namespace <namespace>` -- creates a backup archive containing Neo4j and PostgreSQL database dumps
115+
- `infrahub-backup restore <backup_file> --k8s-namespace <namespace>` -- restores from an archive, handling service stop/start, cache/queue cleanup, database restore, and service restart automatically
116+
- Supports Neo4j Enterprise Edition online backups
117+
- Backup archives include metadata with Infrahub version, Neo4j edition, components backed up, and timestamps
118+
119+
### Display artifact count in proposed changes
120+
121+
The Proposed Changes detail view now displays item counts on all tabs, giving you immediate visibility into how many changes exist in each category:
122+
123+
- **Data** -- count of added, updated, and removed nodes
124+
- **Files** -- total count of changed files across repositories
125+
- **Artifacts** -- count of changed artifacts (excludes unchanged)
126+
- **Schema** -- count of schema changes
127+
- **Checks** -- count of validators
128+
- **Tasks** -- count of related tasks
129+
130+
### Branch list page improvements
131+
132+
The branch list page continues to evolve with richer information and better usability:
133+
134+
- **Created By** column shows who created each branch (available for branches created after 1.7)
135+
- **Proposed Changes** column links directly to associated proposed changes
136+
- **Status** column shows branch state with warning indicators (e.g., "Rebase needed")
137+
- **Schema Changes** indicator shows whether the branch includes schema modifications
138+
- **Last Rebase** timestamp for sync tracking
139+
- **Merged badge** clearly identifies branches that have been merged
140+
- Merged branches are filtered from the proposed change creation form
141+
142+
### General UI improvements
143+
144+
Several smaller improvements enhance the day-to-day experience:
145+
146+
- **Schema field shortcuts** -- clicking an attribute or relationship label in the object detail view opens the schema viewer modal, scrolling directly to the relevant field definition
147+
- **Field type icons** -- icons next to field names indicate the attribute type (text, number, boolean) and relationship schema
148+
- **Diff status badges** -- file and artifact diffs now show badges indicating the type of change (added, removed, updated)
149+
- **Branch artifacts tab** -- view artifact changes directly from the branch details view
150+
- **Refresh button** -- task list and details views now include a manual refresh button with a tooltip showing the last data refresh time
151+
- **Consistent focus outlines** -- improved visual accessibility across all interactive elements
152+
153+
## Infrahub Python SDK
154+
155+
Infrahub v1.8.0 requires the usage of infrahub-sdk v1.19.0, please update the `infrahub-sdk` package accordingly.
156+
157+
Notable SDK changes in this release:
158+
- Added support for the File Object feature
159+
- Fixed an issue where the SDK tracking feature would fail when deleting a parent node with component relationships (e.g., a device with interfaces). The SDK now correctly handles cascade deletions where component nodes are automatically removed when their parent is deleted, preventing "Unable to find the node" errors in generator workflows.
160+
161+
## Full changelog
162+
163+
### Added
164+
165+
- Added the ability to also fetch tags from git ([#8078](https://github.com/opsmill/infrahub/issues/8078))
166+
- Added `Builtin` to the list of restricted namespaces
167+
- Added `CoreFileObject` generic for storing files as node attributes with branch-aware versioning. Nodes inheriting from `CoreFileObject` support file upload via GraphQL mutations and download via REST API endpoints.
168+
- Added a refresh button to the task list and details view with a tooltip showing the last data refresh time
169+
- Added a shortcut in the object details view: clicking an attribute or relationship label opens the schema viewer modal, directly showing and scrolling to the relevant field definition
170+
- Added ability to view artifact changes from the branch details view
171+
- Added consistent focus outline color across all interactive elements for improved visual accessibility
172+
- Added counts to proposed change tabs
173+
- Added icons next to field names in the object details view to indicate field types (e.g., text, number, boolean) and relationship schemas
174+
- Added status badges to file and artifact diffs showing the type of change (added, removed, updated)
175+
- Added tooltip over action buttons (download/copy) on artifact details view.
176+
177+
### Changed
178+
179+
- Improved consistency of GraphQL Query details page with other object views
180+
- Remove "Task Overview" title from embedded task tabs (object that inherit from CoreTaskTarget)
181+
- Simplified default branch view by hiding inapplicable actions and tabs
182+
- Use Jinja2 templates to compute display labels of permission objects, also mark `identifier` as deprecated
183+
184+
### Fixed
185+
186+
- Handle schema updates and associated data migrations as a single item so that an unexpected failure during a schema migration does not leave the schema and data in incompatible states. This applies to loading a schema, merging a branch, and rebasing a branch. ([#6948](https://github.com/opsmill/infrahub/issues/6948))
187+
- Fixed IP addresses disappearing from their parent prefix when the address mask is less specific than the prefix length ([#7267](https://github.com/opsmill/infrahub/issues/7267))
188+
- Fixed missing changelog events for objects created as side effects during node creation, including pool-allocated resources and template-generated child objects. ([#7268](https://github.com/opsmill/infrahub/issues/7268))
189+
- Allow List attributes to use the regex parameter for validating list item values ([#7717](https://github.com/opsmill/infrahub/issues/7717))
190+
- Fixed schema loading crash when a node with `generate_template=True` has a Component relationship to `CoreNumberPool` ([#7903](https://github.com/opsmill/infrahub/issues/7903))
191+
- Prevent creating multiple number pools for the same schema if it is separately loaded on multiple branches. It is now possible to encounter an error if a user tries to create an instance of a schema immediately after an update to include a NumberPool attribute because the associated CoreNumberPool must be created by an asynchronous task. ([#8222](https://github.com/opsmill/infrahub/issues/8222))
192+
- Shift-click range selection now anchors to the last clicked row, with added e2e coverage for range toggling. ([#8229](https://github.com/opsmill/infrahub/issues/8229))
193+
- Fixed display labels showing 'None' for relationship-based fields after upsert.
194+
Relationship peer attributes needed by display label and HFID templates are now correctly loaded during node updates. ([#8237](https://github.com/opsmill/infrahub/issues/8237))
195+
- Fixed error reporting on invalid Jinja2 templates for display_labels ([#8311](https://github.com/opsmill/infrahub/issues/8311))
196+
- Removed `generate_template` on a GenericSchema, this attribute could lead to an invalid GraphQL schema and breaking both frontend and backend operations ([#8371](https://github.com/opsmill/infrahub/issues/8371))
197+
- Fix IPAM view failing to load when more than 40 IP namespaces exist. ([#8481](https://github.com/opsmill/infrahub/issues/8481))
198+
- Fix diff update logic that runs after merge and rebase operations to ignore diffs for merged and deleted branches. Add a new environment variable, "INFRAHUB_DIFF_UPDATE_AFTER_MERGE", that allows skipping the automatic diff updates following a merge. ([#8507](https://github.com/opsmill/infrahub/issues/8507))
199+
- Fixed incorrect merge behavior where removing the source property from an attribute was silently ignored during branch merge. ([#8583](https://github.com/opsmill/infrahub/issues/8583))
200+
- Data tables now display error messages when API requests fail due to permission or other errors.
201+
- Fix false "unsaved changes" warning when editing objects with generic relationships.
202+
- Fix task view showing "Name not found" for related nodes that exist only on a branch by querying the correct branch and time context.
203+
- Fixed adding a relationship from a resource pool within relationship tabs in the object detail view
204+
- Show a user-friendly message in the Files and Artifacts tabs of a proposed change when the source branch has been deleted.
205+
206+
## [Infrahub - v1.7.7](https://github.com/opsmill/infrahub/tree/infrahub-v1.7.7) - 2026-03-12
207+
208+
### Fixed
209+
210+
- Fixed display labels showing 'None' for relationship-based fields after upsert.
211+
Relationship peer attributes needed by display label and HFID templates are now correctly loaded during node updates.
212+
Includes a migration to correct objects that had their display labels and or human-friendly IDs improperly updated to include a null value. ([#8237](https://github.com/opsmill/infrahub/issues/8237))
213+
14214
## [Infrahub - v1.7.6](https://github.com/opsmill/infrahub/tree/infrahub-v1.7.6) - 2026-02-24
15215

16216
### Fixed

backend/infrahub/core/branch/tasks.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,7 @@ async def merge_branch(branch: str, context: InfrahubContext, proposed_change_id
354354
# -------------------------------------------------------------
355355
diff_repository = await component_registry.get_component(DiffRepository, db=db, branch=obj)
356356
await diff_repository.mark_tracking_ids_merged(tracking_ids=[BranchTrackingId(name=obj.name)])
357+
await diff_repository.freeze_diffs_for_branch(branch_name=obj.name)
357358

358359
# -------------------------------------------------------------
359360
# Set branch status to MERGED to make it read-only
@@ -408,6 +409,11 @@ async def delete_branch(branch: str, context: InfrahubContext) -> None:
408409
database = await get_database()
409410
async with database.start_session() as db:
410411
obj = await Branch.get_by_name(db=db, name=str(branch))
412+
413+
component_registry = get_component_registry()
414+
diff_repository = await component_registry.get_component(DiffRepository, db=db, branch=obj)
415+
await diff_repository.freeze_diffs_for_branch(branch_name=branch)
416+
411417
await obj.delete(db=db)
412418

413419
event = BranchDeletedEvent(

backend/infrahub/core/diff/merger/serializer.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -225,8 +225,13 @@ def _serialize_attribute(
225225
property_diff=property_diff, python_value_type=python_type
226226
)
227227
for action, value in actions_and_values:
228-
# we only delete attributes when the whole attribute is deleted
229-
if action is DiffAction.REMOVED and attribute_diff.action is not DiffAction.REMOVED:
228+
# we only delete attribute values when the whole attribute is deleted,
229+
# but other properties can be removed independently
230+
if (
231+
action is DiffAction.REMOVED
232+
and attribute_diff.action is not DiffAction.REMOVED
233+
and property_diff.property_type is DatabaseEdgeType.HAS_VALUE
234+
):
230235
continue
231236
prop_dicts.append(
232237
PropertyMergeDict(
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
from typing import Any
2+
3+
from infrahub.core.diff.model.path import BranchTrackingId, FrozenTrackingId
4+
from infrahub.core.query import Query, QueryType
5+
from infrahub.database import InfrahubDatabase
6+
7+
8+
class EnrichedDiffFreezeByBranchQuery(Query):
9+
"""Freezes DiffRoot nodes and their partners for a given branch.
10+
11+
Sets is_frozen=TRUE and updates tracking_id to 'frozen.{branch_name}'
12+
for all unfrozen DiffRoots with a BranchTrackingId matching the branch name,
13+
as well as their partner DiffRoots.
14+
"""
15+
16+
name = "enriched_diff_freeze_by_branch"
17+
type = QueryType.WRITE
18+
insert_return = False
19+
20+
def __init__(
21+
self,
22+
branch_name: str,
23+
**kwargs: Any,
24+
) -> None:
25+
super().__init__(**kwargs)
26+
self.branch_name = branch_name
27+
28+
async def query_init(self, db: InfrahubDatabase, **kwargs: Any) -> None: # noqa: ARG002
29+
branch_tracking_id = BranchTrackingId(name=self.branch_name)
30+
frozen_tracking_id = FrozenTrackingId(name=self.branch_name)
31+
self.params = {
32+
"branch_tracking_id": branch_tracking_id.serialize(),
33+
"frozen_tracking_id": frozen_tracking_id.serialize(),
34+
}
35+
query = """
36+
MATCH (diff_root:DiffRoot)
37+
WHERE diff_root.tracking_id = $branch_tracking_id
38+
AND (diff_root.is_frozen IS NULL OR diff_root.is_frozen <> TRUE)
39+
OPTIONAL MATCH (diff_root)-[:DIFF_HAS_PARTNER]-(partner:DiffRoot)
40+
SET diff_root.is_frozen = TRUE
41+
SET diff_root.tracking_id = $frozen_tracking_id
42+
SET partner.is_frozen = TRUE
43+
SET partner.tracking_id = $frozen_tracking_id
44+
"""
45+
self.add_to_query(query)

0 commit comments

Comments
 (0)