Skip to content

feat(operator): expose structured triage actions - #108

Open
amwarrier wants to merge 6 commits into
mainfrom
codex/triage-run-actions
Open

feat(operator): expose structured triage actions#108
amwarrier wants to merge 6 commits into
mainfrom
codex/triage-run-actions

Conversation

@amwarrier

@amwarrier amwarrier commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

Summary of Changes

This PR updates the TriageRun SDK for structured actions.

  • action discovery returns {name, description} objects from Application.spec.triage.actions
  • run creation accepts lightweight {name} action references
  • run parsing exposes the same references and per-action status
  • compatibility readers accept the earlier map-shaped Application catalog and string-shaped TriageRun selections during a rolling upgrade
  • one TriageRun can still select multiple actions declared by the same Application

Jira: N/A

Test Plan

  • go test ./pkg/operator -run Triage -count=1
  • go vet ./...
  • golangci-lint run --timeout=5m --concurrency=4 --max-same-issues=20
  • go build -tags containers_image_openpgp ./cmd/wsm

Requirements

  • Lint clean (make lint equivalent commands passed)
  • Format clean (make fmt leaves no diff)
  • go.mod / go.sum remain unchanged by this PR
  • I/AI have tested the changes on this PR
  • Existing rolling-upgrade representations remain readable

Summary by CodeRabbit

  • New Features

    • Triage requests and runs now support multiple named actions.
    • Applications can list available triage actions with names and descriptions.
    • Triage results include per-action statuses, summaries, and execution results.
    • Omitted actions default to the standard action.
  • Bug Fixes

    • Improved validation for missing, duplicate, conflicting, or malformed actions and results.
    • Preserved compatibility with existing single-action requests and result formats.
    • Action listings are presented in a consistent order.

@amwarrier
amwarrier requested a review from a team as a code owner August 4, 2026 15:43
@coderabbitai

coderabbitai Bot commented Aug 4, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The triage API now supports multiple actions, lists actions from Applications, validates and normalizes action input, writes action arrays to TriageRuns, and parses per-action statuses while preserving legacy result fields.

Changes

Multi-action triage runs

Layer / File(s) Summary
Action contracts, discovery, and validation
pkg/operator/triage.go, pkg/operator/triage_test.go
The API adds structured action types, per-action status types, and ListTriageActions. Validation requires application names and rejects empty or duplicate actions. Application actions are sorted and validated.
Multi-action TriageRun creation
pkg/operator/triage.go, pkg/operator/triage_test.go
Creation defaults omitted actions to default and writes normalized action references to spec.actions. Tests cover default and explicit action arrays.
Per-action status parsing
pkg/operator/triage.go, pkg/operator/triage_test.go
Parsing reads structured actions, execution metadata, summaries, and results. Flattened results and the legacy status.results fallback remain supported.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Caller
  participant TriageRunRequest
  participant normalizeActions
  participant TriageRun
  Caller->>TriageRunRequest: provide Actions
  TriageRunRequest->>normalizeActions: validate and normalize action references
  normalizeActions->>TriageRun: write spec.actions
Loading

Possibly related PRs

  • wandb/wsm#104: Introduced the TriageRun SDK structures extended by this change.

Suggested reviewers: collinol

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title uses the required Conventional Commits format and clearly summarizes the structured triage action changes.
Description check ✅ Passed The description covers the change, tests, compatibility behavior, and completed requirements, with only minor template differences.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/triage-run-actions

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.

@amwarrier amwarrier added the release:minor Release: bump minor version (vX.Y+1.0) label Aug 4, 2026
@amwarrier amwarrier changed the title feat(operator): Support multiple triage actions feat(operator): support multiple triage actions Aug 4, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

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 (2)
pkg/operator/triage.go (2)

187-193: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Wait for the operator before submitting the v2 CR.

Lines 187-193 submit the v2 TriageRun without WaitForOperator. Call WaitForOperator before the submission and add a test that proves the wait completes first.

As per coding guidelines, pkg/operator/**/*.go requires Wait for the operator webhook CA bundle to become non-empty before applying the v2 CR; do not skip WaitForOperator readiness handling.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/operator/triage.go` around lines 187 - 193, Update the v2 TriageRun
submission flow around normalizedTriageActions and
dynamicClient.Resource(...).Create to call WaitForOperator first, ensuring the
operator webhook CA bundle is non-empty before creating the CR. Preserve the
existing create behavior after readiness completes, and add a test verifying
WaitForOperator finishes before the v2 TriageRun submission.

Source: Coding guidelines


630-650: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Use server-side apply for the v2 TriageRun.

createTriageRun currently sends FieldManager: "wsm" in CreateOptions, which is still a normal create. For v2 CRs, call Apply() with metav1.ApplyOptions{FieldManager: "wsm", Force: true}, supply a concrete collision-safe object name, and ensure RBAC grants create/patch for the triageruns resource.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/operator/triage.go` around lines 630 - 650, Update the v2 TriageRun
creation flow in createTriageRun to use server-side Apply with
metav1.ApplyOptions{FieldManager: "wsm", Force: true} instead of CreateOptions.
Provide a concrete collision-safe metadata.name rather than relying on
generateName, and update RBAC for the triageruns resource to grant both create
and patch verbs.

Source: Coding guidelines

🧹 Nitpick comments (2)
pkg/operator/triage_test.go (2)

62-84: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Retain a legacy Action creation test.

Lines 62-84 replace singular input coverage with an Actions test. Add a request with Action: "dependencies" and assert that spec.actions contains only "dependencies". This protects the public source-compatibility path.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/operator/triage_test.go` around lines 62 - 84, Add a separate test
covering the legacy singular Action field in createTriageRun, using Action:
"dependencies" and verifying the created object's spec.actions contains only
"dependencies". Keep TestCreateTriageRunPreservesExplicitActions to cover the
plural Actions input unchanged.

268-314: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Test the multi-action status path.

Lines 268-314 use one selected action and one action status. Add two spec.actions values and two status.actionStatuses entries with distinct results. Assert ActionStatuses, flattened Results order, and an empty legacy Action.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/operator/triage_test.go` around lines 268 - 314, Expand the triage test
fixture to define two spec.actions and two status.actionStatuses with distinct
result data, using the existing run objects and listTriageRuns flow. Update
assertions to verify both ActionStatuses in order, flattened Results preserve
the expected action/result order, and the legacy Action field remains empty.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@pkg/operator/triage.go`:
- Around line 187-193: Update the v2 TriageRun submission flow around
normalizedTriageActions and dynamicClient.Resource(...).Create to call
WaitForOperator first, ensuring the operator webhook CA bundle is non-empty
before creating the CR. Preserve the existing create behavior after readiness
completes, and add a test verifying WaitForOperator finishes before the v2
TriageRun submission.
- Around line 630-650: Update the v2 TriageRun creation flow in createTriageRun
to use server-side Apply with metav1.ApplyOptions{FieldManager: "wsm", Force:
true} instead of CreateOptions. Provide a concrete collision-safe metadata.name
rather than relying on generateName, and update RBAC for the triageruns resource
to grant both create and patch verbs.

---

Nitpick comments:
In `@pkg/operator/triage_test.go`:
- Around line 62-84: Add a separate test covering the legacy singular Action
field in createTriageRun, using Action: "dependencies" and verifying the created
object's spec.actions contains only "dependencies". Keep
TestCreateTriageRunPreservesExplicitActions to cover the plural Actions input
unchanged.
- Around line 268-314: Expand the triage test fixture to define two spec.actions
and two status.actionStatuses with distinct result data, using the existing run
objects and listTriageRuns flow. Update assertions to verify both ActionStatuses
in order, flattened Results preserve the expected action/result order, and the
legacy Action field remains empty.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 4a6107f1-c600-421d-9b98-f199b6a97041

📥 Commits

Reviewing files that changed from the base of the PR and between 7fb59e5 and 3831ac7.

📒 Files selected for processing (2)
  • pkg/operator/triage.go
  • pkg/operator/triage_test.go

@amwarrier amwarrier changed the title feat(operator): support multiple triage actions feat(operator): expose structured triage actions Aug 4, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

Caution

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

⚠️ Outside diff range comments (1)
pkg/operator/triage.go (1)

200-200: 🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

Use server-side apply for the v2 TriageRun.

The test intercepts "create" and requires that request to set the generated name. This confirms that the modified v2 creation path uses Create, not server-side apply with field manager wsm.

  • pkg/operator/triage.go#L200-L200: apply the v2 TriageRun with server-side apply and FieldManager: "wsm". Rework name generation if necessary so the apply request has a stable object name.
  • pkg/operator/triage_test.go#L24-L24: replace the create reactor with a patch reactor and assert the apply patch type and field manager.

As per coding guidelines, pkg/operator/**/*.go must “Apply v2 CRs with server-side apply and FieldManager: "wsm".”

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/operator/triage.go` at line 200, Update the v2 TriageRun creation flow in
pkg/operator/triage.go at lines 200-200 to use server-side apply with
FieldManager set to "wsm", ensuring the applied object has a stable generated
name. Update pkg/operator/triage_test.go at lines 24-24 to intercept a patch
instead of a create, and assert the apply patch type and "wsm" field manager.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@pkg/operator/triage.go`:
- Around line 514-529: Reject empty action selections and names: in
pkg/operator/triage.go lines 514-529, make the parser error for an empty action
array and for object or string names that are empty after trimming whitespace;
in lines 653-663, distinguish a non-nil empty Actions slice from omitted Actions
and reject the explicit empty selection while preserving omitted-action default
behavior. Add validation and parsing tests covering spec.actions as [], {}, "",
empty arrays, and whitespace-only names.
- Around line 286-288: Update the legacy action handling in the item-to-action
conversion path to capture and propagate the error returned by
unstructured.NestedString when reading “description” from actionMap. Return a
contextual error matching the array-shaped catalog behavior instead of silently
accepting an empty description.

---

Outside diff comments:
In `@pkg/operator/triage.go`:
- Line 200: Update the v2 TriageRun creation flow in pkg/operator/triage.go at
lines 200-200 to use server-side apply with FieldManager set to "wsm", ensuring
the applied object has a stable generated name. Update
pkg/operator/triage_test.go at lines 24-24 to intercept a patch instead of a
create, and assert the apply patch type and "wsm" field manager.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 5c6198ad-f8ba-4901-b5fa-adb4c5ed60e8

📥 Commits

Reviewing files that changed from the base of the PR and between 3831ac7 and d29db41.

📒 Files selected for processing (2)
  • pkg/operator/triage.go
  • pkg/operator/triage_test.go

Comment thread pkg/operator/triage.go Outdated
Comment thread pkg/operator/triage.go
Comment thread pkg/operator/triage.go Outdated

// Action is retained for source compatibility with clients of the initial
// single-action SDK. New callers should use Actions; setting both is invalid.
Action string `json:"action,omitempty"`

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Does this need to be backwards compatible for something that we haven't implemented yet? I think it should just support a list of actions, that list can be of length 1. We don't need to support both a list and a single action

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

my bad. removed Action

Comment thread pkg/operator/triage.go

// ListTriageActions returns the sorted action metadata declared by one
// Application.
func ListTriageActions(ctx context.Context, namespace, applicationName string) ([]TriageAction, error) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This function isn't used anywhere in wsm? Is this for watchtower? You also have a function called listTriageActions (lowercase l) at line 222, that's super confusing. Which function is supposed to be here?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

renamed it to listTriageActionsWithClient

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

ListTriageActions is invoked by watchtower when the UI check loads.

Comment thread pkg/operator/triage.go Outdated
ApplicationName string `json:"applicationName"`
Actions []TriageActionReference `json:"actions"`
// Action mirrors the selected action for legacy single-action consumers.
Action string `json:"action,omitempty"`

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Same here, can remove singular Action.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

removed

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

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 (1)
pkg/operator/triage.go (1)

194-194: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Add readiness wait before creating the v2 TriageRun.

The create path uses FieldManager: "wsm", but CreateTriageRun calls Create directly without waiting for the operator. Add WaitForOperator before the create call so server-side apply is applied only after the webhook CA bundle is ready, as required for pkg/operator/**/*.go.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/operator/triage.go` at line 194, In the v2 TriageRun creation flow
surrounding normalizedTriageActions, call WaitForOperator before CreateTriageRun
so the operator and webhook CA bundle are ready before the FieldManager "wsm"
server-side apply occurs. Preserve the existing action normalization and create
behavior after readiness succeeds.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@pkg/operator/triage.go`:
- Line 194: In the v2 TriageRun creation flow surrounding
normalizedTriageActions, call WaitForOperator before CreateTriageRun so the
operator and webhook CA bundle are ready before the FieldManager "wsm"
server-side apply occurs. Preserve the existing action normalization and create
behavior after readiness succeeds.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 4697a6d6-a202-4daa-843e-df3b12db6f63

📥 Commits

Reviewing files that changed from the base of the PR and between d29db41 and 14b555e.

📒 Files selected for processing (2)
  • pkg/operator/triage.go
  • pkg/operator/triage_test.go

@amwarrier
amwarrier requested a review from collinol August 10, 2026 15:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

release:minor Release: bump minor version (vX.Y+1.0)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants