Skip to content

Conversation

@rh-amarin
Copy link
Contributor

@rh-amarin rh-amarin commented Jan 9, 2026

HYPERFLEET-500 - feat: introduce oapi-codegen

This PR introduces oapi-codegen to generate the go types from openapi.yaml schema instead of the Java openapi-generator tool.

This PR depends on the approval of:

Additionally this PR also addresses HYPERFLEET-501 since building the container image means generating the code within the container.

Summary by CodeRabbit

  • Bug Fixes

    • Improved client initialization with explicit error handling and more robust API response validation and mapping.
  • Chores

    • Switched OpenAPI generation from a container-based flow to a local Go-based codegen; added tooling and environment entries for the codegen.
    • Build/image updates: embed Git version info, pass platform/build args, parameterize base image, add runtime entrypoint/labels, and simplify build stages.
  • Tests

    • Updated tests and mock data to accommodate the new client initialization behavior.
  • Documentation

    • Updated OpenAPI generation docs to reference the new Go-based workflow.

✏️ Tip: You can customize this high-level summary in your review settings.

@openshift-ci
Copy link

openshift-ci bot commented Jan 9, 2026

Skipping CI for Draft Pull Request.
If you want CI signal for your change, please convert it to an actual PR.
You can still manually trigger a test run with /test all

@openshift-ci
Copy link

openshift-ci bot commented Jan 9, 2026

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by:
Once this PR has been reviewed and has the lgtm label, please assign rafabene for approval. For more information see the Code Review Process.

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@coderabbitai
Copy link

coderabbitai bot commented Jan 9, 2026

Walkthrough

This PR replaces the Docker-based OpenAPI generation with a local oapi-codegen v2.5.1 flow (adds .bingo variables, .bingo/oapi-codegen.mod, openapi/oapi-codegen.yaml, and .bingo/variables.env), removes Dockerfile.openapi and its dockerignore, updates Makefile to invoke the local oapi-codegen binary and to propagate GIT_SHA/GIT_DIRTY into image builds, updates go.mod, simplifies Dockerfile to use a parameterized BASE_IMAGE and ENTRYPOINT, and refactors the HyperFleet API client to use openapi.ClientWithResponses with NewHyperFleetClient returning (client, error); call sites and tests are updated accordingly.

Sequence Diagram(s)

sequenceDiagram
    participant Sentinel as cmd/sentinel
    participant HFClient as internal/HyperFleetClient
    participant OpenAPI as openapi.ClientWithResponses
    participant API as HyperFleet API

    Sentinel->>HFClient: NewHyperFleetClient(endpoint, timeout)
    HFClient-->>Sentinel: (client, error)
    Sentinel->>HFClient: fetchClusters(ctx, search)
    HFClient->>OpenAPI: GetClustersWithResponse(params)
    OpenAPI->>API: HTTP GET /clusters
    API-->>OpenAPI: HTTP 200 + JSON200
    OpenAPI-->>HFClient: Response{HTTPResponse, JSON200}
    HFClient->>HFClient: validate status & JSON200, map to []Resource
    HFClient-->>Sentinel: []Resource or APIError
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested labels

lgtm, approved

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly describes the main change: introducing oapi-codegen as the new OpenAPI code generation tool, replacing the Java-based OpenAPI Generator.
Docstring Coverage ✅ Passed Docstring coverage is 96.30% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


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

@rh-amarin
Copy link
Contributor Author

⏺ OpenAPI Code Generation Comparison

Overview

Aspect main/ (OpenAPI Generator) ogen/ oapi-codegen/
Files Generated 34 20 2
Lines of Code ~11,274 ~20,261 ~2,530
Runtime Deps None (stdlib only) ogen-go/ogen, go-faster/jx, OpenTelemetry oapi-codegen/runtime

  1. main/ - OpenAPI Generator (Java-based)

Type Style:

  type Cluster struct {
      CreatedTime time.Time `json:"created_time"`
      Name string `json:"name" validate:"regexp=^[a-z0-9]([-a-z0-9]*[a-z0-9])?$"`
      Spec map[string]interface{} `json:"spec"`
      Labels *map[string]string `json:"labels,omitempty"`  // pointer for optional
      Id *string `json:"id,omitempty"`
  }

Strengths:

  • ✅ No runtime dependencies - uses only stdlib (encoding/json)
  • ✅ Null-safety pattern with NullableCluster wrapper types
  • ✅ Constructor functions (NewCluster, NewClusterWithDefaults)
  • ✅ Validation in UnmarshalJSON - checks required properties
  • ✅ GetXxxOk() methods return tuple (value, bool) for presence checking
  • ✅ HasXxx() methods for optional field presence
  • ✅ ToMap() method for generic map conversion
  • ✅ Mature tooling - widely used, extensive documentation

Weaknesses:

  • ❌ Verbose - each model in separate file with many boilerplate methods
  • ❌ Pointer-based optionals (*string) - less idiomatic for Go
  • ❌ No built-in validation beyond required field checking
  • ❌ Flattens allOf schemas - loses composition structure
  • ❌ Java dependency - requires JVM to run generator

  1. ogen/ (Go-native generator)

Type Style:

  type Cluster struct {
      ID          OptString     `json:"id"`           // Optional type wrapper
      Kind        string        `json:"kind"`
      Labels      OptClusterLabels `json:"labels"`
      Name        string        `json:"name"`
      Spec        ClusterSpec   `json:"spec"`
      Generation  int32         `json:"generation"`
      Status      ClusterStatus `json:"status"`
  }

  type OptString struct {
      Value string
      Set   bool
  }

Strengths:

  • ✅ Opt[T] types for optionals - explicit presence tracking, no nil pointer issues
  • ✅ Built-in validation (oas_validators_gen.go) with structured errors
  • ✅ OpenTelemetry integration - tracing/metrics out of the box
  • ✅ Enum validation with MarshalText/UnmarshalText
  • ✅ High-performance JSON using go-faster/jx (no reflection)
  • ✅ Generated getters/setters for all fields
  • ✅ Pure Go toolchain - no JVM needed
  • ✅ Server + Client generation in same package
  • ✅ Type-safe response types (GetClusterByIdRes interface)

Weaknesses:

  • ❌ Largest output (~20k lines) - more code to maintain
  • ❌ Heavy runtime dependencies - ogen-go/ogen, go-faster/*, OTel
  • ❌ Learning curve - Opt[T] pattern different from idiomatic Go
  • ❌ Less flexibility - opinionated about patterns
  • ❌ Flattens allOf - doesn't preserve schema composition

  1. oapi-codegen/ (Go-native generator)

Type Style:

  type Cluster struct {
      // Preserves allOf composition!
      ClusterBase `yaml:",inline"`

      CreatedBy   openapi_types.Email `json:"created_by"`  // Typed email
      CreatedTime time.Time           `json:"created_time"`
      Generation  int32               `json:"generation"`
      Status      ClusterStatus       `json:"status"`
  }

  type ClusterBase struct {
      APIResource `yaml:",inline"`
      Kind string `json:"kind"`
      Name string `json:"name"`
      Spec ClusterSpec `json:"spec"`
  }

Strengths:

  • ✅ Most compact (~2.5k lines, 2 files) - minimal footprint
  • ✅ Preserves allOf composition - embedded structs match schema
  • ✅ Semantic types - openapi_types.Email instead of string
  • ✅ Lightweight runtime - just oapi-codegen/runtime
  • ✅ Pure Go toolchain - no JVM
  • ✅ ClientWithResponses - parsed response bodies with type safety
  • ✅ RequestEditorFn pattern - clean auth/middleware injection
  • ✅ Go-idiomatic - feels like handwritten Go code

Weaknesses:

  • ❌ No built-in validation - must add manually or use external
  • ❌ Pointer-based optionals (*string) - though less pervasive
  • ❌ Fewer accessor methods - direct field access preferred
  • ❌ Less observability - no OTel integration
  • ❌ Returns *http.Response - need ClientWithResponses for parsed bodies

Comparison Summary

Feature main/ ogen/ oapi-codegen/
Code Size Medium Large Small ✅
Runtime Deps None ✅ Heavy Light
Optional Handling Pointers Opt[T] ✅ Pointers
Validation Basic Full ✅ None
Schema Composition Flattened Flattened Preserved ✅
Observability None OTel ✅ None
Go Idiomaticity Medium Medium High ✅
Type Safety Good Excellent ✅ Good
Maintenance Java needed Go Go

Recommendation

For your use case (types + client only):

  • oapi-codegen is the best fit if you want minimal, Go-idiomatic code that preserves your schema composition (allOf inheritance). The embedded struct pattern (ClusterBase → Cluster) is clean and matches your OpenAPI design.
  • ogen is better if you need built-in validation, observability (OTel), or are building a complete server+client solution. The Opt[T] pattern is cleaner than nil pointers.
  • OpenAPI Generator (main/) is worth keeping if you need maximum compatibility or zero runtime dependencies, though the Java requirement and verbose output are downsides.

@rh-amarin rh-amarin force-pushed the oapi-codegen-avoid-extends branch from 2715e6c to 9f4cc3f Compare January 12, 2026 15:34
@rh-amarin rh-amarin marked this pull request as ready for review January 13, 2026 10:42
@openshift-ci openshift-ci bot requested review from 86254860 and rafabene January 13, 2026 10:42
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In @openapi/README.md:
- Around line 53-56: Replace the bare URL in the README header for the tool so
it’s a proper Markdown link: change the line containing "Tool: OAPI Codegen
https://github.com/oapi-codegen/oapi-codegen" to include a link label (e.g.,
"Tool: OAPI Codegen (https://github.com/oapi-codegen/oapi-codegen)" or "Tool:
[OAPI Codegen](https://github.com/oapi-codegen/oapi-codegen)") so the raw URL is
formatted as a Markdown link; update the README.md entry that mentions OAPI
Codegen accordingly.
🧹 Nitpick comments (5)
cmd/sentinel/main.go (1)

161-166: Proper error handling for the new client constructor.

The error handling correctly logs the error and returns a wrapped error. Minor style note: there's an extraneous empty line (165) before the closing brace.

🧹 Optional: Remove extra blank line
 	hyperfleetClient, err := client.NewHyperFleetClient(cfg.HyperFleetAPI.Endpoint, cfg.HyperFleetAPI.Timeout)
 	if err != nil {
 		log.Errorf(ctx, "Failed to initialize OpenAPI client: %v", err)
 		return fmt.Errorf("failed to initialize OpenAPI client: %w", err)
-
 	}
test/integration/integration_test.go (1)

123-123: Consider handling constructor error instead of discarding it.

Ignoring the error from NewHyperFleetClient could mask test setup failures. While httptest.Server URLs are typically valid, explicitly checking the error improves test reliability and catches regressions if the constructor logic changes.

Suggested fix
-	hyperfleetClient, _ := client.NewHyperFleetClient(server.URL, 10*time.Second)
+	hyperfleetClient, err := client.NewHyperFleetClient(server.URL, 10*time.Second)
+	if err != nil {
+		t.Fatalf("Failed to create HyperFleetClient: %v", err)
+	}

The same pattern applies to Lines 232 and 336.

internal/client/client_test.go (1)

72-72: Consider handling constructor errors in tests.

The error from NewHyperFleetClient is discarded throughout the test file (Lines 72, 107, 128, 158, 203, 241, 262, 285, 314, 327, 344, 396, 573, 612). While unlikely to fail with httptest.Server URLs, handling errors explicitly would improve test reliability.

Example fix pattern
-	client, _ := NewHyperFleetClient(server.URL, 10*time.Second)
+	client, err := NewHyperFleetClient(server.URL, 10*time.Second)
+	if err != nil {
+		t.Fatalf("Failed to create client: %v", err)
+	}
internal/sentinel/sentinel_test.go (1)

92-92: Constructor error handling pattern.

Same optional improvement as noted in other test files - consider handling the error from NewHyperFleetClient explicitly (Lines 92, 159, 203, 250, 300).

internal/client/client.go (1)

246-306: Consider extracting shared resource conversion logic.

The resource conversion logic in fetchClusters (Lines 246-303) and fetchNodePools (Lines 352-409) is nearly identical. Extracting a generic converter could reduce duplication.

Example approach

You could define an interface or use generics to handle the common conversion:

// Example: extract condition conversion
func convertConditions(conditions []openapi.Condition) []Condition {
    if len(conditions) == 0 {
        return nil
    }
    result := make([]Condition, 0, len(conditions))
    for _, cond := range conditions {
        c := Condition{
            Type:               cond.Type,
            Status:             string(cond.Status),
            LastTransitionTime: cond.LastTransitionTime,
        }
        if cond.Reason != nil {
            c.Reason = *cond.Reason
        }
        if cond.Message != nil {
            c.Message = *cond.Message
        }
        result = append(result, c)
    }
    return result
}
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 11092e8 and 9f4cc3f.

⛔ Files ignored due to path filters (2)
  • .bingo/oapi-codegen.sum is excluded by !**/*.sum
  • go.sum is excluded by !**/*.sum
📒 Files selected for processing (14)
  • .bingo/Variables.mk
  • .bingo/oapi-codegen.mod
  • .bingo/variables.env
  • Dockerfile.openapi
  • Dockerfile.openapi.dockerignore
  • Makefile
  • cmd/sentinel/main.go
  • go.mod
  • internal/client/client.go
  • internal/client/client_test.go
  • internal/sentinel/sentinel_test.go
  • openapi/README.md
  • openapi/oapi-codegen.yaml
  • test/integration/integration_test.go
💤 Files with no reviewable changes (2)
  • Dockerfile.openapi.dockerignore
  • Dockerfile.openapi
🧰 Additional context used
🧬 Code graph analysis (4)
cmd/sentinel/main.go (1)
internal/client/client.go (1)
  • NewHyperFleetClient (50-64)
internal/client/client_test.go (1)
internal/client/client.go (1)
  • NewHyperFleetClient (50-64)
test/integration/integration_test.go (1)
internal/client/client.go (1)
  • NewHyperFleetClient (50-64)
internal/sentinel/sentinel_test.go (1)
internal/client/client.go (1)
  • NewHyperFleetClient (50-64)
🪛 markdownlint-cli2 (0.18.1)
openapi/README.md

53-53: Bare URL used

(MD034, no-bare-urls)

🔇 Additional comments (13)
go.mod (1)

9-9: LGTM! Dependencies align with oapi-codegen integration.

The oapi-codegen/runtime direct dependency and go-jsonmerge/v2 indirect dependency are the expected runtime requirements for oapi-codegen generated client code.

Also applies to: 32-32

.bingo/Variables.mk (1)

32-37: LGTM! Build target follows established bingo conventions.

The OAPI_CODEGEN variable and build rule mirror the existing GOLANGCI_LINT pattern, maintaining consistency in the build tooling setup. The cross-compilation environment handling is correctly configured.

.bingo/oapi-codegen.mod (1)

1-5: LGTM! Bingo module correctly configured for oapi-codegen.

The module follows standard bingo conventions for managing build-time tool dependencies. v2.5.1 is the latest stable release of oapi-codegen/v2 (released Nov 1, 2025). The Go version (1.24.0) being lower than the main module (1.25.0) is fine since bingo modules are isolated.

openapi/oapi-codegen.yaml (1)

1-12: LGTM - Configuration aligns with PR objectives.

The configuration correctly generates models and client while disabling server and embedded spec, matching the stated goal of minimal, idiomatic Go output.

test/integration/integration_test.go (1)

58-59: LGTM - Mock data updated to reflect schema email type.

The change to email format aligns with the OpenAPI schema's semantic Email type for created_by and updated_by fields.

internal/client/client_test.go (1)

23-24: LGTM - Mock data updated to email format.

Consistent with the OpenAPI schema's email type for user identifier fields.

internal/sentinel/sentinel_test.go (1)

31-32: LGTM - Mock data updated to email format.

Consistent with other test files and the OpenAPI schema.

Makefile (2)

49-55: LGTM - Clean oapi-codegen workflow.

The generate target correctly uses the bingo-managed oapi-codegen binary with the configuration file. The clean regeneration approach (rm + mkdir) ensures no stale files remain.

Minor style note: .PHONY: generate is typically placed before the target definition, though both orderings work.


44-46: These variables are actively used and should not be removed.

OPENAPI_SPEC_REF and OPENAPI_SPEC_URL are not unused. They are referenced in the Dockerfile (lines 6-13) where they're used to download the OpenAPI spec, and they're documented in README.md and openapi/README.md as user-configurable parameters that can be overridden via command line (e.g., make generate OPENAPI_SPEC_REF=v1.0.0). Removing them would break the Docker build process and eliminate user configuration options.

Likely an incorrect or invalid review comment.

internal/client/client.go (3)

44-64: LGTM - Constructor refactored to return error.

The constructor properly wraps the error from NewClientWithResponses with context. The comment accurately notes that this should only fail for invalid endpoint URLs.


202-243: LGTM - Response handling is robust.

The implementation correctly:

  1. Checks for network/timeout errors first
  2. Validates HTTP status codes before accessing the response body
  3. Guards against nil JSON200 before dereferencing

309-350: LGTM - NodePools fetch follows same robust pattern.

The implementation mirrors fetchClusters with appropriate error handling and nil checks.

.bingo/variables.env (1)

13-13: LGTM - oapi-codegen tool variable added correctly.

The environment variable follows the bingo convention and aligns with the Makefile and Variables.mk changes. Version v2.5.1 is the current release.

@rh-amarin rh-amarin force-pushed the oapi-codegen-avoid-extends branch from 9f4cc3f to 51343e0 Compare January 13, 2026 12:08
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In @openapi/README.md:
- Line 53: Replace the bare URL in the README line that currently reads
"**Tool**: OAPI Codegen https://github.com/oapi-codegen/oapi-codegen" with
proper Markdown link syntax; e.g., make the tool name or the URL a link using
[OAPI Codegen](https://github.com/oapi-codegen/oapi-codegen) so the URL is not
bare and markdownlint MD034 is satisfied.
🧹 Nitpick comments (5)
internal/client/client.go (1)

308-412: Consider extracting common conversion logic to reduce duplication.

fetchNodePools and fetchClusters share nearly identical patterns for error handling, HTTP status checking, and resource conversion. Consider extracting the common logic into helper functions.

💡 Refactor suggestion

You could extract:

  1. A generic HTTP response validator
  2. A common resource conversion function that accepts the item's fields

Example approach:

// validateResponse checks HTTP status and nil body
func validateResponse(httpResp *http.Response, body interface{}) error {
    if httpResp != nil && httpResp.StatusCode >= 400 {
        return &APIError{
            StatusCode: httpResp.StatusCode,
            Message:    fmt.Sprintf("API request failed with status %d", httpResp.StatusCode),
            Retriable:  isHTTPStatusRetriable(httpResp.StatusCode),
        }
    }
    if body == nil {
        return &APIError{
            StatusCode: 0,
            Message:    "received nil response from API",
            Retriable:  false,
        }
    }
    return nil
}

This can be deferred to a follow-up PR since the current implementation is correct.

internal/sentinel/sentinel_test.go (1)

92-92: Consider checking the error return for defensive testing.

While httptest.NewServer provides a valid URL, explicitly checking the error would make tests more robust against future constructor changes.

💡 Suggested pattern
-	hyperfleetClient, _ := client.NewHyperFleetClient(server.URL, 10*time.Second)
+	hyperfleetClient, err := client.NewHyperFleetClient(server.URL, 10*time.Second)
+	if err != nil {
+		t.Fatalf("Failed to create client: %v", err)
+	}

This applies to all test functions in this file (lines 92, 159, 203, 250, 300).

internal/client/client_test.go (1)

72-72: Consider checking constructor errors for defensive testing.

Similar to the sentinel tests, explicitly checking the error return would make tests more robust, especially for the 14 occurrences in this file.

This is a minor improvement that can be addressed in a follow-up if desired. The current approach works because all URLs used are valid.

test/integration/integration_test.go (2)

111-111: Consider checking JSON encoding errors for consistency.

Other test files in this PR check encoding errors with if err := json.NewEncoder(w).Encode(response); err != nil { t.Logf(...) }. Applying the same pattern here would improve consistency.

This applies to lines 111, 118, 227, and 331 in this file.


123-123: Same optional refactor applies here.

Constructor error handling follows the same pattern as unit tests. Consider checking errors for defensive testing consistency.

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9f4cc3f and 51343e0.

⛔ Files ignored due to path filters (2)
  • .bingo/oapi-codegen.sum is excluded by !**/*.sum
  • go.sum is excluded by !**/*.sum
📒 Files selected for processing (14)
  • .bingo/Variables.mk
  • .bingo/oapi-codegen.mod
  • .bingo/variables.env
  • Dockerfile.openapi
  • Dockerfile.openapi.dockerignore
  • Makefile
  • cmd/sentinel/main.go
  • go.mod
  • internal/client/client.go
  • internal/client/client_test.go
  • internal/sentinel/sentinel_test.go
  • openapi/README.md
  • openapi/oapi-codegen.yaml
  • test/integration/integration_test.go
💤 Files with no reviewable changes (2)
  • Dockerfile.openapi.dockerignore
  • Dockerfile.openapi
🚧 Files skipped from review as they are similar to previous changes (7)
  • go.mod
  • cmd/sentinel/main.go
  • openapi/oapi-codegen.yaml
  • .bingo/Variables.mk
  • Makefile
  • .bingo/variables.env
  • .bingo/oapi-codegen.mod
🧰 Additional context used
🧬 Code graph analysis (3)
internal/client/client_test.go (1)
internal/client/client.go (1)
  • NewHyperFleetClient (50-64)
internal/sentinel/sentinel_test.go (1)
internal/client/client.go (1)
  • NewHyperFleetClient (50-64)
test/integration/integration_test.go (1)
internal/client/client.go (1)
  • NewHyperFleetClient (50-64)
🪛 markdownlint-cli2 (0.18.1)
openapi/README.md

53-53: Bare URL used

(MD034, no-bare-urls)

🔇 Additional comments (6)
openapi/README.md (1)

56-56: LGTM!

Documentation accurately reflects the switch to oapi-codegen.

internal/client/client.go (2)

44-64: LGTM!

The constructor signature change to return (*HyperFleetClient, error) properly handles the case where the endpoint URL is invalid. The error handling is appropriate for this use case.


201-306: LGTM!

The fetchClusters implementation properly handles:

  • Optional search parameter via pointer
  • Network and timeout errors with appropriate retriability
  • HTTP status codes with proper error classification
  • Nil response body detection
  • Nil-pointer-safe extraction for optional fields (Id, Href, Kind)
  • Condition conversion with optional field handling
internal/sentinel/sentinel_test.go (1)

31-32: LGTM!

Mock data updated to use email format for created_by and updated_by fields, aligning with the updated API schema expectations.

internal/client/client_test.go (1)

23-24: LGTM!

Mock data consistently updated to use email format for created_by and updated_by fields.

test/integration/integration_test.go (1)

58-59: LGTM!

Mock data consistently updated to use email format for user identification fields.

@rh-amarin
Copy link
Contributor Author

/retest

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
Makefile (1)

44-53: The generate target is broken and will fail: it references openapi/openapi.yaml without downloading it first.

The openapi/README.md documents that the spec file should be "automatically downloaded during make generate" from OPENAPI_SPEC_URL, but the Makefile implementation at lines 44-53 does not perform this download. The target directly passes a non-existent file to oapi-codegen, and OPENAPI_SPEC_URL is defined but never used.

Add a download step in the generate target before calling oapi-codegen:

generate: $(OAPI_CODEGEN) 
	curl -sSL $(OPENAPI_SPEC_URL) -o openapi/openapi.yaml
	rm -rf pkg/api/openapi
	mkdir -p pkg/api/openapi
	$(OAPI_CODEGEN) --config openapi/oapi-codegen.yaml openapi/openapi.yaml

Or use wget if curl is unavailable.

🧹 Nitpick comments (1)
Makefile (1)

49-54: LGTM — clean migration to oapi-codegen.

The target correctly depends on the bingo-managed tool, clears the output directory, and invokes the generator with the config file.

Minor nit: there's a trailing space on line 50 after $(OAPI_CODEGEN).

🧹 Optional: remove trailing space
 # Regenerate openapi types using oapi-codegen
-generate: $(OAPI_CODEGEN) 
+generate: $(OAPI_CODEGEN)
 	rm -rf pkg/api/openapi
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 51343e0 and 8801831.

📒 Files selected for processing (1)
  • Makefile

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

@rh-amarin rh-amarin marked this pull request as draft January 14, 2026 12:42
@rh-amarin rh-amarin marked this pull request as ready for review January 14, 2026 14:49
@openshift-ci openshift-ci bot requested a review from ciaranRoche January 14, 2026 14:49
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (2)
Makefile (2)

49-60: Trailing whitespace on line 51 may cause issues.

There's trailing whitespace after $(OAPI_CODEGEN) which can cause subtle Make parsing issues.

Also, consider adding error handling for the rm -rf and mkdir -p commands to be consistent with the curl error handling pattern used below.

Proposed fix
-generate: $(OAPI_CODEGEN) 
+generate: $(OAPI_CODEGEN)
 	`@echo` "Fetching OpenAPI spec from hyperfleet-api (ref: $(OPENAPI_SPEC_REF))..."
 	`@mkdir` -p openapi
 	`@curl` -sSL -o openapi/openapi.yaml "$(OPENAPI_SPEC_URL)" || \
 		(echo "Failed to download OpenAPI spec from $(OPENAPI_SPEC_URL)" && exit 1)
 	`@echo` "OpenAPI spec downloaded successfully"
-	rm -rf pkg/api/openapi
-	mkdir -p pkg/api/openapi
+	`@rm` -rf pkg/api/openapi
+	`@mkdir` -p pkg/api/openapi
 	$(OAPI_CODEGEN) --config openapi/oapi-codegen.yaml openapi/openapi.yaml

156-161: Inconsistent indentation in container build commands.

The indentation mixes tabs and spaces inconsistently across the image and image-dev targets. Line 158 uses spaces+tab, while line 186 uses spaces. Makefiles require tabs for recipe lines.

Proposed fix for `image` target
 .PHONY: image
 image: ## Build container image with configurable registry/tag
 	`@echo` "Building image $(IMAGE_REGISTRY)/$(IMAGE_NAME):$(IMAGE_TAG) ..."
 	$(CONTAINER_TOOL) build \
-  	--platform linux/amd64 \
+		--platform linux/amd64 \
 		--build-arg GIT_SHA=$(GIT_SHA) \
 		--build-arg GIT_DIRTY=$(GIT_DIRTY) \
 		-t $(IMAGE_REGISTRY)/$(IMAGE_NAME):$(IMAGE_TAG) .
 	`@echo` "Image built: $(IMAGE_REGISTRY)/$(IMAGE_NAME):$(IMAGE_TAG)"
Proposed fix for `image-dev` target
 	`@echo` "Building dev image quay.io/$(QUAY_USER)/$(IMAGE_NAME):$(DEV_TAG) ..."
 	$(CONTAINER_TOOL) build \
 		--platform linux/amd64 \
 		--build-arg BASE_IMAGE=alpine:3.21 \
 		--build-arg GIT_SHA=$(GIT_SHA) \
 		--build-arg GIT_DIRTY=$(GIT_DIRTY) \
-    -t quay.io/$(QUAY_USER)/$(IMAGE_NAME):$(DEV_TAG) .
+		-t quay.io/$(QUAY_USER)/$(IMAGE_NAME):$(DEV_TAG) .

Also applies to: 180-186

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 729f063 and 54bc4b6.

📒 Files selected for processing (2)
  • Dockerfile
  • Makefile
🧰 Additional context used
🪛 checkmake (0.2.2)
Makefile

[warning] 17-17: Target "VERSION" should be declared PHONY.

(phonydeclared)


[warning] 51-51: Target body for "generate" exceeds allowed length of 5 (8).

(maxbodylength)

🔇 Additional comments (4)
Dockerfile (2)

1-1: LGTM on the BASE_IMAGE parameterization.

The pattern of using ARG BASE_IMAGE with a sensible default (distroless) and allowing override for dev builds (alpine) is clean and flexible. The entrypoint and CMD separation is appropriate.

Also applies to: 21-21, 31-32


3-3: No action needed. Go 1.25 is the current stable version (released August 2025, with patch 1.25.5 available as of December 2025) and will build successfully. Using golang:1.25 as the base image is correct and requires no changes.

Likely an incorrect or invalid review comment.

Makefile (2)

15-17: LGTM on Git-based versioning.

The version composition from GIT_SHA and GIT_DIRTY is clean and provides useful build traceability.


183-183: Alpine 3.21 is currently available and actively maintained. Docker Hub provides the alpine:3.21 image with the latest patch version being 3.21.5. No action required.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

@rh-amarin rh-amarin force-pushed the oapi-codegen-avoid-extends branch from 54bc4b6 to 055ad22 Compare January 14, 2026 15:22
@rafabene
Copy link
Contributor

Although it's a pre-existing issue, test should also call generate just like build does.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@Makefile`:
- Line 16: GIT_DIRTY currently uses "git diff --quiet" which only catches
unstaged changes; update the GIT_DIRTY assignment so it checks both staged and
unstaged changes (for example run both a staged check like "git diff --cached
--quiet" and an unstaged check, or use "git diff-index --quiet HEAD --") and
emit "-modified" if either check indicates changes; replace the existing
GIT_DIRTY shell invocation with a compound command that returns "-modified" when
staged or unstaged diffs exist while preserving the existing fallback behavior.
🧹 Nitpick comments (2)
Makefile (2)

51-60: Consider adding the config file as a prerequisite.

The generate target doesn't depend on openapi/oapi-codegen.yaml. If the config changes (e.g., output paths, type mappings), make generate won't automatically detect it needs to re-run.

Proposed fix
-generate: $(OAPI_CODEGEN)
+generate: $(OAPI_CODEGEN) openapi/oapi-codegen.yaml

156-161: Minor indentation inconsistency.

The multi-line build command has inconsistent indentation (line 158 appears to mix tabs and spaces). This is cosmetic but can cause issues with some Make implementations.

Suggested consistent formatting
 .PHONY: image
 image: ## Build container image with configurable registry/tag
 	`@echo` "Building image $(IMAGE_REGISTRY)/$(IMAGE_NAME):$(IMAGE_TAG) ..."
 	$(CONTAINER_TOOL) build \
-  	--platform linux/amd64 \
+		--platform linux/amd64 \
 		--build-arg GIT_SHA=$(GIT_SHA) \
 		--build-arg GIT_DIRTY=$(GIT_DIRTY) \
 		-t $(IMAGE_REGISTRY)/$(IMAGE_NAME):$(IMAGE_TAG) .
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 055ad22 and f8f3faa.

📒 Files selected for processing (1)
  • Makefile
🧰 Additional context used
🪛 checkmake (0.2.2)
Makefile

[warning] 17-17: Target "VERSION" should be declared PHONY.

(phonydeclared)


[warning] 51-51: Target body for "generate" exceeds allowed length of 5 (8).

(maxbodylength)

🔇 Additional comments (2)
Makefile (2)

85-98: LGTM!

The test targets now correctly depend on generate, ensuring generated code is up-to-date before tests run. This aligns with the architecture standards mentioned in previous reviews.


180-186: LGTM with minor formatting note.

The dev image build correctly passes all necessary build-args. Same indentation inconsistency as the image target (line 186 uses spaces instead of a tab before -t).

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

@rafabene rafabene merged commit df7a527 into openshift-hyperfleet:main Jan 14, 2026
7 of 8 checks passed
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