Skip to content

(feat) Live Diff Workflow#116

Draft
susanhooks wants to merge 4 commits into
mainfrom
sh/add-diff-button
Draft

(feat) Live Diff Workflow#116
susanhooks wants to merge 4 commits into
mainfrom
sh/add-diff-button

Conversation

@susanhooks

@susanhooks susanhooks commented Jul 9, 2026

Copy link
Copy Markdown
Collaborator

Description

Validation

  • Standard CI passes.
  • Kind integration passes, or this PR explains why it was not run.

The kind integration test is manual due to taking ~30 min to complete. When the PR is ready for
review, approve the current commit and start the suite with these PR comments:

/ok to test <sha>
/kind test

As a fallback, run Actions -> Kind Integration -> Run workflow against the copy-pr-bot generated
pull-request/<PR_NUMBER> branch. Use the default test_path for the full suite, or narrow it
only while debugging.

The completed workflow posts its conclusion and exact run URL as a PR comment.

Passing Kind Integration run:

Checklist

  • I am familiar with the contributing guidelines in CONTRIBUTING.md.
  • Commits are signed off for DCO compliance.
  • New or existing tests cover these changes, or the PR explains why tests are not needed.
  • Documentation is updated for user-facing behavior changes.
  • Generated artifacts are updated when applicable, such as OpenAPI specs,
    docs screenshots, or Helm/rendered outputs.
Screenshot 2026-07-09 at 2 51 18 PM Screenshot 2026-07-09 at 2 51 34 PM Screenshot 2026-07-09 at 2 51 58 PM Screenshot 2026-07-09 at 2 52 15 PM Screenshot 2026-07-09 at 2 52 42 PM

Summary by CodeRabbit

  • New Features
    • Added a Configuration Diff workflow to compare intended vs. live device configuration.
    • Added See Diff actions across device status/workflow views and a Live Config Diff row on device details.
    • Added a New Configuration Diff Workflow form that supports URL-driven device filtering.
  • Bug Fixes
    • Improved handling of missing/empty diff data and added more reliable context for workflow links (including device status/IDs).
  • Documentation
    • Added UI guidance clarifying that history diffs are not live diffs, plus updated API/workflow specs.
  • Tests
    • Added Temporal workflow tests and strengthened UI workflow link assertions.

Signed-off-by: Susan Hooks <shooks@nvidia.com>
@copy-pr-bot

copy-pr-bot Bot commented Jul 9, 2026

Copy link
Copy Markdown

This pull request requires additional validation before any workflows can run on NVIDIA's runners.

Pull request vetters can view their responsibilities here.

Contributors can view more details about this message here.

@coderabbitai

coderabbitai Bot commented Jul 9, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Adds a Temporal configuration-diff workflow, exposes it through Nautobot and the web UI, registers its API and RBAC metadata, and updates tests and UI text for the new live diff flow.

Changes

Configuration Diff Workflow

Layer / File(s) Summary
Workflow orchestration and validation
src/nv_config_manager/temporal/ngc/workflows/config_diff.py, src/tests/temporal/ngc/workflows/test_config_diff_workflow.py
Defines the two-stage diff workflow, archives results, returns diff status, and tests diff and no-diff executions without applying changes.
Workflow registration and API exposure
src/nv_config_manager/temporal/ngc/workflows/__init__.py, docs/api-specs/temporal.openapi.json, deploy/helm/values-rbac-open.yaml
Registers ConfigDiffWorkflow, documents its endpoint and input schema, and adds read/execute RBAC mappings.
Nautobot actions and context wiring
components/nautobot/nautobot-nv-config-manager/nv_config_manager/tables.py, components/nautobot/nautobot-nv-config-manager/nv_config_manager/views.py, components/nautobot/nautobot-nv-config-manager/nv_config_manager/templates/..., components/nautobot/nautobot-nv-config-manager/nv_config_manager/tests/test_views.py
Adds Live Diff actions and links, passes device context to templates, and verifies generated workflow URLs.
Workflow form and navigation
ui/src/app/workflows/configdiffworkflow/..., ui/src/components/forms/workflow.tsx, ui/src/config/site.ts, ui/src/types/data-table.types.ts, ui/src/app/device/.../history/page.tsx
Adds the Configuration Diff form and navigation entry, supports URL-based tenant/status selection, and clarifies history diff behavior.

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

Suggested reviewers: dmathur0, jojung1, polarweasel, spidercensus, zsblevins

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 71.43% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title matches the main change: adding a live diff workflow and related UI support.
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 sh/add-diff-button

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

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

🤖 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 `@components/nautobot/nautobot-nv-config-manager/nv_config_manager/tables.py`:
- Around line 89-93: The diff workflow is receiving the wrong managed-device
identifier because `device_id` is set from `record.device.pk` instead of the
`ConfigManagerDeviceStatus`/managed-device identifier used elsewhere. Update the
payload assembly in `tables.py` to pass `record.pk` (or the same identifier used
by the other launch points) from the `ConfigManagerDeviceStatus` context,
keeping the rest of the fields unchanged.

In
`@components/nautobot/nautobot-nv-config-manager/nv_config_manager/templates/nv_config_manager/configmanagerdevicestatus_workflows_tab.html`:
- Around line 56-69: The workflow-tab links in
configmanagerdevicestatus_workflows_tab.html are rendered even when temporal_url
is missing, which can create broken relative URLs, and the devicename query
value is not URL-encoded, which can corrupt the link for names with reserved
characters. Update the link generation blocks around the See Diff/workflow
actions to only render when temporal_url is set, and ensure devicename is passed
through urlencoding just like site and tenant; apply the same fix to the other
workflow-tab link block noted in the template.

In `@src/nv_config_manager/temporal/ngc/workflows/config_diff.py`:
- Around line 61-63: The workflow_description string in config_diff.py is
incomplete and should be rewritten to finish the sentence cleanly. Update the
description used by the config diff workflow so it reads naturally with a
complete object after “without applying” (for example, by adding “it” or
“changes”), keeping the wording user-facing because this value is surfaced in
the UI and exported into the Temporal API docs. Locate the text in
workflow_description and adjust only the description content, not the
surrounding workflow logic.

In `@ui/src/app/workflows/configdiffworkflow/form/page.tsx`:
- Around line 30-41: `DeviceWorkflowForm` leaves `isSubmitting` stuck because
`onSubmit` does not await or return the `startWorkflow` promise and never clears
the submitting state. Update the submit handler in `DeviceWorkflowForm` to be
async, await `startWorkflow(endpoint, params)`, keep the existing toast handling
on failure, and reset `isSubmitting` in a `finally` block so the form can be
retried after success or error.

In `@ui/src/components/forms/workflow.tsx`:
- Around line 269-292: The manual-change guards in the workflow form are never
cleared, so URL-driven tenant/status updates can be blocked after a user change.
Update the React.useEffect logic in workflow.tsx around the tenant and status
preselect blocks to reset the corresponding isManualTenantChange and
isManualStatusChange flags whenever queryTenants or queryStatuses changes, or
track a query signature so new URL selections can re-apply. Keep the fix
localized to the effects that call form.setValue for tenant and status.
🪄 Autofix (Beta)

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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 3cc862e8-7b8c-4bb3-b738-959d0c188958

📥 Commits

Reviewing files that changed from the base of the PR and between 227148e and 5fd18cb.

📒 Files selected for processing (18)
  • components/nautobot/nautobot-nv-config-manager/nv_config_manager/tables.py
  • components/nautobot/nautobot-nv-config-manager/nv_config_manager/templates/nv_config_manager/configmanagerdevicestatus_workflows_tab.html
  • components/nautobot/nautobot-nv-config-manager/nv_config_manager/templates/nv_config_manager/inc/managed_device_details.html
  • components/nautobot/nautobot-nv-config-manager/nv_config_manager/templates/nv_config_manager/inc/see_diff.html
  • components/nautobot/nautobot-nv-config-manager/nv_config_manager/tests/test_views.py
  • components/nautobot/nautobot-nv-config-manager/nv_config_manager/views.py
  • deploy/helm/values-rbac-open.yaml
  • docs/api-specs/temporal.openapi.json
  • src/nv_config_manager/temporal/ngc/workflows/__init__.py
  • src/nv_config_manager/temporal/ngc/workflows/config_diff.py
  • src/tests/temporal/ngc/workflows/test_config_diff_workflow.py
  • ui/src/app/device/[uuid]/[filename]/history/page.tsx
  • ui/src/app/workflows/configdiffworkflow/form/loading.tsx
  • ui/src/app/workflows/configdiffworkflow/form/page.tsx
  • ui/src/components/forms/workflow.tsx
  • ui/src/config/site.ts
  • ui/src/types/data-table.types.ts
  • ui/tsconfig.tsbuildinfo

Comment on lines +89 to +93
"temporal_url": settings.PLUGINS_CONFIG["nv_config_manager"].get("temporal_url"),
"site": site,
"device_id": record.device.pk,
"tenant": getattr(record.device.tenant, "name", "") if record else "",
"status": getattr(record.device.status, "name", "") if record else "",

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Pass the managed-device identifier to the diff workflow.

device_id is populated with record.device.pk, but the other launch points use ConfigManagerDeviceStatus.pk (instance.pk or managed_device.pk). This can cause the workflow to compare the wrong object or fail lookup. Use record.pk (or the workflow’s documented identifier) consistently.

🤖 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 `@components/nautobot/nautobot-nv-config-manager/nv_config_manager/tables.py`
around lines 89 - 93, The diff workflow is receiving the wrong managed-device
identifier because `device_id` is set from `record.device.pk` instead of the
`ConfigManagerDeviceStatus`/managed-device identifier used elsewhere. Update the
payload assembly in `tables.py` to pass `record.pk` (or the same identifier used
by the other launch points) from the `ConfigManagerDeviceStatus` context,
keeping the rest of the fields unchanged.

Comment thread src/nv_config_manager/temporal/ngc/workflows/config_diff.py
Comment on lines +30 to +41
const onSubmit = (data: DeviceWorkflowFormSchema) => {
const endpoint = "/v1/workflow/ngc/config_diff";
const params: ConfigDiffWorkflowInput = {
device_id: data.device,
};
startWorkflow(endpoint, params).catch((error) => {
toast({
variant: "destructive",
title: "Workflow Failed",
description: `Failed to create workflow: ${error}`,
});
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Reset submitting state after the workflow request completes.

DeviceWorkflowForm sets isSubmitting to true, but this callback never returns the startWorkflow promise or resets the state. On rejection the toast is shown while the form remains permanently disabled, preventing retry; on success it also remains stuck if no navigation occurs. Make the submit contract async and clear isSubmitting in a finally block in DeviceWorkflowForm.

🤖 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 `@ui/src/app/workflows/configdiffworkflow/form/page.tsx` around lines 30 - 41,
`DeviceWorkflowForm` leaves `isSubmitting` stuck because `onSubmit` does not
await or return the `startWorkflow` promise and never clears the submitting
state. Update the submit handler in `DeviceWorkflowForm` to be async, await
`startWorkflow(endpoint, params)`, keep the existing toast handling on failure,
and reset `isSubmitting` in a `finally` block so the form can be retried after
success or error.

Comment thread ui/src/components/forms/workflow.tsx
susanhooks and others added 3 commits July 9, 2026 21:08
Signed-off-by: Susan Hooks <shooks@nvidia.com>
Signed-off-by: Susan Hooks <shooks@nvidia.com>
@susanhooks

Copy link
Copy Markdown
Collaborator Author

/ok to test 4cbd7c8

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

🧹 Nitpick comments (1)
src/nv_config_manager/temporal/ngc/workflows/config_diff.py (1)

165-166: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Escape or use a collision-safe Markdown fence for device-generated diffs.

A configuration value can contain triple backticks, which would terminate this fence early and render the remainder as Markdown instead of code. Use a longer/generated fence or escape the content before displaying it.

🤖 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 `@src/nv_config_manager/temporal/ngc/workflows/config_diff.py` around lines 165
- 166, The markdown rendering in the diff output is vulnerable to fence
collisions because the device-generated diff can contain triple backticks and
break the surrounding code block. Update the logic in the PerformDiffStageOutput
construction path in config_diff.py to use a collision-safe fence length or
otherwise escape/sanitize the diff content before embedding it in the markdown
string. Keep the display field safe for arbitrary configuration values while
preserving the diff text.
🤖 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.

Nitpick comments:
In `@src/nv_config_manager/temporal/ngc/workflows/config_diff.py`:
- Around line 165-166: The markdown rendering in the diff output is vulnerable
to fence collisions because the device-generated diff can contain triple
backticks and break the surrounding code block. Update the logic in the
PerformDiffStageOutput construction path in config_diff.py to use a
collision-safe fence length or otherwise escape/sanitize the diff content before
embedding it in the markdown string. Keep the display field safe for arbitrary
configuration values while preserving the diff text.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 23e80bf7-b0e4-43d6-90f6-ad7aeef71ae2

📥 Commits

Reviewing files that changed from the base of the PR and between be98746 and 4cbd7c8.

📒 Files selected for processing (7)
  • components/nautobot/nautobot-nv-config-manager/nv_config_manager/templates/nv_config_manager/configmanagerdevicestatus_workflows_tab.html
  • components/nautobot/nautobot-nv-config-manager/nv_config_manager/templates/nv_config_manager/inc/see_diff.html
  • components/nautobot/nautobot-nv-config-manager/nv_config_manager/tests/test_views.py
  • src/nv_config_manager/temporal/ngc/workflows/config_diff.py
  • src/tests/temporal/ngc/workflows/test_config_diff_workflow.py
  • ui/src/app/workflows/configdiffworkflow/form/page.tsx
  • ui/tsconfig.tsbuildinfo
💤 Files with no reviewable changes (1)
  • components/nautobot/nautobot-nv-config-manager/nv_config_manager/templates/nv_config_manager/inc/see_diff.html
🚧 Files skipped from review as they are similar to previous changes (4)
  • ui/src/app/workflows/configdiffworkflow/form/page.tsx
  • components/nautobot/nautobot-nv-config-manager/nv_config_manager/templates/nv_config_manager/configmanagerdevicestatus_workflows_tab.html
  • components/nautobot/nautobot-nv-config-manager/nv_config_manager/tests/test_views.py
  • src/tests/temporal/ngc/workflows/test_config_diff_workflow.py

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