Skip to content

Add V2 depsolver API support and make it the default (HMS-10029)#2139

Merged
supakeen merged 13 commits intoosbuild:mainfrom
thozza:HMS-9062
Jan 26, 2026
Merged

Add V2 depsolver API support and make it the default (HMS-10029)#2139
supakeen merged 13 commits intoosbuild:mainfrom
thozza:HMS-9062

Conversation

@thozza
Copy link
Member

@thozza thozza commented Jan 16, 2026

Add V2 depsolver API support with complete package metadata, per-transaction results, and RHSM secrets discovery. Make it the default.

Overview

This PR introduces V2 depsolver API bindings and switches the images library to use them by default. The V2 API provides richer package metadata and per-transaction depsolve results, which will enable generating per-transaction RPM osbuild stages in future work. Specifically to resolve Image build failed due to package pre trans scripts issue. The V1 API is retained for CI unit testing to prove behavioral equivalence. All public APIs remain backward compatible—existing clients using the Packages field continue to work unchanged.

Architectural Changes

The V2 handler is more lenient with unknown JSON fields in depsolver responses, reducing maintenance burden when the depsolver adds new fields. A new Transactions field in DepsolveResult exposes per-transaction package lists (disjoint sets), while the existing Packages field is preserved for backward compatibility. The DumpResult and SearchResult structs now include Repos and Solver fields populated by V2 responses.

Key Changes

  • Add v2.go with complete V2 API request/response structures and handler implementation
  • Add Transactions field to DepsolveResult containing per-transaction package lists
  • Add Repos and Solver fields to DumpResult and SearchResult structs
  • Add ClonePtr[T] helper function for safe pointer copying, replacing ToPtr(*ptr) pattern and use it in v2.go
  • Bump minimum osbuild version to 170 (contains V2 API)
  • Switch default handler from V1 to V2

Breaking Changes

This PR is fully backward compatible. The Packages field remains populated and unchanged for all existing callers. V1 API code is retained but only exercised in unit tests.

Testing

  • Comprehensive unit tests for V2 handler covering request generation (depsolve, dump, search) and response parsing
  • Added V2 DepsolveResult assertion helper (assertDepsolveResultV2) that verifies transaction structure, per-transaction package placement, and full metadata parsing
  • V1 tests continue to pass, proving behavioral equivalence between APIs
  • Expanded bash package metadata in test fixtures to enable thorough V2 metadata verification

@thozza thozza force-pushed the HMS-9062 branch 3 times, most recently from 999246d to 528b196 Compare January 19, 2026 09:30
thozza added a commit to thozza/osbuild that referenced this pull request Jan 19, 2026
osbuild/images#2139

Signed-off-by: Tomáš Hozza <thozza@redhat.com>
thozza added a commit to thozza/osbuild that referenced this pull request Jan 19, 2026
osbuild/images#2139

Signed-off-by: Tomáš Hozza <thozza@redhat.com>
@thozza thozza marked this pull request as ready for review January 21, 2026 12:30
@thozza thozza requested a review from a team as a code owner January 21, 2026 12:30
Copy link
Contributor

@lzap lzap left a comment

Choose a reason for hiding this comment

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

Nicely done. Please add the documentation for the common helper.

thozza added 13 commits January 23, 2026 09:08
Modify the unit tests to allow running them against list of apiHandler
implementations. This will allow easily running the same unit tests
against V2 depsolver API, once added.

Signed-off-by: Tomáš Hozza <thozza@redhat.com>
The depsolver results are sorted by "full" NEVRA, so let's add a
convenient method to get it for a Package. The depsolver API
implementations may use it for sorting results. Unit tests will also
leverage this method.

Signed-off-by: Tomáš Hozza <thozza@redhat.com>
Apply repo-specific values (RepoID, RemoteLocations, CheckGPG,
IgnoreSSL) to package templates at assertion time, instead of
duplicating them in each package definition.

This reduces test data duplication and makes the expected package
list easier to maintain.

Signed-off-by: Tomáš Hozza <thozza@redhat.com>
The V2 API will set much more fields in the rpmmd.Package instances
returned in the depsolve result. To keep testing that the currently
used fields are set by any tested API handler, compare only fields set
by V1 API handler.

Refactor the depsolve unit tests to allow specifying depsolve result
assert function specific to the tested apiHandler implementation. This
will allow us to have broader testing for V2 API handler later.

Add assertDepsolveResultV1 which:
- Accepts package sets instead of pre-built expected result. This will
  allow later to check specific Transaction results.
- Builds expected packages internally from actual.Repos. The unified
  depsolve result package set is always the same in all scenarios.
- Compares only "original" V1 API core fields (Name, Epoch, Version,
  Release, Arch, RepoID, Location, RemoteLocations, Checksum,
  CheckGPG, IgnoreSSL).
- Verifies all requested packages are present in the result.

The assertion signature prepares for V2 API transaction checking
without requiring further signature changes.

Signed-off-by: Tomáš Hozza <thozza@redhat.com>
Add a new Transactions field to DepsolveResult that contains a list of
package lists, one per depsolve transaction. Each transaction contains
only the packages unique to that transaction, representing disjoint sets
that should be installed in order.

This new field will be set by V2 depsolver API implementation and later
used to generate rpm stages per transaction results in manifests.

The existing Packages field is kept for backwards compatibility but is
marked for future removal once all clients have been updated to use
Transactions.

Extend unit tests to assert that Transactions value is not set by the
V1 API.

Signed-off-by: Tomáš Hozza <thozza@redhat.com>
Add Repos and Solver fields to DumpResult and SearchResult structs to
match the structure of DepsolveResult. These fields will be populated
by the V2 depsolver API implementation, which returns repository
metadata and solver information in dump and search responses.

The V1 API handler will leave these fields as zero values (empty slice
and empty string), which is safe for existing callers.

Add comments noting that FetchMetadata and SearchMetadata should cache
and expose the full operation result instead of just the packages in
the future.

Signed-off-by: Tomáš Hozza <thozza@redhat.com>
Include full metadata for the bash package (Group, License, SourceRpm,
BuildTime, Provides, Requires, Files, etc.) to enable more
comprehensive V2 API testing later.

Signed-off-by: Tomáš Hozza <thozza@redhat.com>
Add a generic ClonePtr[T] function that creates an independent copy of
a pointer value. Unlike direct pointer assignment which creates aliased
pointers (where modifications to one affect the other), ClonePtr
dereferences the source pointer and returns a pointer to a fresh copy.

The function safely handles nil pointers by returning nil, eliminating
the need for nil checks at call sites.

This complements the existing ToPtr helper. While the pattern
ToPtr(*ptr) achieves the same result, ClonePtr(ptr) is more
self-documenting and makes the intent of creating a deep copy explicit.

Signed-off-by: Tomáš Hozza <thozza@redhat.com>
Replace the ToPtr(*ptr) pattern with the new ClonePtr helper function
for safely copying pointer values. Since ClonePtr handles nil pointers
internally by returning nil, this also removes redundant nil checks at
call sites, resulting in cleaner and more concise code.

Signed-off-by: Tomáš Hozza <thozza@redhat.com>
This ensures that the minimum osbuild version is the one that contains
depsolver V2 API.

Signed-off-by: Tomáš Hozza <thozza@redhat.com>
Add apiHandler interface implementation for the V2 depsolver API.
The V2 provides richer package metadata than V1 and also provides
per-transaction package results.

The V2 API is no longer as strict as V1 implementation and does not fail
on unknown fields in the depsolver reply. This has been a source of a
lot of pain in the past. Although we now have a much nicer and easier
way to iterate on depsolver API changes, introducing a new API version
just to add a new field is probably an overkill and we should not make
this unnecessarily hard.

Populate Repos and Solver fields in DumpResult and SearchResult from
the V2 API response. This provides the API callers with repository
metadata and solver information from dump and search operations.

Add comprehensive unit tests for the V2 handler:

- Extract assertExpectedPackages() as a shared helper between V1 and V2
  assertions to verify packages match expected using V1 core fields and
  that all requested packages are present in the result.

- Add assertDepsolveResultV2() which performs V2-specific checks:
  - Verifies Packages field (for backwards compatibility)
  - Checks full metadata for bash package as a smoke test
  - Verifies transaction count matches the number of package sets
  - Ensures each requested package appears in the correct transaction
  - Validates that the union of all transactions equals expected packages

The V2 handler is not used anywhere yet.

Signed-off-by: Tomáš Hozza <thozza@redhat.com>
Switch the Solver to use the V2 depsolver API by default. The V1 API
implementation is kept around for the sake of being tested in CI via
unit tests and proving that things keep working. V1 will be completely
removed later, since it is not expected to be use going forward.

Signed-off-by: Tomáš Hozza <thozza@redhat.com>
Copy link
Contributor

@lzap lzap left a comment

Choose a reason for hiding this comment

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

I am not fan of this naked ClonePtr for cloning because chances are we miss some fields and then hunting a shared memory bug can be costly. While in Go the manual copying field by field is the standard, there are libraries which are decently fast and can do copying for us, like copier.

Definitely something not for this PR, but this is the first time I see copying at scale in this repo and maybe this could help to create cleaner code.

Anyways, everything is clean, I haven't run the code yet.

@thozza
Copy link
Member Author

thozza commented Jan 23, 2026

Definitely something not for this PR, but this is the first time I see copying at scale in this repo and maybe this could help to create cleaner code.

I agree. Go makes it easy to be lazy with pointers. It’s convenient enough that you often don't think about memory layout, which leads to accidental shared memory and subtle bugs. Using a library to handle deep cloning, rather than implementing it manually for each structure, would definitely be nicer.

Copy link
Member

@supakeen supakeen left a comment

Choose a reason for hiding this comment

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

I have a small question unrelated to the code here but how large do our depsolve results get now, in bytes?

@supakeen supakeen added this pull request to the merge queue Jan 26, 2026
@thozza
Copy link
Member Author

thozza commented Jan 26, 2026

I have a small question unrelated to the code here but how large do our depsolve results get now, in bytes?

I don't have the exact number, I can test it. But the general answer is "considerably larger" due to all the dependencies, provides, files lists, etc... 😬

Merged via the queue into osbuild:main with commit 7b147da Jan 26, 2026
25 checks passed
@thozza thozza deleted the HMS-9062 branch January 26, 2026 09:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants