Skip to content

Conversation

@jortel
Copy link
Contributor

@jortel jortel commented Sep 3, 2025

Summary by CodeRabbit

  • New Features

    • Added customizable error-wrapping to standardize and enrich addon error messages.
  • Bug Fixes

    • Converted unexpected panics into regular errors for improved stability and diagnostics.
    • Improved handling of missing references to avoid premature failures and provide clearer reset guidance.
    • Ensured identity lists are consistently populated when available, improving downstream behavior.

Signed-off-by: Jeff Ortel <[email protected]>
@coderabbitai
Copy link

coderabbitai bot commented Sep 3, 2025

Walkthrough

Adds an Adapter.Wrap field, uses fmt.Errorf to convert non-error panics into errors during Run's recovery, and wires Wrap in adapter construction. Adjusts task reference handling to use local ref.ID for API calls and wraps NotFound cases with contextual ResetError messages.

Changes

Cohort / File(s) Summary of changes
Adapter error wrapping & panic recovery
addon/adapter.go
Added exported field Wrap func(error, ...any) error to Adapter; imported fmt; changed Run's deferred recovery to convert non-error panics to error via fmt.Errorf("%#v", r) and pass through Wrap; initialized Wrap in newAdapter().
Task reference handling & error wrapping
addon/task.go
Replaced direct nil/empty guards with local ref variables for Application and Platform, using ref.ID for Get/List calls; missing-reference cases now return wrapped NotFound{ResetError{...}}; identities populated explicitly from API list results; Addon guard adjusted to return wrapped NotFound where applicable.

Sequence Diagram(s)

sequenceDiagram
  participant Caller
  participant Adapter
  participant Handler as Task/Handler
  participant WrapFn as Adapter.Wrap
  participant Fmt as fmt

  Caller->>Adapter: Run(task)
  Adapter->>Handler: Execute task
  Note over Handler,Adapter: panic occurs (r)
  Handler--xAdapter: panic r

  rect rgba(230,240,255,0.6)
    Adapter->>Adapter: recover() -> r
    alt r is error
      Adapter->>WrapFn: Wrap(r, context...)
      WrapFn-->>Adapter: wrapped error
    else r is non-error
      Adapter->>Fmt: Errorf("%#v", r)
      Fmt-->>Adapter: err
      Adapter->>WrapFn: Wrap(err, context...)
      WrapFn-->>Adapter: wrapped error
    end
  end

  Adapter-->>Caller: return error
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20–30 minutes

Possibly related PRs

Suggested reviewers

  • aufi

Poem

A hop, a wrap, a gentle catch—
When panics leap, we stitch the patch.
fmt hums truth into an error thread,
Adapter tucks the fear to bed.
Little rabbit nods, all safe ahead. 🐇✨


📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3f83de4 and dc5d19a.

📒 Files selected for processing (1)
  • addon/task.go (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • addon/task.go
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build

Pre-merge checks (1 passed, 1 warning, 1 inconclusive)

❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Description Check ⚠️ Warning The pull request has no description explaining the context or purpose of the changes, making it difficult to understand the intent and scope beyond the title and diff. Add a brief description that outlines why the Wrap function and panic recovery improvements were made, including the specific problems addressed and the high-level approach taken.
Title Check ❓ Inconclusive The current title is generic and uses vague phrasing (“Better error handling”) along with an emoji, which does not clearly or specifically convey the primary change introduced by this PR. Consider renaming the PR to a concise, descriptive sentence that highlights the key change (for example, “Wrap non-error panics as errors in Adapter and propagate Wrap to task handlers”) and remove the emoji for clarity.
✅ Passed checks (1 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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.

@jortel jortel changed the title 🐛 Ensure panic is logged. 🐛 Ensure addon panic is logged when not Error. Sep 3, 2025
@jortel jortel marked this pull request as ready for review September 5, 2025 13:48
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (3)
addon/adapter.go (3)

125-133: Make recovered panic messages clearer (avoid %#v).

%#v can add quotes or Go-syntax noise. Include the recovered value’s type and readable value.

-               err = fmt.Errorf("%#v", r)
+               err = fmt.Errorf("panic recovered: %T: %v", r, r)

7-11: Optionally capture stack trace on recovered panics.

Adding a stack to the error log makes postmortems faster.

Option A (preferred): log stack

 import (
-	"fmt"
+	"fmt"
+	"runtime/debug"
 	"os"
-			h.Log.Error(err, "Addon failed.")
+			if r != nil {
+				h.Log.Error(err, "Addon failed.", "panic", true, "stack", string(debug.Stack()))
+			} else {
+				h.Log.Error(err, "Addon failed.")
+			}

Option B (minimal): flag that it was a panic without the stack

-			h.Log.Error(err, "Addon failed.")
+			h.Log.Error(err, "Addon failed.", "panic", r != nil)

84-86: Exposing Wrap on Adapter—confirm intent or rename to reduce ambiguity.

Having both package-level Wrap and field Adapter.Wrap with the same name can be confusing. If this is meant for addon authors, consider ErrorWrap or similar; otherwise, drop it to keep the API surface small.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 692a0dd and fac5a7f.

📒 Files selected for processing (1)
  • addon/adapter.go (4 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
addon/adapter.go (1)
api/filter/error.go (1)
  • Errorf (20-23)
🔇 Additional comments (1)
addon/adapter.go (1)

170-171: LGTM: Wrap is properly wired into the adapter.

No issues with the initialization.

Copy link
Member

@aufi aufi left a comment

Choose a reason for hiding this comment

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

LGTM

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (4)
addon/task.go (4)

36-41: Guard missing Application ref to avoid Get(0)/Identity(0) calls

If the task has no application, this now issues Get(0) and Identity(0).List(). Please verify the client/server behavior for ID=0 and consider an explicit, contextual error instead to avoid confusing 404s or malformed paths.

 ref := h.task.Application
-if ref == nil {
-	ref = &api.Ref{}
-}
-r, err = h.richClient.Application.Get(ref.ID)
+if ref == nil || ref.ID == 0 {
+	return nil, fmt.Errorf("task %d has no application reference", h.task.ID)
+}
+r, err = h.richClient.Application.Get(ref.ID)
+if err != nil {
+	return nil, fmt.Errorf("get application id=%d: %w", ref.ID, err)
+}
@@
-identities, err := h.richClient.Application.Identity(ref.ID).List()
-if err != nil {
-	return
-}
+identities, err := h.richClient.Application.Identity(ref.ID).List()
+if err != nil {
+	return nil, fmt.Errorf("list identities for application id=%d: %w", ref.ID, err)
+}

Also applies to: 45-46


62-67: Similarly guard missing Platform ref to avoid Get(0)

Same concern as Application(): calling Get with ID=0. Suggest explicit error for clarity and to reduce noisy downstream calls.

 ref := h.task.Platform
-if ref == nil {
-	ref = &api.Ref{}
-}
-r, err = h.richClient.Platform.Get(ref.ID)
+if ref == nil || ref.ID == 0 {
+	return nil, fmt.Errorf("task %d has no platform reference", h.task.ID)
+}
+r, err = h.richClient.Platform.Get(ref.ID)
+if err != nil {
+	return nil, fmt.Errorf("get platform id=%d: %w", ref.ID, err)
+}

74-76: Empty addon name now flows into Get(name); verify behavior

With the prior guard removed, name=="" will call Addon.Get(""). Please confirm this yields a clean NotFound (and not a malformed URL or unintended list call). Optionally fail fast with context.

 name := h.task.Addon
+r, err = nil, nil
+if name == "" {
+	return nil, fmt.Errorf("task %d has no addon name", h.task.ID)
+}
 r, err = h.richClient.Addon.Get(name)
+if err != nil {
+	return nil, fmt.Errorf("get addon name=%q: %w", name, err)
+}

115-115: Confirm Wrap is nil-safe or guard before calling

If Wrap(nil) is not guaranteed to return nil, guard it. If it is nil-safe, current code is fine.

-err = Wrap(err)
+if err != nil {
+	err = Wrap(err)
+}
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between fac5a7f and 8e7ea5f.

📒 Files selected for processing (1)
  • addon/task.go (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
addon/task.go (2)
api/application.go (1)
  • Application (1325-1350)
api/base.go (1)
  • Ref (340-343)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: build
  • GitHub Check: test-unit

Signed-off-by: Jeff Ortel <[email protected]>
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Nitpick comments (3)
addon/task.go (3)

43-44: Guard against zero application ID.

Avoid a pointless GET with ID=0 and return a clear error.

-  r, err = h.richClient.Application.Get(ref.ID)
+  if ref.ID == 0 {
+    err = Wrap(&NotFound{
+      RestError: ResetError{
+        Resource: "application",
+        Reason:   "application ID missing.",
+      },
+    })
+    return
+  }
+  r, err = h.richClient.Application.Get(ref.ID)

47-59: Preallocate identities slice to avoid repeated reallocations.

Minor perf/readability improvement.

- r.Identities = []api.Ref{}
- identities, err := h.richClient.Application.Identity(ref.ID).List()
+ identities, err := h.richClient.Application.Identity(ref.ID).List()
   if err != nil {
     return
   }
- for _, identity := range identities {
-   r.Identities = append(
-     r.Identities,
-     api.Ref{
-       ID:   identity.ID,
-       Name: identity.Name,
-     })
- }
+ r.Identities = make([]api.Ref, 0, len(identities))
+ for _, identity := range identities {
+   r.Identities = append(r.Identities, api.Ref{
+     ID:   identity.ID,
+     Name: identity.Name,
+   })
+ }

72-73: Guard against zero platform ID.

Mirror the application check to avoid ID=0 calls.

-  r, err = h.richClient.Platform.Get(ref.ID)
+  if ref.ID == 0 {
+    err = Wrap(&NotFound{
+      RestError: ResetError{
+        Resource: "platform",
+        Reason:   "platform ID missing.",
+      },
+    })
+    return
+  }
+  r, err = h.richClient.Platform.Get(ref.ID)
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8e7ea5f and 3f83de4.

📒 Files selected for processing (1)
  • addon/task.go (3 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
addon/task.go (5)
addon/adapter.go (6)
  • Application (59-59)
  • Wrap (22-22)
  • NotFound (56-56)
  • ResetError (54-54)
  • Identity (63-63)
  • Platform (65-65)
binding/application.go (1)
  • Application (12-14)
api/error.go (1)
  • NotFound (84-87)
api/base.go (1)
  • Ref (340-343)
binding/identity.go (1)
  • Identity (8-10)
🪛 GitHub Check: vet
addon/task.go

[failure] 38-38:
github.com/konveyor/tackle2-hub/binding.NotFound struct literal uses unkeyed fields


[failure] 67-67:
github.com/konveyor/tackle2-hub/binding.NotFound struct literal uses unkeyed fields


[failure] 82-82:
github.com/konveyor/tackle2-hub/binding.NotFound struct literal uses unkeyed fields

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build

Signed-off-by: Jeff Ortel <[email protected]>
@jortel jortel changed the title 🐛 Ensure addon panic is logged when not Error. 🐛 Better error handling in addon adapter. Sep 9, 2025
@jortel jortel merged commit 6d2057a into konveyor:main Sep 9, 2025
17 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.

2 participants