Skip to content

fix: Clean up nolint directives marked as TODO - Part 6#910

Open
cbumb wants to merge 7 commits intoNVIDIA:mainfrom
cbumb:728_nolint-cleanup-6
Open

fix: Clean up nolint directives marked as TODO - Part 6#910
cbumb wants to merge 7 commits intoNVIDIA:mainfrom
cbumb:728_nolint-cleanup-6

Conversation

@cbumb
Copy link
Contributor

@cbumb cbumb commented Feb 25, 2026

Summary

Refactors nolint directives by lowering complexity and improving structure. No intended behavior change.

Modules updated in this PR:
store-client
janitor-provider

Type of Change

  • 🐛 Bug fix
  • ✨ New feature
  • 💥 Breaking change
  • 📚 Documentation
  • 🔧 Refactoring
  • 🔨 Build/CI

Component(s) Affected

  • Core Services
  • Documentation/CI
  • Fault Management
  • Health Monitors
  • Janitor
  • Other: ____________

Testing

  • Tests pass locally
  • Manual testing completed
  • No breaking changes (or documented)

Checklist

  • Self-review completed
  • Documentation updated (if needed)
  • Ready for review

Summary by CodeRabbit

  • Refactor

    • Centralized setup and helpers across cloud instance, container, and datastore flows for clearer, more consistent behavior.
    • Simplified change-stream, changelog scanning, and event processing paths for more reliable data handling.
  • Bug Fixes

    • More reliable container deletion verification and safer instance operation sequencing to reduce transient failures.
    • Improved error wrapping and recovery to surface clearer failure context.
  • Chores

    • Simplified database connection assembly, stricter environment-variable validation, and minor logging/config improvements.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 25, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds internal helper functions and refactors across janitor-provider and store-client: GCP instance client setup, Kind container deletion, Postgres connection building, event processing, changelog parsing, env loading, Mongo ping validation, PostgreSQL query utilities, and struct-unmarshaller pointer handling; expands one unmarshaller signature.

Changes

Cohort / File(s) Summary
GCP CSP Helpers
janitor-provider/pkg/csp/gcp/gcp.go
Added prepareInstanceOp(ctx, node) to centralize HTTP + Instances client creation and node-field derivation; refactored SendRebootSignal and SendTerminateSignal to use it and simplified error wrapping and client close handling.
Kind CSP Container Management
janitor-provider/pkg/csp/kind/kind.go
Extracted container deletion/verification into deleteAndVerifyContainer(ctx, dockerCtx, containerName); SendTerminateSignal delegates deletion and treats missing containers as noop, with added logging and propagated errors.
Postgres connection builder
store-client/pkg/adapter/legacy_adapter.go
Rewrote PostgreSQL connection-string assembly to build a filtered list of key=value pairs and join via strings.Join; added formatPort helper and removed manual concatenation.
Event processing & error handling
store-client/pkg/client/event_processor.go
Centralized error handling with handleProcessingError and markProcessed; per-event resume tokens used and main processing flow refactored to delegate marking and error paths to helpers.
Postgres changelog processing
store-client/pkg/client/postgresql_changestream.go
Added scanChangelogEntry, extractNodeNameFromValues and op-type/value helpers; refactored fetch/scan/emission flow and simplified pipeline/filter matching and value extraction.
Env loading helpers
store-client/pkg/config/env_loader.go
Introduced getRequiredEnv and getEnvWithDefault; replaced direct os.Getenv use with helpers, improving required-var error propagation and defaults handling.
MongoDB ping validation
store-client/pkg/datastore/providers/mongodb/watcher/watch_store.go
Extracted validatePingConfig(mongoConfig) to centralize ping timeout/interval validations; removed inline validation logic.
Postgres DB utilities & filters
store-client/pkg/datastore/providers/postgresql/database_client.go
Added resolveFilterMapForFind, isDescending, knownColumnMappings, resolveSetFields, and syncDenormalizedColumns; refactored filter/sort translation, update SET building, and argument merging (uses slices.Concat).
Struct copying / unmarshaller
store-client/pkg/storewatcher/unmarshaller.go
Refactored pointer/struct copying with copyPtrField and switch-based dispatch in CopyStructFields; changed UnmarshalFullDocumentToJsonTaggedStructFromEvent signature to add bsonTaggedType parameter.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

🐇 I nudged some helpers into neat little rows,
Closed clients, moved tokens, and trimmed the old prose.
Containers hopped out, envs found their light,
Fields copied gently, changelogs now bright.
🥕✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 38.10% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title accurately describes the main objective: cleaning up nolint directives marked as TODO in Part 6 of a series, which aligns with the extensive refactoring across multiple files to reduce complexity and remove duplicate nolint comments.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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

Copy link
Contributor

@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: 9

🧹 Nitpick comments (1)
store-client/pkg/datastore/providers/mongodb/watcher/watch_store.go (1)

196-210: Good extraction—now reuse this helper in GetCollectionClient to remove remaining duplication.

The same three ping checks are still duplicated later, which can drift from this canonical validator.

♻️ Proposed follow-up refactor
 func GetCollectionClient(
 	ctx context.Context,
 	mongoConfig MongoDBConfig,
 ) (*mongo.Collection, error) {
+	if err := validatePingConfig(mongoConfig); err != nil {
+		return nil, err
+	}
+
 	clientOpts, err := constructMongoClientOptions(mongoConfig)
 	if err != nil {
 		return nil, fmt.Errorf("error creating mongoDB clientOpts: %w", err)
 	}
@@
-	if mongoConfig.TotalPingTimeoutSeconds <= 0 {
-		return nil, fmt.Errorf("invalid ping timeout value, value must be a positive integer")
-	}
-
-	if mongoConfig.TotalPingIntervalSeconds <= 0 {
-		return nil, fmt.Errorf("invalid ping interval value, value must be a positive integer")
-	}
-
-	if mongoConfig.TotalPingIntervalSeconds >= mongoConfig.TotalPingTimeoutSeconds {
-		return nil, fmt.Errorf("invalid ping interval value, value must be less than ping timeout")
-	}
-
 	totalTimeout := time.Duration(mongoConfig.TotalPingTimeoutSeconds) * time.Second
 	interval := time.Duration(mongoConfig.TotalPingIntervalSeconds) * time.Second
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@store-client/pkg/datastore/providers/mongodb/watcher/watch_store.go` around
lines 196 - 210, The three ping-parameter checks duplicated in
GetCollectionClient should be replaced by a single call to the extracted helper
validatePingConfig(MongoDBConfig) and its error handled; locate the duplicated
logic inside GetCollectionClient and remove the individual if-checks for
TotalPingTimeoutSeconds and TotalPingIntervalSeconds, call
validatePingConfig(config) instead, and return or propagate the returned error
(preserving the existing error flow) so validation is centralized in the
validatePingConfig function.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@janitor-provider/pkg/csp/gcp/gcp.go`:
- Around line 209-226: The three error returns in prepareInstanceOp flow
currently propagate raw errors from getAuthenticatedHTTPClient,
compute.NewInstancesRESTClient, and getNodeFields; update each return to wrap
the original error with context using fmt.Errorf, e.g. replace returns like
"return nil, nil, err" with wrapped errors such as fmt.Errorf("failed to create
authenticated HTTP client: %w", err), fmt.Errorf("failed to create instances
client: %w", err), and fmt.Errorf("failed to get node fields for node %q: %w",
node.Name, err); ensure you still close instancesClient on getNodeFields errors
(keep instancesClient.Close and its logged cerr handling) and update all three
call sites in prepareInstanceOp accordingly.

In `@janitor-provider/pkg/csp/kind/kind.go`:
- Around line 110-114: Replace the substring check using strings.Contains on
output with an exact-name match against containerName: instead of checking if
output contains containerName, run a line-oriented exact-match (or regex
anchored with start/end) against the output so only the exact container name
matches (consistent with the existing pattern used elsewhere like name=^%s$).
Update the block that currently examines output and returns
model.TerminateNodeRequestRef("") to use this exact-match logic (referencing the
variables output and containerName) so false positives like "node-10" matching
"node-1" are avoided.

In `@store-client/pkg/client/event_processor.go`:
- Around line 223-231: markProcessed currently calls
changeStreamWatcher.MarkProcessed with an empty token, which drops the resume
token; change markProcessed to accept the event (or its resume token) and pass
the real token to changeStreamWatcher.MarkProcessed instead of []byte{} (e.g.,
func (p *DefaultEventProcessor) markProcessed(ctx context.Context, evt *Event)
error or markProcessed(ctx context.Context, token []byte) error), and update
call sites in handleSingleEvent and handleProcessingError to pass the event (or
event.ResumeToken) through so the watcher receives the correct resume token.

In `@store-client/pkg/client/postgresql_changestream.go`:
- Around line 401-403: The current check skips $match when entry.newValues is
nil (e.g., delete events), letting events match incorrectly; update the
conditional around w.matchesFilters so that when entry.newValues is nil you
still evaluate matchMap against the available row data (e.g., entry.oldValues)
or otherwise call w.matchesFilters with a non-nil map, and ensure matchesFilters
handles nil safely; specifically change the block that references
entry.newValues and w.matchesFilters(matchMap, entry.newValues) to fall back to
entry.oldValues (or a merged values map) so non-operationType predicates are
still evaluated.
- Around line 459-466: extractValue currently returns nil, which breaks
field-based pipeline matching in matchesFilters; implement dot-notation
traversal in extractValue to walk nested maps and slices using path segments
(split on '.'), interpreting numeric segments as array indices when the current
value is a []interface{}, using type assertions on map[string]interface{} for
object keys, returning nil if any segment is missing or index out of range, and
returning the final resolved value (or the original value if path is empty);
also remove/replace the TODO with a proper issue reference. Use the function
name extractValue and callers like matchesFilters to locate where this behavior
is required.

In `@store-client/pkg/config/env_loader.go`:
- Around line 193-201: The code returns raw errors from getRequiredEnv (e.g.,
when obtaining connectionURI and databaseName and at the other occurrences
flagged) which loses caller context; change each "return ..., err" that
propagates getRequiredEnv errors to wrap the error with fmt.Errorf including a
short caller context (for example: fmt.Errorf("load env <ENV_NAME>: %w", err)),
and ensure fmt is imported if not already; update all instances referenced (the
getRequiredEnv calls for connectionURI, databaseName and the other occurrences
in env_loader.go) to use this wrapping pattern.

In `@store-client/pkg/datastore/providers/mongodb/watcher/watch_store.go`:
- Around line 117-118: The code validates the Mongo config after calling
mongo.Connect which can leak a connected client on validation failure; move the
validatePingConfig(mongoConfig) call to before creating/connecting the client
(the mongo.Connect/mongo.NewClient sequence) or, if keeping connect-first,
ensure any early return after validatePingConfig calls client.Disconnect(ctx) to
clean up; specifically update the function that constructs the client (the code
invoking mongo.Connect and validatePingConfig) so validation occurs prior to
mongo.Connect or add a defer/explicit client.Disconnect(ctx) on validation error
to avoid leaking the Mongo client.

In `@store-client/pkg/datastore/providers/postgresql/database_client.go`:
- Around line 941-953: The code currently treats a nil filterMap (resulting from
convertFilterToMap when encountering unsupported filter types) as an explicit
"no filter" and returns TRUE; change this so only an explicit nil filter value
yields trueString, while a nil produced by convertFilterToMap for unsupported
filter types returns a descriptive error instead. Also, after calling
filterMapToConditions, wrap any returned error with context (e.g., using
fmt.Errorf("filterMapToConditions for table %s: %w", c.tableName, err)) so the
caller gets actionable information; ensure this logic lives alongside the
maintenanceEventTableName handling and transformFilterMapForMaintenanceEvents
call.

In `@store-client/pkg/storewatcher/unmarshaller.go`:
- Around line 97-109: CopyStructFields currently assumes pointer targets are
struct pointers and that same Kind implies assignability, which causes reflect
panics; update the logic in CopyStructFields to (1) when handling
dstField.Kind() == reflect.Ptr only treat it as a struct pointer if
dstField.Elem().Kind() == reflect.Struct and srcField.Kind()==reflect.Ptr and
srcField.Elem().Kind()==reflect.Struct before calling CopyStructFields on
Elem(); (2) for non-struct pointers (e.g., *string, *int) handle by allocating a
new element with reflect.New(dstField.Type().Elem()), and copy/convert the src
value into dstField.Elem() only if types are assignable or convertible (use
Type().AssignableTo/ConvertibleTo checks); (3) when dstField.Kind() ==
reflect.Struct ensure srcField.Kind() == reflect.Struct before recursing; and
(4) before dstField.Set(srcField) verify
srcField.Type().AssignableTo(dstField.Type()) (or perform a safe conversion) and
that dstField.CanSet()/srcField.IsValid() to avoid Set panics.

---

Nitpick comments:
In `@store-client/pkg/datastore/providers/mongodb/watcher/watch_store.go`:
- Around line 196-210: The three ping-parameter checks duplicated in
GetCollectionClient should be replaced by a single call to the extracted helper
validatePingConfig(MongoDBConfig) and its error handled; locate the duplicated
logic inside GetCollectionClient and remove the individual if-checks for
TotalPingTimeoutSeconds and TotalPingIntervalSeconds, call
validatePingConfig(config) instead, and return or propagate the returned error
(preserving the existing error flow) so validation is centralized in the
validatePingConfig function.

ℹ️ Review info

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d9c0abe and 0a10453.

📒 Files selected for processing (9)
  • janitor-provider/pkg/csp/gcp/gcp.go
  • janitor-provider/pkg/csp/kind/kind.go
  • store-client/pkg/adapter/legacy_adapter.go
  • store-client/pkg/client/event_processor.go
  • store-client/pkg/client/postgresql_changestream.go
  • store-client/pkg/config/env_loader.go
  • store-client/pkg/datastore/providers/mongodb/watcher/watch_store.go
  • store-client/pkg/datastore/providers/postgresql/database_client.go
  • store-client/pkg/storewatcher/unmarshaller.go

Copy link
Contributor

@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.

Caution

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

⚠️ Outside diff range comments (5)
janitor-provider/pkg/csp/gcp/gcp.go (1)

128-131: ⚠️ Potential issue | 🟡 Minor

Unwrapped errors from Reset and Delete violate the error-wrapping guideline.

Both instancesClient.Reset (line 130) and instancesClient.Delete (line 200) return raw errors, making it hard for callers to know which operation produced the failure. While these lines are pre-existing, they are part of the same error-propagation chain that was just refactored.

♻️ Proposed fix
 	op, err := instancesClient.Reset(ctx, resetReq)
 	if err != nil {
-		return "", err
+		return "", fmt.Errorf("failed to reset instance %q: %w", nodeFields.instance, err)
 	}
 	op, err := instancesClient.Delete(ctx, deleteReq)
 	if err != nil {
-		return "", err
+		return "", fmt.Errorf("failed to delete instance %q: %w", nodeFields.instance, err)
 	}

As per coding guidelines: "Wrap errors with context using fmt.Errorf("context: %w", err) in Go code".

Also applies to: 198-201

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@janitor-provider/pkg/csp/gcp/gcp.go` around lines 128 - 131, Wrap the raw
errors returned from instancesClient.Reset and instancesClient.Delete with
contextual messages using fmt.Errorf so callers can identify which GCP operation
failed; for the Reset call (instancesClient.Reset(ctx, resetReq)) change the
return to wrap err (e.g. fmt.Errorf("reset instance %s: %w", instanceID, err))
and for the Delete call (instancesClient.Delete(ctx, deleteReq)) similarly wrap
the error (e.g. fmt.Errorf("delete instance %s: %w", instanceID, err)), ensuring
you import fmt if not already present and preserve the original error via %w.
store-client/pkg/client/postgresql_changestream.go (1)

422-431: ⚠️ Potential issue | 🟠 Major

$in filter only evaluates the first element — multi-operation filters silently broken.

mapOperationType returns the mapping of arr[0] only. For a pipeline filter like {"$in": ["insert", "update"]}, expectedOp becomes "INSERT", and any UPDATE event is rejected with entry.operation != expectedOp. Since the PR claims no behaviour changes, this is a regression introduced by extracting mapOperationType.

🐛 Proposed fix
 	case map[string]interface{}:
 		// Handle {"$in": ["insert", "update"]} style filters
 		if inArray, ok := v["$in"]; ok {
 			if arr, ok := inArray.([]interface{}); ok && len(arr) > 0 {
-				// For simplicity, just check the first operation
-				if op, ok := arr[0].(string); ok {
-					return w.mapOperationType(op)
+				// Return empty string; callers must check each element.
+				// Signal match by returning a sentinel or refactor caller.
 				}
 			}
 		}

A cleaner approach is to change mapOperationType to return []string and update matchesPipeline to check entry.operation against all mapped values:

// mapOperationType maps one or more MongoDB operationType values to PostgreSQL.
func (w *PostgreSQLChangeStreamWatcher) mapOperationType(opType interface{}) []string {
    switch v := opType.(type) {
    case string:
        mapped := w.mapSingleOpType(v)
        if mapped != "" {
            return []string{mapped}
        }
    case map[string]interface{}:
        if inArray, ok := v["$in"]; ok {
            if arr, ok := inArray.([]interface{}); ok {
                var ops []string
                for _, elem := range arr {
                    if s, ok := elem.(string); ok {
                        if mapped := w.mapSingleOpType(s); mapped != "" {
                            ops = append(ops, mapped)
                        }
                    }
                }
                return ops
            }
        }
    }
    return nil
}

Then in matchesPipeline:

-        expectedOp := w.mapOperationType(opType)
-        if expectedOp != "" && entry.operation != expectedOp {
-            return false
-        }
+        expectedOps := w.mapOperationType(opType)
+        if len(expectedOps) > 0 && !slices.Contains(expectedOps, entry.operation) {
+            return false
+        }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@store-client/pkg/client/postgresql_changestream.go` around lines 422 - 431,
The mapOperationType currently maps only the first element of an "$in" array,
causing multi-operation filters to drop events; change
PostgreSQLChangeStreamWatcher.mapOperationType to return a slice of strings
([]string) by handling string inputs (map to single-item slice via
mapSingleOpType) and by iterating over map["$in"] arrays to map each element
(skipping non-strings or unmapped values), then update matchesPipeline to treat
the returned value as a list and accept the entry when entry.operation equals
any of the mapped strings (instead of comparing only to a single expectedOp).
store-client/pkg/client/event_processor.go (1)

152-179: ⚠️ Potential issue | 🟡 Minor

Unmarshal/document-ID error paths ignore MarkProcessedOnError, always marking as processed.

Both error branches (unmarshal at Line 163, document-ID at Line 174) call markProcessed unconditionally, bypassing config.MarkProcessedOnError. Only handler errors go through handleProcessingError which respects that flag. A caller who configures MarkProcessedOnError: false to "preserve events for retry on next restart" would expect that contract to hold for parse failures too — instead, malformed events are silently skipped even with the default config.

If the intent is that parse failures are unrecoverable and should always be skipped, that decision should be documented in the code and in EventProcessorConfig.MarkProcessedOnError's godoc.

📝 Suggested doc clarification
-	// MarkProcessedOnError determines whether to mark events as processed even if handler returns error
-	// Set to false (default) to preserve event for retry on next restart
-	// Set to true to skip failed events and continue (use with caution - may lose events)
+	// MarkProcessedOnError determines whether to mark events as processed when the event
+	// HANDLER returns an error. Set to false (default) to preserve the event for retry on
+	// next restart. Set to true to skip failed events and continue processing
+	// (use with caution - may lose events).
+	// Note: parse-level failures (unmarshal errors, missing document ID) always mark
+	// the event as processed regardless of this flag, as they are considered unrecoverable.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@store-client/pkg/client/event_processor.go` around lines 152 - 179, The
unmarshal and GetDocumentID error paths in
DefaultEventProcessor.handleSingleEvent currently always call markProcessed,
ignoring EventProcessorConfig.MarkProcessedOnError; update those branches to
respect the config by only calling p.markProcessed(ctx, token) when
p.config.MarkProcessedOnError is true, otherwise route the error through
p.handleProcessingError(ctx, token, err, eventID?) (or an appropriate wrapper
error) so the error-handling logic that respects MarkProcessedOnError is used;
alternatively, if parse failures are intended to be always skipped, add a clear
comment/godoc on EventProcessorConfig.MarkProcessedOnError and on
handleSingleEvent stating parse errors are unrecoverable. Ensure references to
p.markProcessed, p.handleProcessingError,
DefaultEventProcessor.handleSingleEvent and
EventProcessorConfig.MarkProcessedOnError are used to locate and change the
code.
store-client/pkg/datastore/providers/postgresql/database_client.go (2)

840-892: ⚠️ Potential issue | 🟠 Major

FindOne skips transformFilterMapForMaintenanceEvents, creating asymmetry with Find.

Find delegates to resolveFilterMapForFind (Line 910), which applies transformFilterMapForMaintenanceEvents for the maintenance_events table — converting camelCase filter keys (e.g. scheduledStartTime) to the indexed snake_case columns (e.g. scheduled_start_time). FindOne still uses the inline path (Lines 850–865) and never applies that transformation.

For the maintenance_events table this means FindOne queries miss indexed columns and may return incorrect results if the filter key doesn't exist in the JSONB document under the camelCase name.

🐛 Proposed fix — align `FindOne` with `Find`
 func (c *PostgreSQLDatabaseClient) FindOne(
 	ctx context.Context, filter interface{}, options *client.FindOneOptions,
 ) (client.SingleResult, error) {
 	var whereClause string
 	var args []interface{}

 	if builder, ok := filter.(*query.Builder); ok {
 		whereClause, args = builder.ToSQL()
-	} else if filterMap != nil {
-		conditions, err := c.filterMapToConditions(filterMap)
-		if err != nil {
-			return nil, err
-		}
-		whereClause, args = conditionsToWhereClause(conditions)
-	} else {
-		slog.Error("Unsupported filter type", "filterType", fmt.Sprintf("%T", filter))
-		return nil, fmt.Errorf("unsupported filter type")
+	} else {
+		var err error
+		whereClause, args, err = c.resolveFilterMapForFind(filter)
+		if err != nil {
+			return nil, err
+		}
 	}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@store-client/pkg/datastore/providers/postgresql/database_client.go` around
lines 840 - 892, FindOne currently converts the filter inline (via
convertFilterToMap) and builds conditions directly, skipping the same
maintenance-events key transformation used by Find; update FindOne to reuse
resolveFilterMapForFind (the same helper used by Find) to obtain the transformed
filter map (which in turn calls transformFilterMapForMaintenanceEvents for the
maintenance_events table) before calling
filterMapToConditions/conditionsToWhereClause, so camelCase keys like
scheduledStartTime are converted to the indexed snake_case columns; ensure the
code path still handles query.Builder inputs the same way and preserves existing
error handling and SQL construction.

472-524: ⚠️ Potential issue | 🟡 Minor

Wrap errors from convertUpdateToSetClause and convertFilterToWhereClause with context.

Lines 479 and 487 return errors unwrapped, violating the fmt.Errorf("context: %w", err) guideline and making stack-level attribution harder.

📝 Proposed fix
-	setClause, updateArgs, err := c.convertUpdateToSetClause(update)
-	if err != nil {
-		return nil, err
-	}
+	setClause, updateArgs, err := c.convertUpdateToSetClause(update)
+	if err != nil {
+		return nil, fmt.Errorf("updateDocuments set clause: %w", err)
+	}

-	whereClause, filterArgs, err := c.convertFilterToWhereClause(filter, paramOffset)
-	if err != nil {
-		return nil, err
-	}
+	whereClause, filterArgs, err := c.convertFilterToWhereClause(filter, paramOffset)
+	if err != nil {
+		return nil, fmt.Errorf("updateDocuments where clause: %w", err)
+	}

As per coding guidelines: "Wrap errors with context using fmt.Errorf("context: %w", err) in Go code".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@store-client/pkg/datastore/providers/postgresql/database_client.go` around
lines 472 - 524, In updateDocuments, wrap errors returned from
convertUpdateToSetClause and convertFilterToWhereClause with contextual
fmt.Errorf calls instead of returning them raw; update the error handling after
calling convertUpdateToSetClause to return fmt.Errorf("convert update to SET
clause: %w", err) and after convertFilterToWhereClause to return
fmt.Errorf("convert filter to WHERE clause: %w", err) so callers see contextual
error messages (refer to updateDocuments, convertUpdateToSetClause,
convertFilterToWhereClause).
♻️ Duplicate comments (4)
store-client/pkg/client/postgresql_changestream.go (1)

402-404: $match field filters still bypassed for delete events (nil newValues).

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@store-client/pkg/client/postgresql_changestream.go` around lines 402 - 404,
The $match filters are skipped for delete events because the code only checks
entry.newValues; update the logic in the change-stream evaluation (where
entry.newValues and w.matchesFilters(matchMap, ... ) are used) to also run
matchesFilters against entry.oldValues when entry.newValues is nil (i.e., for
delete events), or otherwise construct the document to match against oldValues
for deletes; ensure you reference entry.newValues, entry.oldValues and the
matchesFilters(matchMap, ...) call so delete events are filtered by the same
$match criteria as inserts/updates.
store-client/pkg/datastore/providers/postgresql/database_client.go (2)

934-959: LGTM — resolveFilterMapForFind correctly handles nil filters and wraps errors with context.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@store-client/pkg/datastore/providers/postgresql/database_client.go` around
lines 934 - 959, No change required: the resolveFilterMapForFind method already
handles nil filters, converts and validates the filter map, applies
maintenance_events field transformation via
transformFilterMapForMaintenanceEvents when c.tableName ==
maintenanceEventTableName, wraps errors from filterMapToConditions with table
context, and returns the whereClause and args produced by
conditionsToWhereClause; leave PostgreSQLDatabaseClient.resolveFilterMapForFind
as-is.

422-470: LGTM — convertUpdateToSetClause now correctly errors on unsupported update types.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@store-client/pkg/datastore/providers/postgresql/database_client.go` around
lines 422 - 470, The review comment contains duplicated review metadata/tags
(e.g. both "[approve_code_changes]" and "[duplicate_comment]")—clean up the PR
by removing the redundant tag so only the intended approval marker remains; no
code changes in convertUpdateToSetClause, builder.SetDocumentField, builder.Set,
or related logic are required, just edit the review/comment to remove the
duplicate marker.
store-client/pkg/storewatcher/unmarshaller.go (1)

93-108: LGTM — CanSet() guard and type-safety checks address the previous reflect panic risk.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@store-client/pkg/storewatcher/unmarshaller.go` around lines 93 - 108, The
reflect panic risk has been addressed by guarding with dstField.CanSet() and
explicit kind/type checks in the switch; no code changes required—keep the
dstField.CanSet() guard and the current cases that call copyPtrField(dstField,
srcField), CopyStructFields(dstField, srcField), and use
srcField.Type().AssignableTo / ConvertibleTo before calling dstField.Set or
dstField.Set(srcField.Convert(...)).
🧹 Nitpick comments (4)
janitor-provider/pkg/csp/gcp/gcp.go (1)

206-229: Error wrapping fully addressed; consider making prepareInstanceOp a package-level function.

The error-context wrapping at lines 211, 216, and 225 is correct (past review comment resolved ✅), and the instancesClient.Close() guard on the getNodeFields failure path correctly prevents a resource leak.

One optional consistency note: prepareInstanceOp is defined as a method on *Client, but it never accesses the receiver — matching the pattern of the two sibling helpers (getAuthenticatedHTTPClient, getNodeFields) that are package-level functions. Since Client is an empty struct, there is no future state it could plausibly need.

♻️ Optional: convert to package-level function
-func (c *Client) prepareInstanceOp(
-	ctx context.Context, node corev1.Node,
-) (*compute.InstancesClient, *gcpNodeFields, error) {
+func prepareInstanceOp(
+	ctx context.Context, node corev1.Node,
+) (*compute.InstancesClient, *gcpNodeFields, error) {

Then update the two call sites:

-	instancesClient, nodeFields, err := c.prepareInstanceOp(ctx, node)
+	instancesClient, nodeFields, err := prepareInstanceOp(ctx, node)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@janitor-provider/pkg/csp/gcp/gcp.go` around lines 206 - 229,
prepareInstanceOp is a method on *Client but does not use the receiver; make it
a package-level function by removing the receiver from func (c *Client)
prepareInstanceOp -> func prepareInstanceOp and update all call sites that
currently invoke c.prepareInstanceOp(...) to call prepareInstanceOp(...); keep
the existing logic (calls to getAuthenticatedHTTPClient,
compute.NewInstancesRESTClient, getNodeFields and the instancesClient.Close() on
error) unchanged.
store-client/pkg/client/postgresql_changestream.go (1)

342-376: scanChangelogEntry never uses its receiver — consider making it a package-level function.

The method body only operates on rows *sql.Rows and never reads or writes any field of w. A standalone function scanChangelogEntry(rows *sql.Rows) (*postgresqlEvent, error) would be cleaner and avoid falsely implying watcher state is involved.

♻️ Proposed refactor
-func (w *PostgreSQLChangeStreamWatcher) scanChangelogEntry(rows *sql.Rows) (*postgresqlEvent, error) {
+func scanChangelogEntry(rows *sql.Rows) (*postgresqlEvent, error) {

Then update the call site at line 320:

-		entry, err := w.scanChangelogEntry(rows)
+		entry, err := scanChangelogEntry(rows)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@store-client/pkg/client/postgresql_changestream.go` around lines 342 - 376,
The method scanChangelogEntry has an unused receiver
(PostgreSQLChangeStreamWatcher) so convert it to a package-level function
scanChangelogEntry(rows *sql.Rows) (*postgresqlEvent, error) that performs the
same scanning and JSON unmarshalling into postgresqlEvent, then update every
call site that currently invokes w.scanChangelogEntry(...) (e.g. in the change
stream processing loop) to call scanChangelogEntry(...) instead; ensure imports
and visibility remain correct and run tests to validate behavior.
janitor-provider/pkg/csp/kind/kind.go (1)

126-127: Remove the unused ctx parameter from deleteAndVerifyContainer.

The ctx parameter is never referenced in the helper function—only dockerCtx is used. Removing it simplifies the signature and reduces cognitive overhead.

Proposed cleanup
-	if err := c.deleteAndVerifyContainer(ctx, dockerCtx, containerName); err != nil {
+	if err := c.deleteAndVerifyContainer(dockerCtx, containerName); err != nil {
 		return "", err
 	}
@@
 func (c *Client) deleteAndVerifyContainer(
-	ctx, dockerCtx context.Context, containerName string,
+	dockerCtx context.Context, containerName string,
 ) error {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@janitor-provider/pkg/csp/kind/kind.go` around lines 126 - 127, The helper
method deleteAndVerifyContainer has an unused ctx parameter; update its
signature to remove the unused ctx and adjust all call sites (e.g., where
c.deleteAndVerifyContainer(ctx, dockerCtx) is invoked) to pass only dockerCtx;
modify the method definition for deleteAndVerifyContainer accordingly and ensure
any imports/uses inside that function reference dockerCtx (and not ctx) so
compilation and behavior remain unchanged.
store-client/pkg/storewatcher/unmarshaller.go (1)

110-125: Consider a default debug log in copyPtrField for unmatched pointer combinations.

When srcField is non-nil, the pointed-to types are not both structs, the pointer types are not directly assignable, and the elements are not convertible, the function silently leaves dstField unchanged. This is safe today, but will silently drop fields if struct shapes diverge in the future.

🔍 Suggested default case
 	case srcField.Type().Elem().ConvertibleTo(dstField.Type().Elem()):
 		newPtr := reflect.New(dstField.Type().Elem())
 		newPtr.Elem().Set(srcField.Elem().Convert(dstField.Type().Elem()))
 		dstField.Set(newPtr)
+	default:
+		slog.Debug("copyPtrField: skipping incompatible pointer field",
+			"srcType", srcField.Type().String(),
+			"dstType", dstField.Type().String())
 	}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@store-client/pkg/storewatcher/unmarshaller.go` around lines 110 - 125, In
copyPtrField: when none of the existing switch branches match (srcField non-nil,
not both struct pointers, not assignable, and not convertible) the function
currently returns silently and may drop fields; add a default branch that emits
a debug/log message (using the package's logger or a new debug logger) that
includes the dstField.Type(), srcField.Type(), and a note that the pointer
combination was skipped, referencing copyPtrField and CopyStructFields so the
log pinpoints the code path; do not change the current behavior (do not set
dstField) — only add the diagnostic log for future debugging.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@janitor-provider/pkg/csp/gcp/gcp.go`:
- Around line 128-131: Wrap the raw errors returned from instancesClient.Reset
and instancesClient.Delete with contextual messages using fmt.Errorf so callers
can identify which GCP operation failed; for the Reset call
(instancesClient.Reset(ctx, resetReq)) change the return to wrap err (e.g.
fmt.Errorf("reset instance %s: %w", instanceID, err)) and for the Delete call
(instancesClient.Delete(ctx, deleteReq)) similarly wrap the error (e.g.
fmt.Errorf("delete instance %s: %w", instanceID, err)), ensuring you import fmt
if not already present and preserve the original error via %w.

In `@store-client/pkg/client/event_processor.go`:
- Around line 152-179: The unmarshal and GetDocumentID error paths in
DefaultEventProcessor.handleSingleEvent currently always call markProcessed,
ignoring EventProcessorConfig.MarkProcessedOnError; update those branches to
respect the config by only calling p.markProcessed(ctx, token) when
p.config.MarkProcessedOnError is true, otherwise route the error through
p.handleProcessingError(ctx, token, err, eventID?) (or an appropriate wrapper
error) so the error-handling logic that respects MarkProcessedOnError is used;
alternatively, if parse failures are intended to be always skipped, add a clear
comment/godoc on EventProcessorConfig.MarkProcessedOnError and on
handleSingleEvent stating parse errors are unrecoverable. Ensure references to
p.markProcessed, p.handleProcessingError,
DefaultEventProcessor.handleSingleEvent and
EventProcessorConfig.MarkProcessedOnError are used to locate and change the
code.

In `@store-client/pkg/client/postgresql_changestream.go`:
- Around line 422-431: The mapOperationType currently maps only the first
element of an "$in" array, causing multi-operation filters to drop events;
change PostgreSQLChangeStreamWatcher.mapOperationType to return a slice of
strings ([]string) by handling string inputs (map to single-item slice via
mapSingleOpType) and by iterating over map["$in"] arrays to map each element
(skipping non-strings or unmapped values), then update matchesPipeline to treat
the returned value as a list and accept the entry when entry.operation equals
any of the mapped strings (instead of comparing only to a single expectedOp).

In `@store-client/pkg/datastore/providers/postgresql/database_client.go`:
- Around line 840-892: FindOne currently converts the filter inline (via
convertFilterToMap) and builds conditions directly, skipping the same
maintenance-events key transformation used by Find; update FindOne to reuse
resolveFilterMapForFind (the same helper used by Find) to obtain the transformed
filter map (which in turn calls transformFilterMapForMaintenanceEvents for the
maintenance_events table) before calling
filterMapToConditions/conditionsToWhereClause, so camelCase keys like
scheduledStartTime are converted to the indexed snake_case columns; ensure the
code path still handles query.Builder inputs the same way and preserves existing
error handling and SQL construction.
- Around line 472-524: In updateDocuments, wrap errors returned from
convertUpdateToSetClause and convertFilterToWhereClause with contextual
fmt.Errorf calls instead of returning them raw; update the error handling after
calling convertUpdateToSetClause to return fmt.Errorf("convert update to SET
clause: %w", err) and after convertFilterToWhereClause to return
fmt.Errorf("convert filter to WHERE clause: %w", err) so callers see contextual
error messages (refer to updateDocuments, convertUpdateToSetClause,
convertFilterToWhereClause).

---

Duplicate comments:
In `@store-client/pkg/client/postgresql_changestream.go`:
- Around line 402-404: The $match filters are skipped for delete events because
the code only checks entry.newValues; update the logic in the change-stream
evaluation (where entry.newValues and w.matchesFilters(matchMap, ... ) are used)
to also run matchesFilters against entry.oldValues when entry.newValues is nil
(i.e., for delete events), or otherwise construct the document to match against
oldValues for deletes; ensure you reference entry.newValues, entry.oldValues and
the matchesFilters(matchMap, ...) call so delete events are filtered by the same
$match criteria as inserts/updates.

In `@store-client/pkg/datastore/providers/postgresql/database_client.go`:
- Around line 934-959: No change required: the resolveFilterMapForFind method
already handles nil filters, converts and validates the filter map, applies
maintenance_events field transformation via
transformFilterMapForMaintenanceEvents when c.tableName ==
maintenanceEventTableName, wraps errors from filterMapToConditions with table
context, and returns the whereClause and args produced by
conditionsToWhereClause; leave PostgreSQLDatabaseClient.resolveFilterMapForFind
as-is.
- Around line 422-470: The review comment contains duplicated review
metadata/tags (e.g. both "[approve_code_changes]" and
"[duplicate_comment]")—clean up the PR by removing the redundant tag so only the
intended approval marker remains; no code changes in convertUpdateToSetClause,
builder.SetDocumentField, builder.Set, or related logic are required, just edit
the review/comment to remove the duplicate marker.

In `@store-client/pkg/storewatcher/unmarshaller.go`:
- Around line 93-108: The reflect panic risk has been addressed by guarding with
dstField.CanSet() and explicit kind/type checks in the switch; no code changes
required—keep the dstField.CanSet() guard and the current cases that call
copyPtrField(dstField, srcField), CopyStructFields(dstField, srcField), and use
srcField.Type().AssignableTo / ConvertibleTo before calling dstField.Set or
dstField.Set(srcField.Convert(...)).

---

Nitpick comments:
In `@janitor-provider/pkg/csp/gcp/gcp.go`:
- Around line 206-229: prepareInstanceOp is a method on *Client but does not use
the receiver; make it a package-level function by removing the receiver from
func (c *Client) prepareInstanceOp -> func prepareInstanceOp and update all call
sites that currently invoke c.prepareInstanceOp(...) to call
prepareInstanceOp(...); keep the existing logic (calls to
getAuthenticatedHTTPClient, compute.NewInstancesRESTClient, getNodeFields and
the instancesClient.Close() on error) unchanged.

In `@janitor-provider/pkg/csp/kind/kind.go`:
- Around line 126-127: The helper method deleteAndVerifyContainer has an unused
ctx parameter; update its signature to remove the unused ctx and adjust all call
sites (e.g., where c.deleteAndVerifyContainer(ctx, dockerCtx) is invoked) to
pass only dockerCtx; modify the method definition for deleteAndVerifyContainer
accordingly and ensure any imports/uses inside that function reference dockerCtx
(and not ctx) so compilation and behavior remain unchanged.

In `@store-client/pkg/client/postgresql_changestream.go`:
- Around line 342-376: The method scanChangelogEntry has an unused receiver
(PostgreSQLChangeStreamWatcher) so convert it to a package-level function
scanChangelogEntry(rows *sql.Rows) (*postgresqlEvent, error) that performs the
same scanning and JSON unmarshalling into postgresqlEvent, then update every
call site that currently invokes w.scanChangelogEntry(...) (e.g. in the change
stream processing loop) to call scanChangelogEntry(...) instead; ensure imports
and visibility remain correct and run tests to validate behavior.

In `@store-client/pkg/storewatcher/unmarshaller.go`:
- Around line 110-125: In copyPtrField: when none of the existing switch
branches match (srcField non-nil, not both struct pointers, not assignable, and
not convertible) the function currently returns silently and may drop fields;
add a default branch that emits a debug/log message (using the package's logger
or a new debug logger) that includes the dstField.Type(), srcField.Type(), and a
note that the pointer combination was skipped, referencing copyPtrField and
CopyStructFields so the log pinpoints the code path; do not change the current
behavior (do not set dstField) — only add the diagnostic log for future
debugging.

ℹ️ Review info

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0a10453 and 1c7a6f2.

📒 Files selected for processing (7)
  • janitor-provider/pkg/csp/gcp/gcp.go
  • janitor-provider/pkg/csp/kind/kind.go
  • store-client/pkg/client/event_processor.go
  • store-client/pkg/client/postgresql_changestream.go
  • store-client/pkg/datastore/providers/mongodb/watcher/watch_store.go
  • store-client/pkg/datastore/providers/postgresql/database_client.go
  • store-client/pkg/storewatcher/unmarshaller.go
🚧 Files skipped from review as they are similar to previous changes (1)
  • store-client/pkg/datastore/providers/mongodb/watcher/watch_store.go

@cbumb cbumb force-pushed the 728_nolint-cleanup-6 branch from c089785 to 9fde532 Compare February 25, 2026 07:44
Copy link
Contributor

@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: 4

♻️ Duplicate comments (1)
store-client/pkg/client/postgresql_changestream.go (1)

403-405: ⚠️ Potential issue | 🟠 Major

$match field predicates are still bypassed when newValues is nil.

On Line [403], delete events can skip non-operationType filtering entirely, causing false-positive matches. Evaluate against oldValues when newValues is absent.

✅ Proposed patch
-		if entry.newValues != nil && !w.matchesFilters(matchMap, entry.newValues) {
-			return false
-		}
+		payload := entry.newValues
+		if payload == nil {
+			payload = entry.oldValues
+		}
+
+		if payload == nil {
+			// If field predicates exist but no payload is available, fail closed.
+			if len(matchMap) > 1 {
+				return false
+			}
+		} else if !w.matchesFilters(matchMap, payload) {
+			return false
+		}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@store-client/pkg/client/postgresql_changestream.go` around lines 403 - 405,
The current check uses entry.newValues only, letting delete events (where
newValues is nil) bypass $match predicates; change the logic in the block around
the conditional that calls w.matchesFilters(matchMap, ...) so that when
entry.newValues is nil it evaluates matches against entry.oldValues instead
(i.e., call w.matchesFilters(matchMap, entry.newValues ?? entry.oldValues)), and
ensure you treat the case where both newValues and oldValues are nil as a
non-match; update the conditional near the call to w.matchesFilters to reflect
this fallback behavior.
🧹 Nitpick comments (3)
janitor-provider/pkg/csp/gcp/gcp.go (2)

109-112: Wrap the prepareInstanceOp error with caller context.

Both SendRebootSignal and SendTerminateSignal return the error from prepareInstanceOp unwrapped. Per coding guidelines, every propagation site should add context so the call stack is self-evident in logs.

♻️ Proposed fix
-	instancesClient, nodeFields, err := prepareInstanceOp(ctx, node)
-	if err != nil {
-		return "", err
-	}
+	instancesClient, nodeFields, err := prepareInstanceOp(ctx, node)
+	if err != nil {
+		return "", fmt.Errorf("send reboot signal: %w", err)
+	}
-	instancesClient, nodeFields, err := prepareInstanceOp(ctx, node)
-	if err != nil {
-		return "", err
-	}
+	instancesClient, nodeFields, err := prepareInstanceOp(ctx, node)
+	if err != nil {
+		return "", fmt.Errorf("send terminate signal: %w", err)
+	}

As per coding guidelines: "Wrap errors with context using fmt.Errorf("context: %w", err) in Go code".

Also applies to: 179-182

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@janitor-provider/pkg/csp/gcp/gcp.go` around lines 109 - 112, In
SendRebootSignal and SendTerminateSignal, wrap the error returned from
prepareInstanceOp with caller context using fmt.Errorf, e.g. return "",
fmt.Errorf("SendRebootSignal: prepareInstanceOp failed: %w", err) (and similarly
for SendTerminateSignal) so the propagated error includes the function context;
update both call sites that currently do `if err != nil { return "", err }` to
use the wrapped error form referencing prepareInstanceOp.

130-130: Use %q for instance name in error strings for consistency.

Lines 130 and 200 use %s for nodeFields.instance, while line 225 uses %q for node.Name. Quoted identifiers are easier to distinguish in log output.

♻️ Proposed fix
-		return "", fmt.Errorf("reset instance %s: %w", nodeFields.instance, err)
+		return "", fmt.Errorf("reset instance %q: %w", nodeFields.instance, err)
-		return "", fmt.Errorf("delete instance %s: %w", nodeFields.instance, err)
+		return "", fmt.Errorf("delete instance %q: %w", nodeFields.instance, err)

Also applies to: 200-200

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@janitor-provider/pkg/csp/gcp/gcp.go` at line 130, Replace the unquoted
instance identifiers in the fmt.Errorf calls with quoted format verbs for
consistency: change the fmt.Errorf call that formats nodeFields.instance (the
"reset instance %s: %w" invocation) to use %q instead of %s, and do the same for
the other fmt.Errorf that currently uses nodeFields.instance at the second
occurrence; this will match the existing use of %q for node.Name and produce
quoted identifiers in logs.
store-client/pkg/client/postgresql_changestream.go (1)

321-341: Handle row-iteration errors after the rows.Next() loop.

rows.Next() loop exits silently on driver/stream errors unless rows.Err() is checked. Add a post-loop check so polling failures are observable.

💡 Proposed patch
 	for rows.Next() {
 		entry, err := scanChangelogEntry(rows)
 		if err != nil {
 			slog.Error("Failed to process changelog entry", "error", err)
 			continue
 		}
@@
 		}
 	}
+
+	if err := rows.Err(); err != nil {
+		slog.Error("Failed while iterating changelog rows", "error", err)
+	}
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@store-client/pkg/client/postgresql_changestream.go` around lines 321 - 341,
The rows.Next() loop in the worker that calls scanChangelogEntry (which updates
w.lastSeenID, checks w.matchesPipeline and sends entries on w.eventChan) doesn't
check rows.Err() after the loop, so driver/stream errors can be ignored; after
the loop finishes add a rows.Err() check and handle any error (log via
slog.Error or return it/upstream) and/or close/stop the worker (use
ctx.Done()/w.stopChan) so polling failures are observable and not silently
ignored.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@store-client/pkg/client/postgresql_changestream.go`:
- Around line 396-400: The code in the change filter incorrectly treats an
operationType that maps to zero PostgreSQL ops as permissive; inside the block
that reads matchMap["operationType"] and calls mapOperationTypes(opType)
(producing expectedOps), change the logic so that if len(expectedOps) == 0 you
immediately return false (reject the event) instead of allowing it to pass; keep
the existing check using slices.Contains(entry.operation) for non-empty
expectedOps to preserve normal behavior.

In `@store-client/pkg/datastore/providers/postgresql/database_client.go`:
- Around line 429-441: When updateMap contains a "$set" key, currently sibling
operator keys are ignored; modify the logic in the function handling updates
(the block that reads updateMap and calls c.convertFilterToMap) to detect any
other keys that start with "$" besides "$set" and return an error instead of
proceeding. Specifically, after detecting hasSet, iterate updateMap's keys and
if any key != "$set" and has the "$" prefix, return a descriptive fmt.Errorf
indicating mixed/unsupported Mongo update operators; keep the existing
convertFilterToMap usage for validating the "$set" value and preserve the
existing debug logs when valid.
- Around line 851-853: In FindOne and Find, when calling
resolveFilterMapForFind, don't return the raw error — wrap it with caller
context using fmt.Errorf to preserve operation context; e.g., replace returns
like "return nil, err" after resolveFilterMapForFind with "return nil,
fmt.Errorf(\"FindOne: resolveFilterMapForFind failed: %w\", err)" (use an
appropriate function name in the message for each site), ensuring you import fmt
if missing and apply the same wrapping pattern for the other call site (the one
referenced near the second occurrence).
- Around line 648-655: The isDescending function currently handles only int,
int64, and float64 causing int32 (and other small numeric types from BSON) to
default to ascending; update isDescending to include cases for int8, int16,
int32 and float32 (and any other numeric types you expect) in the type switch so
those values returning < 0 are treated as descending; modify the switch in
isDescending to add case branches for int8, int16, int32, float32 (and mirror
behavior for other signed numeric types if needed) so negative values across
these types return true.

---

Duplicate comments:
In `@store-client/pkg/client/postgresql_changestream.go`:
- Around line 403-405: The current check uses entry.newValues only, letting
delete events (where newValues is nil) bypass $match predicates; change the
logic in the block around the conditional that calls w.matchesFilters(matchMap,
...) so that when entry.newValues is nil it evaluates matches against
entry.oldValues instead (i.e., call w.matchesFilters(matchMap, entry.newValues
?? entry.oldValues)), and ensure you treat the case where both newValues and
oldValues are nil as a non-match; update the conditional near the call to
w.matchesFilters to reflect this fallback behavior.

---

Nitpick comments:
In `@janitor-provider/pkg/csp/gcp/gcp.go`:
- Around line 109-112: In SendRebootSignal and SendTerminateSignal, wrap the
error returned from prepareInstanceOp with caller context using fmt.Errorf, e.g.
return "", fmt.Errorf("SendRebootSignal: prepareInstanceOp failed: %w", err)
(and similarly for SendTerminateSignal) so the propagated error includes the
function context; update both call sites that currently do `if err != nil {
return "", err }` to use the wrapped error form referencing prepareInstanceOp.
- Line 130: Replace the unquoted instance identifiers in the fmt.Errorf calls
with quoted format verbs for consistency: change the fmt.Errorf call that
formats nodeFields.instance (the "reset instance %s: %w" invocation) to use %q
instead of %s, and do the same for the other fmt.Errorf that currently uses
nodeFields.instance at the second occurrence; this will match the existing use
of %q for node.Name and produce quoted identifiers in logs.

In `@store-client/pkg/client/postgresql_changestream.go`:
- Around line 321-341: The rows.Next() loop in the worker that calls
scanChangelogEntry (which updates w.lastSeenID, checks w.matchesPipeline and
sends entries on w.eventChan) doesn't check rows.Err() after the loop, so
driver/stream errors can be ignored; after the loop finishes add a rows.Err()
check and handle any error (log via slog.Error or return it/upstream) and/or
close/stop the worker (use ctx.Done()/w.stopChan) so polling failures are
observable and not silently ignored.

ℹ️ Review info

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1c7a6f2 and c089785.

📒 Files selected for processing (4)
  • janitor-provider/pkg/csp/gcp/gcp.go
  • janitor-provider/pkg/csp/kind/kind.go
  • store-client/pkg/client/postgresql_changestream.go
  • store-client/pkg/datastore/providers/postgresql/database_client.go
🚧 Files skipped from review as they are similar to previous changes (1)
  • janitor-provider/pkg/csp/kind/kind.go

Copy link
Contributor

@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

♻️ Duplicate comments (5)
store-client/pkg/datastore/providers/postgresql/database_client.go (3)

847-853: resolveFilterMapForFind errors still returned unwrapped in FindOne and Find.

Lines 852 and 901 return raw errors without caller context. This was flagged in a prior review.

As per coding guidelines: "Wrap errors with context using fmt.Errorf("context: %w", err) in Go code".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@store-client/pkg/datastore/providers/postgresql/database_client.go` around
lines 847 - 853, In FindOne and Find (in database_client.go) you return errors
from resolveFilterMapForFind directly; update both call sites to wrap those
errors with context using fmt.Errorf, e.g. fmt.Errorf("resolving filter for
FindOne: %w", err) (or similar for Find), so the returned error includes caller
context and references resolveFilterMapForFind in the message.

429-441: Sibling $ operators alongside $set are still silently ignored.

When $set is present, other operator keys (e.g., $unset) are not validated or rejected. This was flagged in a prior review.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@store-client/pkg/datastore/providers/postgresql/database_client.go` around
lines 429 - 441, When parsing updateMap in the update path (the block that
checks if setOp, hasSet := updateMap["$set"]), ensure we validate and reject any
sibling operator keys that start with '$' other than "$set"; after converting
setFields with convertFilterToMap, iterate the keys of updateMap and if any key
has prefix "$" and is not "$set" return a clear error (e.g., "$set cannot be
mixed with other update operators: <op>"). Update the logic around updateMap,
setOp, setFields and convertFilterToMap to perform this check and return an
error instead of silently ignoring operators like "$unset".

648-659: isDescending still missing int32 (and other small numeric types from BSON).

This was flagged in a prior review. Sort direction values from BSON unmarshaling commonly arrive as int32, which would silently default to ascending here.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@store-client/pkg/datastore/providers/postgresql/database_client.go` around
lines 648 - 659, The isDescending function currently ignores BSON int32 (and
other small numeric types) and should treat any signed integer or float value <
0 as descending; update isDescending (in database_client.go) to either add
explicit cases for int32, int8, int16 and float32 or (preferably) use reflect to
detect signed integer kinds and float kinds and compare their numeric value < 0
so all BSON numeric types are handled consistently.
store-client/pkg/config/env_loader.go (1)

193-201: Raw errors from getRequiredEnv returned without caller context.

Lines 195 and 200 return the error directly without wrapping. The same pattern appears at lines 246, 251, 256, 439, and 444. This was flagged in a prior review.

As per coding guidelines: "Wrap errors with context using fmt.Errorf("context: %w", err) in Go code".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@store-client/pkg/config/env_loader.go` around lines 193 - 201, Calls to
getRequiredEnv are returning raw errors without context; update each return to
wrap the error with fmt.Errorf including which env var failed. For example,
replace "connectionURI, err := getRequiredEnv(EnvMongoDBURI); if err != nil {
return nil, err }" with wrapping: if err != nil { return nil, fmt.Errorf("failed
to load %s: %w", EnvMongoDBURI, err) } and do the same for
EnvMongoDBDatabaseName and every other getRequiredEnv call in this file (the
occurrences noted around the other flagged lines), importing fmt if necessary.
Ensure each wrapped message names the env constant to provide caller context.
store-client/pkg/client/postgresql_changestream.go (1)

396-405: Two prior issues remain unaddressed in matchesPipeline.

  1. Line 398: When mapOperationTypes returns an empty slice for an unsupported operation type, len(expectedOps) > 0 is false, so the event passes the filter instead of being rejected. This was flagged in a prior review.

  2. Lines 403-405: When entry.newValues is nil (e.g., delete events), matchesFilters is skipped entirely, so non-operationType predicates are not evaluated. This broadens matching for delete events. This was also flagged in a prior review.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@store-client/pkg/client/postgresql_changestream.go` around lines 396 - 405,
mapOperationTypes returning an empty slice should reject the event: in
matchesPipeline, if "operationType" exists in matchMap, call
mapOperationTypes(opType) and if the returned slice is empty, immediately return
false (do not treat empty as a wildcard). Also ensure non-operationType
predicates are always evaluated for delete/update: when checking matchesFilters,
don't skip it just because entry.newValues is nil — instead call matchesFilters
with entry.newValues if present, otherwise with entry.oldValues (and if both are
nil, treat as non-match and return false) so delete events still run through the
remaining predicates; update the logic around matchMap, matchesFilters,
entry.newValues, and entry.oldValues accordingly.
🧹 Nitpick comments (1)
janitor-provider/pkg/csp/kind/kind.go (1)

172-174: Inconsistent container-name matching: strings.Contains here vs exact line matching at lines 112-117.

The initial container lookup was changed to exact line-by-line matching to prevent false positives (e.g., "node-10" matching "node-1"), but the post-delete verification still uses strings.Contains. For consistency and to avoid the same class of bug, apply the same pattern.

Proposed fix
-	if strings.Contains(string(output), containerName) {
+	for _, line := range strings.Split(strings.TrimSpace(string(output)), "\n") {
+		if line == containerName {
+			return fmt.Errorf("container %s still exists after deletion attempt", containerName)
+		}
+	}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@janitor-provider/pkg/csp/kind/kind.go` around lines 172 - 174, The
post-delete verification currently uses strings.Contains(output, containerName)
which can yield false positives; update the check to use the same exact
line-by-line matching used earlier (the initial lookup at lines where the code
splits output into lines and compares the container name field exactly) so that
you only treat the container as present when a line's container identifier
exactly equals containerName; apply this precise matching to the verification
that follows the delete attempt (the block referencing containerName and output)
instead of strings.Contains.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@janitor-provider/pkg/csp/kind/kind.go`:
- Around line 136-138: The deleteAndVerifyContainer function currently accepts
an unused ctx parameter; either remove the unused ctx from the signature of
deleteAndVerifyContainer or actually use it by propagating it to the docker exec
calls and checking for parent cancellation (e.g., verify ctx.Err() before/after
execs and pass ctx into exec.CommandContext alongside dockerCtx where
appropriate); update all call sites of deleteAndVerifyContainer to match the new
signature if you remove the parameter or ensure callers pass the intended
context if you elect to use it.

---

Duplicate comments:
In `@store-client/pkg/client/postgresql_changestream.go`:
- Around line 396-405: mapOperationTypes returning an empty slice should reject
the event: in matchesPipeline, if "operationType" exists in matchMap, call
mapOperationTypes(opType) and if the returned slice is empty, immediately return
false (do not treat empty as a wildcard). Also ensure non-operationType
predicates are always evaluated for delete/update: when checking matchesFilters,
don't skip it just because entry.newValues is nil — instead call matchesFilters
with entry.newValues if present, otherwise with entry.oldValues (and if both are
nil, treat as non-match and return false) so delete events still run through the
remaining predicates; update the logic around matchMap, matchesFilters,
entry.newValues, and entry.oldValues accordingly.

In `@store-client/pkg/config/env_loader.go`:
- Around line 193-201: Calls to getRequiredEnv are returning raw errors without
context; update each return to wrap the error with fmt.Errorf including which
env var failed. For example, replace "connectionURI, err :=
getRequiredEnv(EnvMongoDBURI); if err != nil { return nil, err }" with wrapping:
if err != nil { return nil, fmt.Errorf("failed to load %s: %w", EnvMongoDBURI,
err) } and do the same for EnvMongoDBDatabaseName and every other getRequiredEnv
call in this file (the occurrences noted around the other flagged lines),
importing fmt if necessary. Ensure each wrapped message names the env constant
to provide caller context.

In `@store-client/pkg/datastore/providers/postgresql/database_client.go`:
- Around line 847-853: In FindOne and Find (in database_client.go) you return
errors from resolveFilterMapForFind directly; update both call sites to wrap
those errors with context using fmt.Errorf, e.g. fmt.Errorf("resolving filter
for FindOne: %w", err) (or similar for Find), so the returned error includes
caller context and references resolveFilterMapForFind in the message.
- Around line 429-441: When parsing updateMap in the update path (the block that
checks if setOp, hasSet := updateMap["$set"]), ensure we validate and reject any
sibling operator keys that start with '$' other than "$set"; after converting
setFields with convertFilterToMap, iterate the keys of updateMap and if any key
has prefix "$" and is not "$set" return a clear error (e.g., "$set cannot be
mixed with other update operators: <op>"). Update the logic around updateMap,
setOp, setFields and convertFilterToMap to perform this check and return an
error instead of silently ignoring operators like "$unset".
- Around line 648-659: The isDescending function currently ignores BSON int32
(and other small numeric types) and should treat any signed integer or float
value < 0 as descending; update isDescending (in database_client.go) to either
add explicit cases for int32, int8, int16 and float32 or (preferably) use
reflect to detect signed integer kinds and float kinds and compare their numeric
value < 0 so all BSON numeric types are handled consistently.

---

Nitpick comments:
In `@janitor-provider/pkg/csp/kind/kind.go`:
- Around line 172-174: The post-delete verification currently uses
strings.Contains(output, containerName) which can yield false positives; update
the check to use the same exact line-by-line matching used earlier (the initial
lookup at lines where the code splits output into lines and compares the
container name field exactly) so that you only treat the container as present
when a line's container identifier exactly equals containerName; apply this
precise matching to the verification that follows the delete attempt (the block
referencing containerName and output) instead of strings.Contains.

ℹ️ Review info

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c089785 and 546bd49.

📒 Files selected for processing (9)
  • janitor-provider/pkg/csp/gcp/gcp.go
  • janitor-provider/pkg/csp/kind/kind.go
  • store-client/pkg/adapter/legacy_adapter.go
  • store-client/pkg/client/event_processor.go
  • store-client/pkg/client/postgresql_changestream.go
  • store-client/pkg/config/env_loader.go
  • store-client/pkg/datastore/providers/mongodb/watcher/watch_store.go
  • store-client/pkg/datastore/providers/postgresql/database_client.go
  • store-client/pkg/storewatcher/unmarshaller.go
🚧 Files skipped from review as they are similar to previous changes (1)
  • store-client/pkg/datastore/providers/mongodb/watcher/watch_store.go

@github-actions
Copy link

Merging this branch will decrease overall coverage

Impacted Packages Coverage Δ 🤖
github.com/nvidia/nvsentinel/janitor 0.00% (ø)
github.com/nvidia/nvsentinel/janitor/api/v1alpha1 24.78% (ø)
github.com/nvidia/nvsentinel/janitor/pkg/config 24.07% (ø)
github.com/nvidia/nvsentinel/janitor/pkg/controller 18.38% (-0.03%) 👎

Coverage by file

Changed files (no unit tests)

Changed File Coverage Δ Total Covered Missed 🤖
github.com/nvidia/nvsentinel/janitor/api/v1alpha1/gpureset_types.go 71.43% (ø) 7 5 2
github.com/nvidia/nvsentinel/janitor/api/v1alpha1/rebootnode_types.go 37.00% (ø) 300 111 189
github.com/nvidia/nvsentinel/janitor/api/v1alpha1/terminatenode_types.go 26.84% (ø) 272 73 199
github.com/nvidia/nvsentinel/janitor/main.go 0.00% (ø) 1223 0 1223
github.com/nvidia/nvsentinel/janitor/pkg/config/config.go 22.48% (ø) 218 49 169
github.com/nvidia/nvsentinel/janitor/pkg/config/default.go 24.94% (ø) 397 99 298
github.com/nvidia/nvsentinel/janitor/pkg/controller/rebootnode_controller.go 19.44% (ø) 895 174 721
github.com/nvidia/nvsentinel/janitor/pkg/controller/utils.go 0.00% (ø) 101 0 101

Please note that the "Total", "Covered", and "Missed" counts above refer to code statements instead of lines of code. The value in brackets refers to the test coverage of that file in the old version of the code.

Changed unit test files

  • github.com/nvidia/nvsentinel/janitor/pkg/controller/rebootnode_controller_test.go

@cbumb cbumb force-pushed the 728_nolint-cleanup-6 branch from 546bd49 to bb681ac Compare February 25, 2026 19:40
Copy link
Contributor

@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.

♻️ Duplicate comments (1)
store-client/pkg/client/postgresql_changestream.go (1)

403-405: ⚠️ Potential issue | 🟠 Major

$match field predicates are still skipped when newValues is nil.

At Line 403, filtering only against entry.newValues lets delete events bypass non-operationType predicates. Fall back to entry.oldValues (or reject if field predicates exist and no payload is available).

✅ Proposed fix
-		if entry.newValues != nil && !w.matchesFilters(matchMap, entry.newValues) {
-			return false
-		}
+		payload := entry.newValues
+		if payload == nil {
+			payload = entry.oldValues
+		}
+
+		if payload == nil {
+			// If field predicates exist but no payload is available, reject.
+			if len(matchMap) > 1 {
+				return false
+			}
+		} else if !w.matchesFilters(matchMap, payload) {
+			return false
+		}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@store-client/pkg/client/postgresql_changestream.go` around lines 403 - 405,
The current filter short-circuits by only calling w.matchesFilters(matchMap,
entry.newValues) which lets delete events (where entry.newValues == nil) bypass
field predicates; change the logic in the block around entry.newValues to: if
entry.newValues != nil use w.matchesFilters(matchMap, entry.newValues), else if
entry.oldValues != nil use w.matchesFilters(matchMap, entry.oldValues), else if
matchMap contains any non-operationType predicates return false (reject because
no payload to evaluate). Update the check that currently references
entry.newValues and w.matchesFilters to try oldValues as a fallback and enforce
rejection when neither payload exists but field predicates are present.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@store-client/pkg/client/postgresql_changestream.go`:
- Around line 403-405: The current filter short-circuits by only calling
w.matchesFilters(matchMap, entry.newValues) which lets delete events (where
entry.newValues == nil) bypass field predicates; change the logic in the block
around entry.newValues to: if entry.newValues != nil use
w.matchesFilters(matchMap, entry.newValues), else if entry.oldValues != nil use
w.matchesFilters(matchMap, entry.oldValues), else if matchMap contains any
non-operationType predicates return false (reject because no payload to
evaluate). Update the check that currently references entry.newValues and
w.matchesFilters to try oldValues as a fallback and enforce rejection when
neither payload exists but field predicates are present.

ℹ️ Review info

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 546bd49 and bb681ac.

📒 Files selected for processing (2)
  • store-client/pkg/client/postgresql_changestream.go
  • store-client/pkg/datastore/providers/postgresql/database_client.go
🚧 Files skipped from review as they are similar to previous changes (1)
  • store-client/pkg/datastore/providers/postgresql/database_client.go

@cbumb cbumb force-pushed the 728_nolint-cleanup-6 branch from 296cb3a to f7eb403 Compare March 2, 2026 03:02
@github-actions
Copy link

github-actions bot commented Mar 2, 2026

Merging this branch will decrease overall coverage

Impacted Packages Coverage Δ 🤖
github.com/nvidia/nvsentinel/janitor-provider/pkg/csp/kind 0.00% (ø)
github.com/nvidia/nvsentinel/store-client/pkg/client 5.88% (-0.11%) 👎
github.com/nvidia/nvsentinel/store-client/pkg/config 0.00% (ø)
github.com/nvidia/nvsentinel/store-client/pkg/datastore/providers/postgresql 5.07% (-0.03%) 👎

Coverage by file

Changed files (no unit tests)

Changed File Coverage Δ Total Covered Missed 🤖
github.com/nvidia/nvsentinel/janitor-provider/pkg/csp/kind/kind.go 0.00% (ø) 0 0 0
github.com/nvidia/nvsentinel/store-client/pkg/client/postgresql_changestream.go 0.30% (-0.05%) 2026 (+277) 6 2020 (+277) 👎
github.com/nvidia/nvsentinel/store-client/pkg/config/env_loader.go 0.00% (ø) 1650 (-28) 0 1650 (-28)
github.com/nvidia/nvsentinel/store-client/pkg/datastore/providers/postgresql/database_client.go 0.00% (ø) 4272 (+96) 0 4272 (+96)

Please note that the "Total", "Covered", and "Missed" counts above refer to code statements instead of lines of code. The value in brackets refers to the test coverage of that file in the old version of the code.

@github-actions
Copy link

github-actions bot commented Mar 2, 2026

Merging this branch will increase overall coverage

Impacted Packages Coverage Δ 🤖
github.com/nvidia/nvsentinel/store-client/pkg/client 6.31% (+0.31%) 👍

Coverage by file

Changed unit test files

  • github.com/nvidia/nvsentinel/store-client/pkg/client/postgresql_changestream_test.go

@github-actions
Copy link

github-actions bot commented Mar 2, 2026

🛡️ CodeQL Analysis

🚨 Found 1 security alert(s)

🔗 View details

@github-actions
Copy link

github-actions bot commented Mar 2, 2026

Merging this branch will decrease overall coverage

Impacted Packages Coverage Δ 🤖
github.com/nvidia/nvsentinel/plugins/mock-slurm-operator/pkg/controller 0.00% (ø)
github.com/nvidia/nvsentinel/plugins/slinky-drainer/pkg/controller 78.77% (-1.37%) 👎

Coverage by file

Changed files (no unit tests)

Changed File Coverage Δ Total Covered Missed 🤖
github.com/nvidia/nvsentinel/plugins/mock-slurm-operator/pkg/controller/node_controller.go 0.00% (ø) 0 0 0
github.com/nvidia/nvsentinel/plugins/slinky-drainer/pkg/controller/drainrequest_controller.go 78.77% (-1.37%) 146 115 (-2) 31 (+2) 👎

Please note that the "Total", "Covered", and "Missed" counts above refer to code statements instead of lines of code. The value in brackets refers to the test coverage of that file in the old version of the code.

Changed unit test files

  • github.com/nvidia/nvsentinel/plugins/slinky-drainer/pkg/controller/drainrequest_controller_test.go

@github-actions
Copy link

github-actions bot commented Mar 2, 2026

🛡️ CodeQL Analysis

🚨 Found 1 security alert(s)

🔗 View details

@github-actions
Copy link

github-actions bot commented Mar 4, 2026

Merging this branch changes the coverage (2 decrease, 1 increase)

Impacted Packages Coverage Δ 🤖
github.com/nvidia/nvsentinel/labeler 0.00% (ø)
github.com/nvidia/nvsentinel/labeler/pkg/initializer 0.00% (ø)
github.com/nvidia/nvsentinel/labeler/pkg/labeler 82.09% (ø)
github.com/nvidia/nvsentinel/store-client/pkg/datastore/providers/mongodb/watcher 12.73% (+0.19%) 👍
github.com/nvidia/nvsentinel/store-client/pkg/datastore/providers/postgresql 5.10% (-0.03%) 👎
github.com/nvidia/nvsentinel/store-client/pkg/storewatcher 11.74% (-0.24%) 👎

Coverage by file

Changed files (no unit tests)

Changed File Coverage Δ Total Covered Missed 🤖
github.com/nvidia/nvsentinel/labeler/main.go 0.00% (ø) 86 0 86
github.com/nvidia/nvsentinel/labeler/pkg/initializer/init.go 0.00% (ø) 33 0 33
github.com/nvidia/nvsentinel/labeler/pkg/labeler/labeler.go 82.09% (ø) 296 243 53
github.com/nvidia/nvsentinel/store-client/pkg/datastore/providers/mongodb/watcher/unmarshaller.go 16.40% (ø) 628 103 525
github.com/nvidia/nvsentinel/store-client/pkg/datastore/providers/postgresql/changestream.go 6.42% (ø) 4798 308 4490
github.com/nvidia/nvsentinel/store-client/pkg/datastore/providers/postgresql/datastore.go 5.19% (ø) 1157 60 1097
github.com/nvidia/nvsentinel/store-client/pkg/datastore/providers/postgresql/health_events.go 0.04% (ø) 2761 1 2760
github.com/nvidia/nvsentinel/store-client/pkg/datastore/providers/postgresql/pipeline_filter.go 10.57% (ø) 2290 242 2048
github.com/nvidia/nvsentinel/store-client/pkg/datastore/providers/postgresql/sql_filter_builder.go 14.32% (ø) 2318 332 1986
github.com/nvidia/nvsentinel/store-client/pkg/datastore/providers/postgresql/watcher_factory.go 8.53% (ø) 293 25 268
github.com/nvidia/nvsentinel/store-client/pkg/storewatcher/config.go 0.00% (ø) 96 0 96
github.com/nvidia/nvsentinel/store-client/pkg/storewatcher/watch_store.go 14.33% (ø) 2177 312 1865

Please note that the "Total", "Covered", and "Missed" counts above refer to code statements instead of lines of code. The value in brackets refers to the test coverage of that file in the old version of the code.

Changed unit test files

  • github.com/nvidia/nvsentinel/labeler/pkg/labeler/labeler_test.go
  • github.com/nvidia/nvsentinel/store-client/pkg/datastore/providers/mongodb/watcher/watch_store_test.go
  • github.com/nvidia/nvsentinel/store-client/pkg/datastore/providers/postgresql/database_client_test.go

@github-actions
Copy link

github-actions bot commented Mar 4, 2026

Merging this branch will increase overall coverage

Impacted Packages Coverage Δ 🤖
github.com/nvidia/nvsentinel/store-client/pkg/datastore/providers/mongodb/watcher 12.80% (+0.16%) 👍

Coverage by file

Changed files (no unit tests)

Changed File Coverage Δ Total Covered Missed 🤖
github.com/nvidia/nvsentinel/store-client/pkg/datastore/providers/mongodb/watcher/watch_store.go 14.50% (+0.26%) 2656 (+7) 385 (+8) 2271 (-1) 👍

Please note that the "Total", "Covered", and "Missed" counts above refer to code statements instead of lines of code. The value in brackets refers to the test coverage of that file in the old version of the code.

Changed unit test files

  • github.com/nvidia/nvsentinel/store-client/pkg/datastore/providers/mongodb/watcher/watch_store_test.go

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.

1 participant