Skip to content

fix: Unify code responsible for upserting resources from sync subcommand#53

Merged
dacbd merged 7 commits intomainfrom
dacbd/unify-upsert-to-ctrlplane
Feb 15, 2026
Merged

fix: Unify code responsible for upserting resources from sync subcommand#53
dacbd merged 7 commits intomainfrom
dacbd/unify-upsert-to-ctrlplane

Conversation

@dacbd
Copy link
Collaborator

@dacbd dacbd commented Feb 15, 2026

Summary by CodeRabbit

  • Refactor
    • Consolidated resource upsert logic into a centralized shared utility used by all cloud provider sync commands (AWS, Azure, Google, GitHub, Kubernetes).
    • Removed duplicated in-file upsert helpers; sync flows now delegate to the shared upsert utility.
    • Commands now ensure a non-empty provider name (generate a default when none supplied) before upserting resources.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 15, 2026

📝 Walkthrough

Walkthrough

Consolidates per-command resource upsert logic by removing local upsertToCtrlplane helpers and replacing them with a centralized exported UpsertResources(ctx, resources, name) in internal/common; updates imports across many sync commands and introduces default provider-name fallback where needed.

Changes

Cohort / File(s) Summary
AWS Sync Commands
cmd/ctrlc/root/sync/aws/eks/eks.go, cmd/ctrlc/root/sync/aws/networks/networks.go, cmd/ctrlc/root/sync/aws/rds/rds.go
Removed local upsertToCtrlplane helpers; call ctrlp.UpsertResources(ctx, allResources, name); replaced resourceprovider/viper imports with ctrlp "github.com/ctrlplanedev/cli/internal/common".
Azure Sync Commands
cmd/ctrlc/root/sync/azure/aks/aks.go, cmd/ctrlc/root/sync/azure/networks/networks.go
Replaced local upsert flow with ctrlp.UpsertResources(...); removed local helper and resourceprovider/viper imports; propagate returned error from centralized call.
Google Sync Commands
cmd/ctrlc/root/sync/google/bigtable/bigtable.go, .../google/buckets/buckets.go, .../google/cloudrun/cloudrun.go, .../google/cloudsql/cloudsql.go, .../google/gke/gke.go, .../google/networks/networks.go, .../google/redis/redis.go, .../google/secrets/secrets.go, .../google/vms/vms.go
Centralized upsert via ctrlp.UpsertResources(...); removed per-file upsertToCtrlplane helpers and viper/resourceprovider usage; added default provider-name fallback (usually based on project) where missing; minor example/text formatting tweaks.
GitHub Sync Commands
cmd/ctrlc/root/sync/github/pullrequests.go
Switched from in-file upsert helper to ctrlp.UpsertResources(...); added provider-name defaulting when not provided; removed viper and resourceprovider dependencies; new call uses pointer name *string.
Kubernetes Sync Command
cmd/ctrlc/root/sync/kubernetes/kubernetes.go
Replaced resource-provider construction and per-file UpsertResource calls with ctrlp.UpsertResources(...); added top-level ctx propagation through RunE; removed local helper and related imports.
Internal Common Package
internal/common/common.go
Added exported UpsertResources(ctx context.Context, resources []api.ResourceProviderResource, name *string) error which reads config (viper), constructs API client and resource provider, performs the upsert, logs status, and returns errors.

Sequence Diagram(s)

sequenceDiagram
    participant CLI as CLI command
    participant CTRL as ctrlp.UpsertResources
    participant API as CtrlPlane API (client)
    CLI->>CTRL: UpsertResources(ctx, resources, name)
    CTRL->>API: build client (url, api-key, workspace)
    CTRL->>API: perform UpsertResources request
    API-->>CTRL: response (status / error)
    CTRL-->>CLI: return error or nil
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Possibly related PRs

  • aws/az network scans #26: Centralizes resource upserts into internal/common.UpsertResources and removes local upsertToCtrlplane helpers across sync commands.

Poem

🐰
Hopping through code with a twitch of my nose,
I gathered stray upserts in neat little rows.
One path to the plane, no helpers astray,
The rabbit declares: consolidated today! 🥕✨

🚥 Pre-merge checks | ✅ 3 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 64.52% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ 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 accurately summarizes the main change: unifying duplicated upsert logic across multiple sync command implementations into a single centralized function.
Merge Conflict Detection ✅ Passed ✅ No merge conflicts detected when merging into main

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

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch dacbd/unify-upsert-to-ctrlplane

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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: 3

🤖 Fix all issues with AI agents
In `@cmd/ctrlc/root/sync/google/cloudrun/cloudrun.go`:
- Around line 126-156: This code inlines resource upsert logic in cloudrun.go
(using resourceprovider.New and rp.UpsertResource) instead of using the unified
ctrlp.UpsertResources helper and also calls
cliutil.HandleResponseOutput/Println; fix by migrating this command to call
ctrlp.UpsertResources like the other sync commands (remove the manual ctrlplane
client creation, resourceprovider.New, rp.UpsertResource, fmt.Println and direct
logging) or alternatively update ctrlp.UpsertResources to return the full
response so this command can call ctrlp.UpsertResources and then pass that
response to cliutil.HandleResponseOutput; choose one approach and update usages
accordingly to keep behavior consistent with other sync commands.
- Line 154: Remove the debug print that dumps the HTTP response by deleting the
fmt.Println(upsertResp) call; rely on the existing structured logger that
already records the status of the upsert response (leave the structured log call
intact) so no raw response is printed to stdout and sensitive/internal fields
aren't exposed.

In `@internal/common/common.go`:
- Around line 13-16: The function UpsertResources dereferences the pointer
parameter name without a nil check causing a potential panic; modify
UpsertResources to first check if name == nil and return a descriptive error
(e.g., "name is nil") before checking *name == "" so you never dereference a nil
pointer, and keep the existing empty-string error path (check name == nil ||
*name == "" and return appropriate errors) to locate the change look for the
UpsertResources(ctx context.Context, resources []api.ResourceProviderResource,
name *string) signature.
🧹 Nitpick comments (4)
internal/common/common.go (1)

18-20: No validation of required Viper config values.

If url, api-key, or workspace are empty/unset, the function will proceed and fail with a potentially confusing downstream error. Consider validating these early with a clear message, especially since this is the centralized path for all providers now.

cmd/ctrlc/root/sync/aws/networks/networks.go (1)

70-72: Remove leftover commented-out code.

These commented-out viper lines are remnants of the old upsert logic and are no longer needed.

-				//apiURL := viper.GetString("url")
-				//apiKey := viper.GetString("api-key")
-				//workspaceId := viper.GetString("workspace")
-
cmd/ctrlc/root/sync/google/cloudsql/cloudsql.go (1)

222-228: Inconsistent default provider name format across sync commands.

This file uses google-cloudsql-{project} (no project- infix), while other Google sync commands (networks, vms, bigtable, gke, buckets) use the pattern google-{service}-project-{project}. Consider aligning for consistency.

Suggested fix
-		*providerName = fmt.Sprintf("google-cloudsql-%s", *project)
+		*providerName = fmt.Sprintf("google-cloudsql-project-%s", *project)
cmd/ctrlc/root/sync/kubernetes/kubernetes.go (1)

122-136: Inconsistent context usage: context.Background() vs ctx.

Lines 124 and 134 pass context.Background() to processNamespace and processDeployment, while the rest of the function consistently uses the ctx variable from line 81. Use ctx everywhere for consistency, even though the parameter is currently unused in those functions.

♻️ Proposed fix
 			for _, namespace := range namespaces.Items {
-				resource := processNamespace(context.Background(), clusterName, namespace)
+				resource := processNamespace(ctx, clusterName, namespace)
 				resources = append(resources, resource)
 			}
 			for _, deployment := range deployments.Items {
-				resource := processDeployment(context.Background(), clusterName, deployment)
+				resource := processDeployment(ctx, clusterName, deployment)
 				resources = append(resources, resource)
 			}

@dacbd
Copy link
Collaborator Author

dacbd commented Feb 15, 2026

@coderabbitai review

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 15, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

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

🤖 Fix all issues with AI agents
In `@internal/common/common.go`:
- Around line 32-38: The UpsertResource caller currently ignores non-2xx HTTP
responses: after calling SetResourceProviderResources and getting upsertResp,
check the HTTP status code on upsertResp (e.g., upsertResp.StatusCode or
upsertResp.Status) and return an error for unexpected codes (match the existing
pattern used in internal/api/providers/resource.go — for example if
resp.StatusCode() != http.StatusAccepted { return fmt.Errorf("upsert resources
failed: status %d", resp.StatusCode()) }); keep the logging of the response but
ensure non-success status codes cause UpsertResource to return a descriptive
error instead of nil.

Comment on lines +32 to +38
upsertResp, err := rp.UpsertResource(ctx, resources)
if err != nil {
return fmt.Errorf("failed to upsert resources: %w", err)
}

log.Info("Response from upserting resources", "status", upsertResp.Status)
return nil
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

ast-grep --pattern $'func ($_, $_) UpsertResource($_, $_) ($_, $_) {
  $$$
}'

Repository: ctrlplanedev/cli

Length of output: 42


🏁 Script executed:

rg -A 10 "func.*UpsertResource" --type go

Repository: ctrlplanedev/cli

Length of output: 1589


🏁 Script executed:

sed -n '1,150p' pkg/resourceprovider/resourceprovider.go | tail -100

Repository: ctrlplanedev/cli

Length of output: 2794


🏁 Script executed:

rg -A 20 "func (r \*ResourceProvider) UpsertResource" pkg/resourceprovider/resourceprovider.go

Repository: ctrlplanedev/cli

Length of output: 42


🏁 Script executed:

rg -B 5 -A 15 "SetResourceProviderResources" pkg/resourceprovider/resourceprovider.go

Repository: ctrlplanedev/cli

Length of output: 958


🏁 Script executed:

rg "SetResourceProviderResources" --type go

Repository: ctrlplanedev/cli

Length of output: 6003


🏁 Script executed:

rg -B 2 -A 5 "SetResourceProviderResourcesWithResponse" internal/api/providers/resource.go cmd/ctrlc/root/sync/salesforce/common/util.go

Repository: ctrlplanedev/cli

Length of output: 1305


🏁 Script executed:

sed -n '1,50p' internal/common/common.go

Repository: ctrlplanedev/cli

Length of output: 1110


Check HTTP status code before returning nil.

SetResourceProviderResources returns (*http.Response, error) without validating status codes. Non-2xx responses won't set err, so UpsertResource returns them unchanged. The caller logs the status but always returns nil, causing 4xx/5xx responses to silently succeed.

Other code in the repo (e.g., internal/api/providers/resource.go) validates status codes explicitly: if resp.StatusCode() != http.StatusAccepted { return fmt.Errorf(...) }. Apply the same validation in UpsertResource.

🤖 Prompt for AI Agents
In `@internal/common/common.go` around lines 32 - 38, The UpsertResource caller
currently ignores non-2xx HTTP responses: after calling
SetResourceProviderResources and getting upsertResp, check the HTTP status code
on upsertResp (e.g., upsertResp.StatusCode or upsertResp.Status) and return an
error for unexpected codes (match the existing pattern used in
internal/api/providers/resource.go — for example if resp.StatusCode() !=
http.StatusAccepted { return fmt.Errorf("upsert resources failed: status %d",
resp.StatusCode()) }); keep the logging of the response but ensure non-success
status codes cause UpsertResource to return a descriptive error instead of nil.

@dacbd dacbd merged commit 7b70937 into main Feb 15, 2026
4 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.

1 participant