Skip to content

Conversation

Cahllagerfeld
Copy link
Contributor

@Cahllagerfeld Cahllagerfeld commented Oct 6, 2025

  • Once the snapshot list is enabled, we need to add the form to that page as well
grafik

Summary by CodeRabbit

  • New Features

    • Create Snapshot from Run: new page with validated form, prefilled defaults from the selected run, and cancel/create actions with loading and error states.
    • Run Actions menu now includes “New Snapshot,” navigating to the create-snapshot flow.
    • Pipeline and Run selectors support infinite scrolling and auto-generate a snapshot name from the chosen run.
  • Style

    • Improved table layouts: names truncate to prevent overflow; snapshot and run icons no longer shrink in flex containers.

Testing

  • From the global snapshot list hit Create snapshot
  • From an existing run, hit the three dots, and then create-snapshot

Copy link
Contributor

coderabbitai bot commented Oct 6, 2025

📝 Walkthrough

Walkthrough

Adds a run-scoped “Create Snapshot” flow: updates RunActionsMenu to accept runId and link to a new create-snapshot route/page. Implements form, schema, selects, submission hook, and utility for naming. Adds infinite queries for pipelines and runs. Minor UI class tweaks to icons/text truncation. No changes to existing public data-fetching signatures except explicit return type and new exports.

Changes

Cohort / File(s) Summary
Run actions integration
src/app/runs/[id]/Header.tsx, src/app/runs/[id]/RunActionMenu.tsx
Passes runId into RunActionsMenu. RunActionsMenu now accepts { runId }, imports Link/routes/Plus icon, and adds “New Snapshot” menu item linking to the create-snapshot route.
Create snapshot page & routing
src/app/runs/[id]/create-snapshot/page.tsx, src/router/Router.tsx, src/router/routes.tsx
Adds a lazy route runs.createSnapshot(":runId") and a page that loads run via usePipelineRun and renders CreateSnapshotForm with loading/error states. Exposes routes.projects.runs.createSnapshot(id).
Create snapshot form stack
src/components/pipeline-snapshots/create/form.tsx, src/components/pipeline-snapshots/create/form-schema.ts, src/components/pipeline-snapshots/create/name-helper.ts, src/components/pipeline-snapshots/create/use-submit-handler.ts
Introduces Zod schema, form with RHF and default values from optional run, generateSnapshotName utility, and a submit handler hook that resolves snapshotId (via fetchPipelineRun when needed), updates snapshot, handles toasts, invalidation, and navigation.
Form UI subcomponents
src/components/pipeline-snapshots/create/_form-components/create-snapshot-form-header.tsx, src/components/pipeline-snapshots/create/_form-components/create-snapshot-form-footer.tsx
Adds header and footer components; footer includes Cancel (navigate back) and a pending-aware Create Snapshot button with spinner.
Select components with infinite queries
src/components/pipeline-snapshots/create/pipeline-select.tsx, src/components/pipeline-snapshots/create/run-select.tsx
Adds PipelineSelect and RunSelect with RHF Controller, infinite loading via react-query, skeleton/error states, load-more controls, and dependent field resets. Run selection can auto-fill name via generateSnapshotName.
Data layer: infinite queries & typing
src/data/pipelines/index.ts, src/data/pipeline-runs/all-pipeline-runs-query.ts, src/data/pipeline-runs/pipeline-run-detail-query.ts
Adds pipelineListInfinite and allPipelineRunsInfinite using infiniteQueryOptions, with paging keys and next-page logic. Declares explicit Promise return type for fetchPipelineRun.
UI polish (icons/layout)
src/app/pipelines/[pipelineId]/snapshots/columns/index.tsx, src/app/runs/columns.tsx
Adds shrink-0 to icons and truncate to text span to adjust flex behavior/truncation; no logic changes.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor User
  participant Header as RunsDetailHeader
  participant Menu as RunActionsMenu
  participant Router
  participant Page as CreateSnapshotFromRunPage
  participant Form as CreateSnapshotForm
  participant Hook as useSubmitHandler
  participant Data as fetchPipelineRun/useUpdateSnapshot
  participant Nav as Navigation

  User->>Header: Open run details
  Header->>Menu: Render with runId
  User->>Menu: Click "New Snapshot"
  Menu->>Router: Link to runs.createSnapshot(runId)
  Router->>Page: Load page (protected)
  Page->>Data: usePipelineRun(runId)
  Data-->>Page: Run data or error
  Page->>Form: Render with run (if loaded)

  Note over Form,Hook: On submit
  Form->>Hook: handleCreateSnapshot(name, pipelineId, runId)
  alt originalSnapshotId provided
    Hook->>Data: useUpdateSnapshot.mutate({ snapshotId, name })
  else Fetch snapshotId from run
    Hook->>Data: fetchPipelineRun(runId)
    Data-->>Hook: { snapshotId? }
    alt snapshotId found
      Hook->>Data: useUpdateSnapshot.mutate({ snapshotId, name })
    else
      Hook-->>Form: Toast "Snapshot not found"
    end
  end
  Data-->>Hook: onSuccess
  Hook-->>Nav: Navigate to snapshot overview
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~55 minutes

Possibly related PRs

  • Release #675: Overlaps run/snapshot components and routes; modifies RunActionsMenu/Header and snapshot-related flows.
  • Release #778: Also alters Runs header and RunActionsMenu structure; intersects with this PR’s runId prop and action menu changes.

Suggested reviewers

  • schustmi
  • atzin-escandia

Poem

I hop through routes with nimble delight,
A snapshot blooms from a run in sight.
Dropdowns unfurl, pages align,
Infinite lists scroll just fine.
With a click and a spin—no fright—
I nibble “Create,” and name it bright.
Thump! Another feature takes flight. 🐇✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Title Check ✅ Passed The title accurately indicates the addition of snapshot creation but the suffix “for OSS” does not correspond to any code changes and may introduce confusion, even though the core feature is correctly identified.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
✨ 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 feat/852--create-snapshots

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.

@Cahllagerfeld
Copy link
Contributor Author

@coderabbitai review

Copy link
Contributor

coderabbitai bot commented Oct 6, 2025

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

🧹 Nitpick comments (3)
src/components/pipeline-snapshots/create/_form-components/create-snapshot-form-footer.tsx (1)

13-13: Consider explicit navigation instead of history-based.

Using navigate(-1) can be unpredictable if users arrive via direct link or external navigation. Consider navigating to a specific route (e.g., the run detail page or runs list) for more predictable UX.

Example:

-<Button type="button" onClick={() => navigate(-1)} intent="secondary" size="md">
+<Button type="button" onClick={() => navigate(routes.projects.runs.detail(runId))} intent="secondary" size="md">

Note: You would need to pass runId as a prop to implement this suggestion.

src/components/pipeline-snapshots/create/name-helper.ts (1)

1-3: Consider improving the name generation strategy.

The current approach has a few limitations:

  1. Timestamp length: Date.now() produces 13-digit millisecond timestamps, creating long names like "my-run-snapshot-1728205177123".
  2. Not user-friendly: Millisecond timestamps are hard to read and compare.
  3. Potential collisions: Rapid submissions could theoretically generate the same timestamp.
  4. No input validation: Empty or very long runName values could produce problematic names.

Consider alternatives:

 export function generateSnapshotName(runName: string) {
-  return `${runName}-snapshot-${Date.now()}`;
+  // Option 1: Use shorter, more readable format
+  const timestamp = new Date().toISOString().replace(/[:.]/g, '-').slice(0, -5);
+  return `${runName}-snapshot-${timestamp}`;
+
+  // Option 2: Use a counter or random suffix
+  const suffix = Math.random().toString(36).substring(2, 8);
+  return `${runName}-snapshot-${suffix}`;
 }

Or add validation:

export function generateSnapshotName(runName: string) {
  const sanitizedName = runName.trim() || 'snapshot';
  const timestamp = Date.now();
  return `${sanitizedName}-${timestamp}`;
}
src/components/pipeline-snapshots/create/run-select.tsx (1)

28-32: Skip querying until a pipeline is selected

Without a pipeline, the request fires with an empty pipeline_id, producing avoidable errors and an “Error fetching runs” stub in the UI. Gate the query with enabled: !!pipeline so it waits until the user picks a pipeline.

 	const runQuery = useInfiniteQuery({
 		...allPipelineRunsInfinite({
 			params: { pipeline_id: pipeline, sort_by: "desc:created" }
-		})
+		}),
+		enabled: Boolean(pipeline)
 	});
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between db83eea and f16509d.

📒 Files selected for processing (18)
  • src/app/pipelines/[pipelineId]/snapshots/columns/index.tsx (1 hunks)
  • src/app/runs/[id]/Header.tsx (1 hunks)
  • src/app/runs/[id]/RunActionMenu.tsx (3 hunks)
  • src/app/runs/[id]/create-snapshot/page.tsx (1 hunks)
  • src/app/runs/columns.tsx (1 hunks)
  • src/components/pipeline-snapshots/create/_form-components/create-snapshot-form-footer.tsx (1 hunks)
  • src/components/pipeline-snapshots/create/_form-components/create-snapshot-form-header.tsx (1 hunks)
  • src/components/pipeline-snapshots/create/form-schema.ts (1 hunks)
  • src/components/pipeline-snapshots/create/form.tsx (1 hunks)
  • src/components/pipeline-snapshots/create/name-helper.ts (1 hunks)
  • src/components/pipeline-snapshots/create/pipeline-select.tsx (1 hunks)
  • src/components/pipeline-snapshots/create/run-select.tsx (1 hunks)
  • src/components/pipeline-snapshots/create/use-submit-handler.ts (1 hunks)
  • src/data/pipeline-runs/all-pipeline-runs-query.ts (2 hunks)
  • src/data/pipeline-runs/pipeline-run-detail-query.ts (1 hunks)
  • src/data/pipelines/index.ts (2 hunks)
  • src/router/Router.tsx (2 hunks)
  • src/router/routes.tsx (1 hunks)
🔇 Additional comments (6)
src/app/runs/columns.tsx (1)

65-65: LGTM! Icon layout improvement.

Adding shrink-0 prevents the icon from being compressed in flex layouts when space is constrained, maintaining consistent visual sizing alongside dynamic text content.

src/app/pipelines/[pipelineId]/snapshots/columns/index.tsx (1)

60-60: LGTM!

The addition of shrink-0 to the icon prevents it from shrinking in the flex container, and truncate on the text prevents overflow. Both are appropriate UI improvements.

Also applies to: 67-67

src/router/routes.tsx (1)

34-34: LGTM!

The new createSnapshot route generator follows the existing pattern and integrates cleanly with the runs routes.

src/data/pipelines/index.ts (1)

13-21: LGTM!

The infinite query implementation follows TanStack Query v5 best practices:

  • Properly uses pageParam in the query function
  • Correctly implements getNextPageParam with null termination
  • Distinguishes the infinite query key with an "infinite" suffix
src/app/runs/[id]/Header.tsx (1)

41-41: LGTM!

Passing runId to RunActionsMenu enables the new snapshot creation flow from the run context.

src/components/pipeline-snapshots/create/_form-components/create-snapshot-form-footer.tsx (1)

18-18: Verify the spinner color scheme.

The spinner uses border-theme-text-negative (typically red/error color) combined with border-b-theme-text-brand. This creates a two-tone effect that may not align with the brand's loading indicator style. Ensure this is intentional.

Typical spinner patterns use a single color with one transparent/lighter edge:

-<div className="h-4 w-4 animate-spin rounded-rounded border-2 border-theme-text-negative border-b-theme-text-brand" />
+<div className="h-4 w-4 animate-spin rounded-rounded border-2 border-theme-border-moderate border-b-theme-text-brand" />

Copy link
Contributor Author

@Cahllagerfeld Cahllagerfeld left a comment

Choose a reason for hiding this comment

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

@znegrin Within this PR, I created the option to create a snapshot from the run detail.
In this case, pipeline and run are prefilled already, and disabled.

Do you think there will be another practical way, where the user selects the pipeline first, and the run afterwards, so basically starting with an entirely empty form for creating a snapshot?

In case no, we can prob drop teh entire Run and Pipeline Selects we're having right now.

What do you think?

@Cahllagerfeld Cahllagerfeld linked an issue Oct 7, 2025 that may be closed by this pull request
@znegrin
Copy link
Contributor

znegrin commented Oct 7, 2025

@Cahllagerfeld this was designed with the two dropdowns for the "Run a pipeline" option that we have in both the pipelines and the runs list, so users can click there and then select it from scratch. Not sure if this is used or even relevant, but this was the logic behind it. I agree that for the cases where users don't need to select anything, we can skip these dropdowns, as users already have the information in the header. You can see in my new designs that I am not showing them anymore for certain cases.

From what I've seen, we have four different ways to create, edit, or run a snapshot, if I'm correct:

  • Run a pipeline button: In this case, the user needs to select a template first. Right now, they don't need to select a specific run for this one.
  • New snapshot button (from the three dots dropdown inside a run): it currently shows the deactivated dropdowns for pipeline and run. We can probably remove those and just show the pipeline structure on the left and the name at the top using the new designs.
  • New snapshot: from the snapshots list. This is the one where users need to select a pipeline and a run first. We may need to rethink this flow to adapt it to the new designs.
  • Run snapshot: from a snapshot page, this one doesn't need to show the dropdowns, and it goes directly to the editor (which will change to the new screens).

@Cahllagerfeld Cahllagerfeld changed the title Create Snapshots Create Snapshots for OSS Oct 7, 2025
@Cahllagerfeld
Copy link
Contributor Author

Okay I got it 👍

@Cahllagerfeld Cahllagerfeld marked this pull request as ready for review October 7, 2025 07:50
@Cahllagerfeld Cahllagerfeld requested a review from tzador October 16, 2025 08:56
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.

Allow creation of snapshot from OSS Dashboard

2 participants