Skip to content

Conversation

myftija
Copy link
Member

@myftija myftija commented Sep 18, 2025

Changes in this PR:

  • added an autoRevalidate hook which revalidates the page based on an
    interval and/or focus change
  • added simple polling-based live reloading for deployments
  • replaced the live reloading mechanism for the bulk actions and queues page
    with the new autoRevalidate hook. They were previously using an SSE
    endpoint, but the events were basically being used just as signals to
    revalidate periodically.

Copy link

changeset-bot bot commented Sep 18, 2025

⚠️ No Changeset found

Latest commit: 4d29e22

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

Copy link
Contributor

coderabbitai bot commented Sep 18, 2025

Walkthrough

  • Added useAutoRevalidate hook to trigger Remix revalidation via interval and focus/visibility.
  • Updated env schema: removed QUEUE_SSE_AUTORELOAD_INTERVAL_MS and QUEUE_SSE_AUTORELOAD_TIMEOUT_MS; added DEPLOYMENTS_AUTORELOAD_POLL_INTERVAL_MS, BULK_ACTION_AUTORELOAD_POLL_INTERVAL_MS, QUEUES_AUTORELOAD_POLL_INTERVAL_MS.
  • Replaced SSE-based updates with polling in deployments, queues, and bulk-action routes; loaders now return autoReloadPollIntervalMs from env.
  • Removed two SSE resource routes for queues and bulk-action progress.
  • Minor UI change to deployment label badge and removed an unused import.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Pre-merge checks and finishing touches

❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Description Check ⚠️ Warning The PR description lists the core changes (autoRevalidate hook, polling for deployments, replacing SSE for bulk actions and queues) but does not follow the repository's required template: it is missing the "Closes #" line, the ✅ checklist, a "Testing" section with steps taken, a "Changelog" entry, and Screenshots. Because those template elements are required for reviewer verification and traceability, the description is incomplete for this repository's standards. Please update the PR description to follow the repository template: add "Closes #" if applicable, complete the checklist (including confirmation you followed the contributing guide and ran tests), provide a "Testing" section with concrete steps you ran to verify the changes, add a short "Changelog" summary of user-visible behavior, and attach screenshots if the UI changed. Also call out any important migration notes (e.g., SSE → polling) and note how reviewers can observe or reproduce the live-reload behavior.
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 (1 passed)
Check name Status Explanation
Title Check ✅ Passed The title "feat(webapp): deployments page live reloading" is concise, follows conventional prefixing, and accurately highlights a clear, user-visible change in the changeset (adding live reloading for deployments). The PR also introduces a new auto-revalidate hook and migrates bulk-actions/queues from SSE to polling, but the title's focus on deployments remains a valid, specific summary of the primary feature. It is readable and informative for teammates scanning history.
✨ Finishing touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch live-reload-deployments-page

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.

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: 0

🧹 Nitpick comments (5)
apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.deployments.$deploymentParam/route.tsx (1)

134-138: Unify label casing with the list view

The list view uses titleCase(deployment.label) while this detail view uses CSS capitalize. Align to a single approach to avoid inconsistent casing across pages.

Apply:

-                  {deployment.label && (
-                    <Badge variant="extra-small" className="capitalize">
-                      {deployment.label}
-                    </Badge>
-                  )}
+                  {deployment.label && (
+                    <Badge variant="extra-small">{titleCase(deployment.label)}</Badge>
+                  )}

Add import (outside the shown range):

+import { titleCase } from "~/utils";
apps/webapp/app/env.server.ts (1)

1031-1034: Validate poll intervals as non‑negative; document “0 disables”

Current schema accepts negative numbers; the hook treats <= 0 as disabled. Make that explicit and prevent accidental negatives.

-    DEPLOYMENTS_AUTORELOAD_POLL_INTERVAL_MS: z.coerce.number().int().default(5_000),
-    BULK_ACTION_AUTORELOAD_POLL_INTERVAL_MS: z.coerce.number().int().default(1_000),
-    QUEUES_AUTORELOAD_POLL_INTERVAL_MS: z.coerce.number().int().default(5_000),
+    DEPLOYMENTS_AUTORELOAD_POLL_INTERVAL_MS: z.coerce.number().int().nonnegative().default(5_000),
+    BULK_ACTION_AUTORELOAD_POLL_INTERVAL_MS: z.coerce.number().int().nonnegative().default(1_000),
+    QUEUES_AUTORELOAD_POLL_INTERVAL_MS: z.coerce.number().int().nonnegative().default(5_000),
apps/webapp/app/hooks/useAutoRevalidate.ts (3)

4-8: Export the options type

Useful for consumers to type their options.

-type UseAutoRevalidateOptions = {
+export type UseAutoRevalidateOptions = {
   interval?: number; // in milliseconds
   onFocus?: boolean;
   disabled?: boolean;
 };

14-25: Skip polling when tab is hidden; include revalidator in deps

Prevents unnecessary network churn in background tabs; keeps deps accurate.

-  useEffect(() => {
-    if (!interval || interval <= 0 || disabled) return;
-
-    const intervalId = setInterval(() => {
-      if (revalidator.state === "loading") {
-        return;
-      }
-      revalidator.revalidate();
-    }, interval);
-
-    return () => clearInterval(intervalId);
-  }, [interval, disabled]);
+  useEffect(() => {
+    if (!interval || interval <= 0 || disabled) return;
+
+    const intervalId = setInterval(() => {
+      if (document.visibilityState !== "visible") return;
+      if (revalidator.state === "loading") return;
+      revalidator.revalidate();
+    }, interval);
+
+    return () => clearInterval(intervalId);
+  }, [interval, disabled, revalidator]);

27-45: Coalesce focus + visibility events to avoid double revalidate

Both events can fire together; debounce to a single revalidate and add revalidator to deps.

-  useEffect(() => {
-    if (!onFocus || disabled) return;
-
-    const handleFocus = () => {
-      if (document.visibilityState === "visible" && revalidator.state !== "loading") {
-        revalidator.revalidate();
-      }
-    };
-
-    // Revalidate when the page becomes visible
-    document.addEventListener("visibilitychange", handleFocus);
-    // Revalidate when the window gains focus
-    window.addEventListener("focus", handleFocus);
-
-    return () => {
-      document.removeEventListener("visibilitychange", handleFocus);
-      window.removeEventListener("focus", handleFocus);
-    };
-  }, [onFocus, disabled]);
+  useEffect(() => {
+    if (!onFocus || disabled) return;
+
+    let timeoutId: number | undefined;
+    const schedule = () => {
+      if (timeoutId) clearTimeout(timeoutId);
+      timeoutId = window.setTimeout(() => {
+        if (document.visibilityState === "visible" && revalidator.state !== "loading") {
+          revalidator.revalidate();
+        }
+      }, 0);
+    };
+
+    document.addEventListener("visibilitychange", schedule);
+    window.addEventListener("focus", schedule);
+
+    return () => {
+      if (timeoutId) clearTimeout(timeoutId);
+      document.removeEventListener("visibilitychange", schedule);
+      window.removeEventListener("focus", schedule);
+    };
+  }, [onFocus, disabled, revalidator]);
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between db87295 and 4d29e22.

📒 Files selected for processing (8)
  • apps/webapp/app/env.server.ts (1 hunks)
  • apps/webapp/app/hooks/useAutoRevalidate.ts (1 hunks)
  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.bulk-actions.$bulkActionParam/route.tsx (4 hunks)
  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.deployments.$deploymentParam/route.tsx (1 hunks)
  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.deployments/route.tsx (3 hunks)
  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.queues/route.tsx (5 hunks)
  • apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.queues.stream.tsx (0 hunks)
  • apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.bulkaction.$bulkActionParam.stream.tsx (0 hunks)
💤 Files with no reviewable changes (2)
  • apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.queues.stream.tsx
  • apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.bulkaction.$bulkActionParam.stream.tsx
🧰 Additional context used
📓 Path-based instructions (5)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

**/*.{ts,tsx}: Always prefer using isomorphic code like fetch, ReadableStream, etc. instead of Node.js specific code
For TypeScript, we usually use types over interfaces
Avoid enums
No default exports, use function declarations

Files:

  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.deployments.$deploymentParam/route.tsx
  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.deployments/route.tsx
  • apps/webapp/app/hooks/useAutoRevalidate.ts
  • apps/webapp/app/env.server.ts
  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.bulk-actions.$bulkActionParam/route.tsx
  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.queues/route.tsx
{packages/core,apps/webapp}/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

We use zod a lot in packages/core and in the webapp

Files:

  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.deployments.$deploymentParam/route.tsx
  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.deployments/route.tsx
  • apps/webapp/app/hooks/useAutoRevalidate.ts
  • apps/webapp/app/env.server.ts
  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.bulk-actions.$bulkActionParam/route.tsx
  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.queues/route.tsx
apps/webapp/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/webapp.mdc)

When importing from @trigger.dev/core in the webapp, never import the root package path; always use one of the documented subpath exports from @trigger.dev/core’s package.json

Files:

  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.deployments.$deploymentParam/route.tsx
  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.deployments/route.tsx
  • apps/webapp/app/hooks/useAutoRevalidate.ts
  • apps/webapp/app/env.server.ts
  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.bulk-actions.$bulkActionParam/route.tsx
  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.queues/route.tsx
apps/webapp/app/**/*.ts

📄 CodeRabbit inference engine (.cursor/rules/webapp.mdc)

Modules intended for test consumption under apps/webapp/app/**/*.ts must not read environment variables; accept configuration via options instead

Files:

  • apps/webapp/app/hooks/useAutoRevalidate.ts
  • apps/webapp/app/env.server.ts
{apps/webapp/app/**/*.server.{ts,tsx},apps/webapp/app/routes/**/*.ts}

📄 CodeRabbit inference engine (.cursor/rules/webapp.mdc)

Access environment variables only via the env export from app/env.server.ts; do not reference process.env directly

Files:

  • apps/webapp/app/env.server.ts
🧬 Code graph analysis (4)
apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.deployments.$deploymentParam/route.tsx (1)
apps/webapp/app/components/primitives/Badge.tsx (1)
  • Badge (21-27)
apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.deployments/route.tsx (2)
apps/webapp/app/env.server.ts (1)
  • env (1184-1184)
apps/webapp/app/hooks/useAutoRevalidate.ts (1)
  • useAutoRevalidate (10-48)
apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.bulk-actions.$bulkActionParam/route.tsx (2)
apps/webapp/app/env.server.ts (1)
  • env (1184-1184)
apps/webapp/app/hooks/useAutoRevalidate.ts (1)
  • useAutoRevalidate (10-48)
apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.queues/route.tsx (2)
apps/webapp/app/env.server.ts (1)
  • env (1184-1184)
apps/webapp/app/hooks/useAutoRevalidate.ts (1)
  • useAutoRevalidate (10-48)
⏰ 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). (23)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (2, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (6, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (8, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (1, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (5, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (7, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (5, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (6, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (4, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (8, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (1, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (3, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (2, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (3, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (7, 8)
  • GitHub Check: units / packages / 🧪 Unit Tests: Packages (1, 1)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (4, 8)
  • GitHub Check: e2e / 🧪 CLI v3 tests (ubuntu-latest - pnpm)
  • GitHub Check: e2e / 🧪 CLI v3 tests (ubuntu-latest - npm)
  • GitHub Check: e2e / 🧪 CLI v3 tests (windows-latest - pnpm)
  • GitHub Check: e2e / 🧪 CLI v3 tests (windows-latest - npm)
  • GitHub Check: typecheck / typecheck
  • GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (3)
apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.deployments/route.tsx (1)

64-66: Auto‑reload wiring LGTM

  • Correctly sources interval from env via loader (server‑side access only).
  • Hooks up client polling and focus revalidation.
  • Public payload shape change looks minimal and safe.

Also applies to: 121-124, 144-145, 152-153

apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.bulk-actions.$bulkActionParam/route.tsx (1)

20-22: Good replacement of SSE with interval polling; smart disable when not PENDING

  • Env access via loader is compliant.
  • Polling disabled after completion avoids wasted requests.

Also applies to: 75-78, 135-135, 140-145

apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.queues/route.tsx (1)

26-26: Queues auto‑reload integration looks solid

  • Loader exposes env‑driven interval; page consumes via useAutoRevalidate with focus behavior.
  • Nice type‑only import for ButtonVariant.

Also applies to: 69-71, 118-124, 217-226, 233-234

@myftija myftija merged commit e4982bf into main Sep 19, 2025
31 checks passed
@myftija myftija deleted the live-reload-deployments-page branch September 19, 2025 08:40
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.

2 participants