Skip to content

feat(deploy-modal): logs section + URL-driven log selection#4522

Open
stylessh wants to merge 56 commits intosimstudioai:stagingfrom
stylessh:stylessh/deploy-modal-logs
Open

feat(deploy-modal): logs section + URL-driven log selection#4522
stylessh wants to merge 56 commits intosimstudioai:stagingfrom
stylessh:stylessh/deploy-modal-logs

Conversation

@stylessh
Copy link
Copy Markdown
Contributor

@stylessh stylessh commented May 8, 2026

Summary

Adds a Logs section below Versions in the workflow deploy modal showing the latest 5 runs (status, trigger, duration, timestamp). Clicking a row deep-links to /logs?executionId=<id> and auto-opens the detail panel.

To make that link survive — and to make log selection in general bookmarkable / back-button-friendly — adopted nuqs and refactored the logs page so ?executionId=<id> is the source of truth for the open detail panel. Also fixed the filter store's syncWithURL which was wiping unrelated query params (it now only deletes/sets keys it owns), and declared @radix-ui/react-dismissable-layer and @opentelemetry/core as direct deps (they were resolving through hoisted transitives and broke the Turbopack build).

Type of Change

  • New feature

Testing

  • Open a workflow → Deploy modal → General tab → confirm Logs section shows the last 5 runs with proper status/trigger badges, duration, and timestamp.
  • Click a log row → lands on /logs?executionId=..., URL persists, detail panel opens.
  • On /logs, click any row → URL updates; close panel → URL clears; back/forward navigates selection state. Apply filters and confirm executionId is no longer wiped from the URL.
  • Workflows with no runs render a "No runs yet" empty state.

Checklist

  • Code follows project style guidelines
  • Self-reviewed my changes
  • No new warnings introduced
  • I confirm that I have read and agree to the terms outlined in the Contributor License Agreement (CLA)

waleedlatif1 and others added 30 commits April 3, 2026 23:30
…ership workflow edits via sockets, ui improvements
…ration, signup method feature flags, SSO improvements
* feat(posthog): Add tracking on mothership abort (simstudioai#4023)

Co-authored-by: Theodore Li <theo@sim.ai>

* fix(login): fix captcha headers for manual login  (simstudioai#4025)

* fix(signup): fix turnstile key loading

* fix(login): fix captcha header passing

* Catch user already exists, remove login form captcha
…nts, secrets performance, polling refactors, drag resources in mothership
…endar triggers, docs updates, integrations/models pages improvements
…mat, logs performance improvements

fix(csp): add missing analytics domains, remove unsafe-eval, fix workspace CSP gap (simstudioai#4179)
fix(landing): return 404 for invalid dynamic route slugs (simstudioai#4182)
improvement(seo): optimize sitemaps, robots.txt, and core web vitals across sim and docs (simstudioai#4170)
fix(gemini): support structured output with tools on Gemini 3 models (simstudioai#4184)
feat(brightdata): add Bright Data integration with 8 tools (simstudioai#4183)
fix(mothership): fix superagent credentials (simstudioai#4185)
fix(logs): close sidebar when selected log disappears from filtered list; cleanup (simstudioai#4186)
v0.6.46: mothership streaming fixes, brightdata integration
icecrasher321 and others added 22 commits April 22, 2026 14:01
…ze, subagent thinking, files sorting, agentphone integration
fix(db): revert statement_timeout startup options breaking pooled connections (simstudioai#4284)
v0.6.57: mothership reliability, ashby refactor, tables row count, copilot id fix, bun upgrade
…rizations, mothership positional table row insertion, CI improvements, org-external users, file viewer improvements
v0.6.62: fix new copilot chat creation and selection on refresh
…ixes, db query optimizations, contract boundaries code hygiene, CORS, toast improvements, tables infinite query, executor robustness, reranker support
…ogs block, parallel-in-loop wall clock, gpt-image-2
…s, logs panel width, tables UI/DB decoupling

v0.6.67: VFS upload fix, posthog/copilot correlation, exa date filters, logs panel width, tables UI/DB decoupling
…ering upgrades, data drains, security hardening, paginated dropdowns
…ntegrations, robots.txt update, workday hardening
v0.6.72: billing pool contention fix
- New "Logs" section in deploy modal General tab showing latest 5 runs;
  clicking a row deep-links to /logs?executionId=<id>.
- Adopt nuqs for URL state and make `executionId` the source of truth
  for the open log detail panel (auto-opens on deep link, persists on
  selection, clears on close, survives back/forward).
- Filter store's syncWithURL now preserves unrelated query params
  instead of wiping the entire query string.
- Declare @radix-ui/react-dismissable-layer and @opentelemetry/core as
  direct deps (were resolving via hoisted transitive deps).
@vercel
Copy link
Copy Markdown

vercel Bot commented May 8, 2026

@stylessh is attempting to deploy a commit to the Sim Team on Vercel.

A member of the Team first needs to authorize it.

@cursor
Copy link
Copy Markdown

cursor Bot commented May 8, 2026

PR Summary

Medium Risk
Introduces URL-driven state for log detail selection/navigation via nuqs and modifies query-param syncing, which can affect back/forward behavior and deep links across the logs UI. Also adds new runtime dependencies that could impact build/startup if misconfigured.

Overview
Adds a Logs section to the workflow deploy modal that shows the latest 5 runs (status/trigger/duration/timestamp) and deep-links to the Logs page via ?executionId=....

Refactors the Logs page so executionId in the URL becomes the source of truth for opening/closing and navigating the details sidebar (including keyboard and row interactions), enabled by wiring NuqsAdapter at the app root.

Centralizes log status/trigger badge logic into a new shared lib/logs/status module and updates logs components to consume it, while tightening the filter store URL sync to only clear/set owned query keys (preserving unrelated params like executionId).

Reviewed by Cursor Bugbot for commit 9cce6fd. Bugbot is set up for automated code reviews on this repo. Configure here.

@stylessh stylessh changed the base branch from main to staging May 8, 2026 22:13
@gitguardian
Copy link
Copy Markdown

gitguardian Bot commented May 8, 2026

⚠️ GitGuardian has uncovered 1 secret following the scan of your pull request.

Please consider investigating the findings and remediating the incidents. Failure to do so may lead to compromising the associated services or software components.

Since your pull request originates from a forked repository, GitGuardian is not able to associate the secrets uncovered with secret incidents on your GitGuardian dashboard.
Skipping this check run and merging your pull request will create secret incidents on your GitGuardian dashboard.

🔎 Detected hardcoded secret in your pull request
GitGuardian id GitGuardian status Secret Commit Filename
29606901 Triggered Generic High Entropy Secret a54dcbe apps/sim/providers/utils.test.ts View secret
🛠 Guidelines to remediate hardcoded secrets
  1. Understand the implications of revoking this secret by investigating where it is used in your code.
  2. Replace and store your secret safely. Learn here the best practices.
  3. Revoke and rotate this secret.
  4. If possible, rewrite git history. Rewriting git history is not a trivial act. You might completely break other contributing developers' workflow and you risk accidentally deleting legitimate data.

To avoid such incidents in the future consider


🦉 GitGuardian detects secrets in your source code to help developers and security teams secure the modern development process. You are seeing this because you or someone else with access to this repository has authorized GitGuardian to scan your pull request.

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented May 8, 2026

Greptile Summary

Adds a Logs section to the workflow deploy modal showing the latest 5 runs, and refactors the /logs page to use nuqs (useQueryState) so ?executionId=<id> is the URL-driven source of truth for the open detail panel. The filter store's syncWithURL is also fixed to only delete the keys it owns, preserving unrelated params like executionId when filters change.

  • Deploy modal logs panel (logs.tsx): new component fetches the last 5 runs and deep-links each row to /logs?executionId=<id>. Imports StatusBadge, TriggerBadge, and getDisplayStatus directly from the logs feature's utils file, creating cross-feature coupling; loading skeleton renders 3 rows while LOGS_LIMIT is 5, causing a visible layout shift.
  • logs.tsx (logs page): replaces manual URLSearchParams parsing with useQueryState; adds isSidebarOpenRef and updates all navigation handlers (handleLogClick, handleNavigateNext, handleNavigatePrev, handleCloseSidebar, keyboard Enter) to stay in sync with the URL.
  • store.ts (filter store): syncWithURL now starts from the live URL params and only clears its own 8 keys, so unrelated params survive filter updates.

Confidence Score: 4/5

Safe to merge; the new Logs panel and URL-driven selection work correctly in the happy path with two minor edge cases worth addressing.

The syncWithURL fix correctly scopes its URL writes to owned keys, and the nuqs integration is straightforward. The deploy modal's new Logs component has a skeleton/data count mismatch that causes a layout shift on load, and the deep-link effect's same-ID guard silently skips reopening the panel when a user navigates back to an execution they previously closed — both are noticeable but low-impact.

logs.tsx (deploy modal) for the cross-feature import and skeleton count; logs.tsx (logs page) for the deep-link effect's same-ID guard.

Important Files Changed

Filename Overview
apps/sim/app/workspace/[workspaceId]/logs/logs.tsx Replaces manual URL parsing with nuqs useQueryState for executionId; adds isSidebarOpenRef to sync sidebar close with URL; updates all navigation handlers. Logic is sound but the deep-link guard has a subtle no-op edge case when re-linking to the same execution after closing the panel.
apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/deploy/components/deploy-modal/components/general/components/logs.tsx New component showing latest 5 runs in the deploy modal. Imports badges/utils from a different feature's directory (cross-feature coupling) and the loading skeleton renders 3 rows instead of matching LOGS_LIMIT (5), causing a layout shift.
apps/sim/stores/logs/filters/store.ts Fixed syncWithURL to start from the current URL params and only delete owned keys, preserving executionId (and any other unknown params) across filter changes. Clean targeted fix.
apps/sim/app/layout.tsx Wraps the app with NuqsAdapter from nuqs/adapters/next/app — a minimal, correct change required by the nuqs Next.js App Router integration.
apps/sim/package.json Adds nuqs, @radix-ui/react-dismissable-layer, and @opentelemetry/core as explicit direct dependencies to fix transitive Turbopack resolution failures.

Sequence Diagram

sequenceDiagram
    participant Modal as Deploy Modal (Logs)
    participant Router as Next.js Router
    participant LogsPage as /logs Page
    participant nuqs as nuqs (useQueryState)
    participant FilterStore as Filter Store

    Modal->>Router: "router.push(/logs?executionId=X)"
    Router->>LogsPage: "mount with ?executionId=X"
    nuqs-->>LogsPage: "executionIdParam = X"
    LogsPage->>LogsPage: deepLinkQuery fetches by executionId
    LogsPage->>LogsPage: dispatch(TOGGLE_LOG, resolvedId)

    Note over LogsPage,nuqs: User clicks a different row
    LogsPage->>nuqs: setExecutionIdParam(log.executionId)
    nuqs-->>Router: "replaceState ?executionId=Y"
    LogsPage->>LogsPage: dispatch(TOGGLE_LOG, rowId)

    Note over LogsPage,FilterStore: User changes a filter
    FilterStore->>FilterStore: syncWithURL()
    FilterStore->>FilterStore: "getSearchParams() reads ?executionId=Y"
    FilterStore->>FilterStore: delete only FILTER_PARAM_KEYS
    FilterStore->>FilterStore: "replaceState ?executionId=Y&level=error"

    Note over LogsPage,nuqs: User closes sidebar
    LogsPage->>nuqs: setExecutionIdParam(null)
    nuqs-->>Router: replaceState (executionId removed)
Loading

Reviews (1): Last reviewed commit: "feat(deploy-modal): add logs section + U..." | Re-trigger Greptile

Comment on lines +10 to +14
import {
getDisplayStatus,
StatusBadge,
TriggerBadge,
} from '@/app/workspace/[workspaceId]/logs/utils'
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.

P2 Cross-feature import of presentation components

StatusBadge, TriggerBadge, and getDisplayStatus are defined inside the logs feature's own utils file (@/app/workspace/[workspaceId]/logs/utils) and are now imported by a completely different feature (the deploy modal). Per the project's architecture guidelines, utilities consumed by two or more distinct features belong in @/lib/ or a shared @/components path rather than inside a feature-scoped directory. As the logs feature grows, any refactor or rename of these utilities will silently break the deploy modal.

Context Used: Core architecture principles for the Sim app (source)

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

</div>
</div>
<div className='bg-[var(--surface-2)]'>
{[0, 1, 2].map((i) => (
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.

P2 Skeleton renders 3 placeholder rows, but LOGS_LIMIT is 5. When the actual data loads with 4–5 rows the container jumps in height, producing a visible layout shift. The skeleton count should match LOGS_LIMIT.

Suggested change
{[0, 1, 2].map((i) => (
{Array.from({ length: LOGS_LIMIT }, (_, i) => i).map((i) => (

Comment on lines 438 to 440
const resolvedId = deepLinkQuery.data?.id
if (resolvedId) {
if (resolvedId && resolvedId !== selectedLogIdRef.current) {
dispatch({ type: 'TOGGLE_LOG', logId: resolvedId })
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.

P2 Deep-link won't reopen sidebar for same execution ID after manual close

The guard resolvedId !== selectedLogIdRef.current prevents dispatching TOGGLE_LOG when the IDs match. Because selectedLogIdRef retains the last-selected log id even after handleCloseSidebar (which only changes isSidebarOpen, not the selected id), navigating back to /logs?executionId=<X> after manually closing the panel for log X will leave the sidebar closed — the effect sees resolvedId === selectedLogIdRef.current and silently no-ops. The guard is necessary to avoid double-opening on data refetch, but it needs an additional check: if the sidebar is currently closed it should still open.

Address PR feedback:

- Move LogStatus, getDisplayStatus, STATUS_CONFIG, StatusBadge, and
  TriggerBadge from feature-scoped logs/utils.ts to @/lib/logs/status
  so cross-feature consumers (deploy modal) don't reach into another
  feature's directory. Update all four consumers accordingly.
- Match deploy-modal Logs skeleton row count to LOGS_LIMIT to avoid
  layout shift when data loads.
- Allow deep-link bridge to reopen the sidebar when navigating back to
  the same executionId after a manual close (previously the same-id
  guard silently no-op'd).
- Fix biome organizeImports error caught by CI lint:check.
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.

5 participants