Skip to content

Conversation

jortel
Copy link
Contributor

@jortel jortel commented Aug 12, 2025

Filter apps on platform id: GET /applications?filter=platform.id=1

Closes #872

Add platform to the task dashboard.

Closes #875

Add list of manifest (refs) to application.

Closes #876

Summary by CodeRabbit

  • New Features

    • Applications listing API now supports server-side filtering by platform ID.
    • Applications listing now includes manifest references for each application.
    • Task dashboard responses now include platform information for each task when available.
  • Documentation

    • API docs updated to describe the platform ID filter and the new manifest and platform fields in responses.

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

coderabbitai bot commented Aug 12, 2025

Walkthrough

Adds server-side filtering by platform.id to the Applications List endpoint, exposes application manifests in the List response, and adds Platform to the TaskDashboard API representation.

Changes

Cohort / File(s) Summary
Applications — filtering & manifests
api/application.go
Add qf filter for platform.id mapped to PlatformId and applied via filter.Where(db); extend List query to join manifests, select ManifestId, build model.Manifest entries, and populate new public Manifests []Ref on API Application.
Task dashboard — platform field
api/task.go
Add Platform *Ref field to TaskDashboard and populate it in TaskDashboard.With (r.Platform = r.refPtr(m.PlatformID, m.Platform)).

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant API as Applications API (List)
  participant Filter as qf Filter Builder
  participant DB as Database
  participant Manifest as Manifests join

  Client->>API: GET /applications?filter=platform.id=18
  API->>Filter: parse/build filter (platform.id → PlatformId literal)
  Filter-->>API: filter.Where(db) clause
  API->>DB: Query with applied where-clause and join manifests
  DB-->>API: Filtered application rows + manifest IDs
  API->>Manifest: build manifest refs from rows
  API-->>Client: 200 OK (JSON list with manifests)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~15 minutes

Assessment against linked issues

Objective Addressed Explanation
Filtering by platform.id in Applications List (#872)
Platform included in task dashboard (#875)

Assessment against linked issues: Out-of-scope changes

Code Change Explanation
Added Manifests []Ref field and manifest join/processing (api/application.go) The linked issues request filtering and adding platform to task dashboard; introducing manifests and new public API field is not mentioned and appears unrelated to those objectives.

I twitch my whiskers at the code's new tracks,
Platform IDs and manifests in stacks,
I hop through rows and nudge the facts,
A tidy patch with rabbit pacts —
Hooray for hops and tiny snacks 🐰✨

✨ 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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
api/application.go (1)

149-151: Document the filter query parameter in the swagger comments.

You list supported filters, but the query parameter itself isn’t declared. Add a @param line so the filter shows up in generated API docs and clients.

Consider adding this line near the other params for the List endpoint:

// @param filter query string false "Filter expression. Example: platform.id=18"

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a1f66e2 and 9e8e10b.

📒 Files selected for processing (1)
  • api/application.go (4 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
api/application.go (3)
api/filter/filter.go (3)
  • New (16-27)
  • Assert (371-375)
  • Field (223-225)
api/filter/lexer.go (1)
  • LITERAL (23-23)
api/filter/error.go (1)
  • Error (6-8)
🔇 Additional comments (2)
api/application.go (2)

10-10: Import of filter package (qf) looks correct and scoped.

Aliasing the filter package as qf is clear and avoids naming collisions with the local variable named filter later. No issues.


243-243: Filter applied to the composed query — placement is fine.

Applying the filter after joins and before pagination is correct. Once the rename maps to a real column/expression, this should work as intended.

After fixing the rename target, verify behavior quickly with a minimal manual check (assuming a dev DB exists):

  • GET /applications?filter=platform.id=1 returns only apps with PlatformID=1
  • GET /applications?filter=platform.id=999999 returns empty list

If you want, I can draft an integration test stub for this endpoint.

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

🔭 Outside diff range comments (1)
api/task.go (1)

103-106: Bug: wrong error is returned when injectFiles fails

On failure, the handler returns result.Error instead of the local err from injectFiles, masking the real cause.

Apply this diff:

-    err := r.injectFiles(h.DB(ctx))
-    if err != nil {
-      _ = ctx.Error(result.Error)
-      return
-    }
+    if err := r.injectFiles(h.DB(ctx)); err != nil {
+      _ = ctx.Error(err)
+      return
+    }
🧹 Nitpick comments (3)
api/task.go (3)

239-239: Swagger route for Queued report is incorrect

The handler is registered at TasksReportQueueRoot => /tasks/report/queue, but the doc says /tasks.

Apply this diff:

-// @router /tasks [get]
+// @router /tasks/report/queue [get]

309-309: Swagger route for Dashboard report is incorrect

The handler is registered at TasksReportDashboardRoot => /tasks/report/dashboard, but the doc says /tasks.

Apply this diff:

-// @router /tasks [get]
+// @router /tasks/report/dashboard [get]

3-11: Use os.ReadFile instead of deprecated io/ioutil.ReadFile

io/ioutil is deprecated; prefer os.ReadFile.

Apply these diffs:

-import (
-  "fmt"
-  "io/ioutil"
-  "net/http"
+import (
+  "fmt"
+  "net/http"
+  "os"
-    b, nErr := ioutil.ReadFile(m.Path)
+    b, nErr := os.ReadFile(m.Path)

Also applies to: 915-919

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9e8e10b and 27fbb33.

📒 Files selected for processing (1)
  • api/task.go (2 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
api/task.go (6)
addon/adapter.go (1)
  • Platform (64-64)
migration/v18/model/platform.go (1)
  • Platform (15-24)
model/pkg.go (2)
  • Platform (37-37)
  • Ref (57-57)
migration/json/fields.go (1)
  • Ref (9-12)
api/base.go (1)
  • Ref (340-343)
migration/v13/model/core.go (1)
  • Ref (178-181)
⏰ 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). (3)
  • GitHub Check: test-unit
  • GitHub Check: build
  • GitHub Check: vet
🔇 Additional comments (2)
api/task.go (2)

1009-1013: Add Platform to TaskDashboard: LGTM

The new Platform field mirrors Task.Platform and uses the same JSON/YAML tags. This keeps the dashboard representation consistent with Task and enables clients to access platform metadata directly.


1015-1024: Populate TaskDashboard.Platform consistently: LGTM

Using r.refPtr(m.PlatformID, m.Platform) matches how Application is handled and aligns with existing Task.With() behavior. Upstream DB query already joins Platform, so name resolution will work as with Application.

Signed-off-by: Jeff Ortel <[email protected]>
@jortel jortel changed the title ✨ Filter apps on platform id. ✨ AI updates. Aug 12, 2025
@jortel jortel changed the title ✨ AI updates. ✨ AI updates for platform awareness. Aug 12, 2025
@jortel jortel changed the title ✨ AI updates for platform awareness. ✨ API updates for platform awareness. Aug 12, 2025
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)
api/application.go (4)

149-151: Clarify filter usage in swagger doc with an inline example

Add a minimal example so users know the exact querystring format.

-// @description filters:
-// @description - platform.id
+// @description filters:
+// @description - platform.id (e.g. GET /applications?filter=platform.id=1)

179-188: SQLite-specific alias in WHERE: document intent to prevent future confusion

Using SELECT aliases in WHERE is valid in SQLite (non-standard elsewhere). Given the repo uses SQLite, this is acceptable. Recommend adding an explanatory comment to avoid “fixes” that break it later.

 filter, err := qf.New(ctx,
   []qf.Assert{
     {Field: "platform.id", Kind: qf.LITERAL},
   })
 if err != nil {
   _ = ctx.Error(err)
   return
 }
- filter = filter.Renamed("platform.id", "PlatformId")
+ // Note: SQLite supports using SELECT column aliases in WHERE clauses (non-standard).
+ // Mapping "platform.id" -> "PlatformId" relies on that behavior.
+ filter = filter.Renamed("platform.id", "PlatformId")

245-246: Minor: Apply filters before ORDER for readability

Functionally equivalent in GORM, but placing WHERE before ORDER improves readability and avoids surprises if future logic adds GROUP BY/HAVING.

- db = db.Order("a.ID")
- db = filter.Where(db)
+ // Apply filters before ordering for clarity.
+ db = filter.Where(db)
+ db = db.Order("a.ID")

1411-1414: Optional: Sort manifests for stable API output

Map iteration order is non-deterministic; sort by ID for consistent JSON. sort is already imported.

 r.Manifests = []Ref{}
 for _, mf := range m.Manifest {
   r.Manifests = append(r.Manifests, Ref{ID: mf.ID})
 }
+// Ensure stable ordering.
+sort.Slice(r.Manifests, func(i, j int) bool { return r.Manifests[i].ID < r.Manifests[j].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 27fbb33 and 4fc014a.

📒 Files selected for processing (1)
  • api/application.go (11 hunks)
🧰 Additional context used
🧠 Learnings (4)
📚 Learning: 2025-07-09T11:55:52.155Z
Learnt from: jortel
PR: konveyor/tackle2-hub#849
File: test/api/application/manifest_test.go:33-33
Timestamp: 2025-07-09T11:55:52.155Z
Learning: The test `TestAppManifestGet` in test/api/application/manifest_test.go is intentionally designed to test the application-scoped manifest API functionality. It deliberately uses `Application.Manifest(application.ID)` for operations that are supported (Create, Get) while using `RichClient.Manifest.Delete` for cleanup operations that are not supported by the application-scoped API.

Applied to files:

  • api/application.go
📚 Learning: 2025-07-09T11:54:43.934Z
Learnt from: jortel
PR: konveyor/tackle2-hub#849
File: test/api/application/manifest_test.go:33-33
Timestamp: 2025-07-09T11:54:43.934Z
Learning: In test/api/application/manifest_test.go, the application-scoped manifest API (created via Application.Manifest(application.ID)) does not support delete operations. Delete operations must use the global RichClient.Manifest.Delete method. This explains why cleanup code uses RichClient.Manifest.Delete(r.ID) instead of the application-scoped Manifest variable.

Applied to files:

  • api/application.go
📚 Learning: 2025-08-12T17:51:09.657Z
Learnt from: jortel
PR: konveyor/tackle2-hub#874
File: api/application.go:179-188
Timestamp: 2025-08-12T17:51:09.657Z
Learning: SQLite supports using SELECT column aliases in WHERE clauses as a non-standard extension, unlike most other database systems (PostgreSQL, MySQL, SQL Server, Oracle). This means filter.Renamed() mappings to SELECT aliases are valid in SQLite-based applications like tackle2-hub.

Applied to files:

  • api/application.go
📚 Learning: 2025-08-12T17:51:09.657Z
Learnt from: jortel
PR: konveyor/tackle2-hub#874
File: api/application.go:179-188
Timestamp: 2025-08-12T17:51:09.657Z
Learning: SQLite supports using SELECT column aliases in WHERE clauses, which is a non-standard SQL extension that differs from most other database systems like MySQL, PostgreSQL, etc. This means filter.Renamed() mappings to SELECT aliases are valid in SQLite-based applications.

Applied to files:

  • api/application.go
🧬 Code Graph Analysis (1)
api/application.go (7)
api/filter/filter.go (3)
  • New (16-27)
  • Assert (371-375)
  • Field (223-225)
api/filter/lexer.go (1)
  • LITERAL (23-23)
api/filter/error.go (1)
  • Error (6-8)
api/manifest.go (1)
  • Manifest (334-339)
migration/v18/model/platform.go (1)
  • Manifest (7-13)
model/pkg.go (2)
  • Manifest (34-34)
  • Ref (57-57)
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). (3)
  • GitHub Check: test-unit
  • GitHub Check: build
  • GitHub Check: vet
🔇 Additional comments (8)
api/application.go (8)

10-10: Import qf alias: LGTM

Brings in the filter package with an alias that matches subsequent usage.


205-205: M.ManifestId: LGTM

Struct field aligns with the SELECT alias and downstream usage.


227-227: Projection of mf.ID as ManifestId: LGTM

Alias matches M.ManifestId and supports the builder aggregation.


243-243: LEFT JOIN Manifest: LGTM

Join matches the projection and aggregation. The maps in the builder mitigate row multiplication from joins.


257-257: Manifests aggregation map: LGTM

Pattern mirrors identities/contributors/assessments aggregation.


303-307: Collect manifest refs: LGTM

Correctly guards against zero IDs and dedupes via map.


1340-1340: API field Manifests []Ref: LGTM

Matches the new list behavior and uses the standard Ref type for related resources.


324-326: Verify model.Application field name for manifests
I wasn’t able to locate the Application struct in the model package to confirm whether the slice field is named Manifest or Manifests. Please ensure that:

  • model.Application defines a field
    Manifest []model.Manifest
    (singular) if you intend to use app.Manifest,
    or
    Manifests []model.Manifest
    (plural) if you need to update the loop to app.Manifests = append(app.Manifests, m).

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.

Application manifest refs. Platform included in task dashboard. Application filtering
2 participants