Skip to content

Feat/show org deployment level#3868

Merged
Siumauricio merged 5 commits intocanaryfrom
feat/show-org-deployment-level
Mar 3, 2026
Merged

Feat/show org deployment level#3868
Siumauricio merged 5 commits intocanaryfrom
feat/show-org-deployment-level

Conversation

@Siumauricio
Copy link
Contributor

@Siumauricio Siumauricio commented Mar 3, 2026

What is this PR about?

Please describe in a short paragraph what this PR is about.

Checklist

Before submitting this PR, please make sure that:

  • You created a dedicated branch based on the canary branch.
  • You have read the suggestions in the CONTRIBUTING.md file https://github.com/Dokploy/dokploy/blob/canary/CONTRIBUTING.md#pull-request
  • You have tested this PR in your local instance. If you have not tested it yet, please do so before submitting. This helps avoid wasting maintainers' time reviewing code that has not been verified by you.

Issues related (if applicable)

Screenshots (if applicable)

Greptile Summary

This PR adds an organization-level deployments dashboard with two tabs: a centralized Deployments view (all application and compose deployments across the org, with filtering, sorting, and pagination) and a Queue view (live job/run status from BullMQ in self-hosted mode or Inngest in cloud mode). A new /jobs API endpoint is added to the apps/api server for fetching Inngest run state in a BullMQ-compatible shape.

Key changes:

  • New findAllDeploymentsCentralized service function with correct org-scoped and member-access-restricted queries
  • New allCentralized and queueList tRPC procedures with appropriate authorization
  • New apps/api/src/service.ts implementing Inngest event + run fetching
  • A logic bug in fetchDeploymentJobs: the full event list is passed to buildDeploymentRowsFromRuns but only the first 50 events per server have their runs populated, causing events beyond position 50 to always display as "pending" regardless of their actual state
  • Cloud-mode queueList fetches each server's jobs sequentially rather than concurrently, which will add latency when an org has multiple servers

Confidence Score: 3/5

  • Mostly safe to merge, but the queue display will show incorrect "pending" state for older Inngest-based jobs until the buildDeploymentRowsFromRuns call is fixed.
  • The core deployments table and authorization logic are sound. The critical issue is in fetchDeploymentJobs — events beyond the first 50 fetched for a server will always render as "pending" in the Queue tab due to passing the full unfiltered event list to buildDeploymentRowsFromRuns instead of the sliced toFetch list. This is a functional bug that will show stale/incorrect state to users. The sequential server fetching is a performance concern but not a correctness issue.
  • apps/api/src/service.ts needs the buildDeploymentRowsFromRuns call fixed (pass toFetch instead of events). apps/dokploy/server/api/routers/deployment.ts should parallelize server fetching with Promise.all.

Last reviewed commit: edceebe

Introduced a new deployments page that includes a table for viewing all application and compose deployments, as well as a queue table for monitoring deployment jobs. Updated the sidebar to include a link to the new deployments section. Enhanced the API to support centralized deployment queries and job queue retrieval, improving overall deployment management and visibility.
Added a new endpoint to fetch deployment jobs for a server, integrating with the Inngest API to retrieve job details. Updated the queue management system to support centralized job retrieval for cloud environments, improving the deployment monitoring experience. Enhanced the UI to include action buttons for job cancellation and improved error handling for job fetching.
@dosubot dosubot bot added the size:XXL This PR changes 1000+ lines, ignoring generated files. label Mar 3, 2026
autofix-ci bot and others added 2 commits March 3, 2026 07:05
Added self-hosted and production configuration examples for Inngest to the .env.example file. This enhancement provides clearer guidance for developers on setting up the Inngest integration.
@dosubot dosubot bot added the enhancement New feature or request label Mar 3, 2026
@dosubot
Copy link

dosubot bot commented Mar 3, 2026

Documentation Updates

1 document(s) were updated by changes in this PR:

README
View Changes
@@ -6,6 +6,31 @@
 ```
 open http://localhost:3000
 ```
+
+## Environment Variables
+
+The API server requires the following environment variables for configuration:
+
+### Inngest Configuration
+
+Required for the GET /jobs endpoint to list deployment jobs:
+
+- **INNGEST_BASE_URL** - The base URL for the Inngest instance
+  - Self-hosted: `http://localhost:8288`
+  - Production: `https://dev-inngest.dokploy.com`
+  
+- **INNGEST_SIGNING_KEY** - The signing key for authenticating with Inngest
+
+Optional configuration for filtering and pagination:
+
+- **INNGEST_EVENTS_RECEIVED_AFTER** (optional) - An RFC3339 timestamp to filter events received after a specific date (e.g., `2024-01-01T00:00:00Z`). If unset, no date filter is applied.
+
+- **INNGEST_JOBS_MAX_EVENTS** (optional) - Maximum number of events to fetch when listing jobs. Default is 100, maximum is 10000. Used for pagination with cursor.
+
+### Lemon Squeezy Integration
+
+- **LEMON_SQUEEZY_API_KEY** - API key for Lemon Squeezy integration
+- **LEMON_SQUEEZY_STORE_ID** - Store ID for Lemon Squeezy integration
 
 ## API Endpoints
 

How did I do? Any feedback?  Join Discord

Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

10 files reviewed, 4 comments

Edit Code Review Agent Settings | Greptile

}),
);

return buildDeploymentRowsFromRuns(events, runsByEventId, serverId);
Copy link
Contributor

Choose a reason for hiding this comment

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

Events beyond the 50-limit always show as "pending"

fetchDeploymentJobs slices requestedForServer to 50 events for run fetching (toFetch), but then passes the full events list to buildDeploymentRowsFromRuns. Inside that function, all events matching the server ID are iterated — including events at positions 51+. For those events, runsByEventId.get(ev.id) returns undefined, so runs = [], and the code creates a row with state: "pending" — even though those deployments may have completed or failed.

Fix: pass toFetch instead of events (all events in toFetch already match serverId, so the filter inside buildDeploymentRowsFromRuns is harmless):

Suggested change
return buildDeploymentRowsFromRuns(events, runsByEventId, serverId);
return buildDeploymentRowsFromRuns(toFetch, runsByEventId, serverId);

Comment on lines +103 to +106
}
rows.sort((a, b) => (b.timestamp ?? 0) - (a.timestamp ?? 0));
} else {
const jobs = await myQueue.getJobs();
Copy link
Contributor

Choose a reason for hiding this comment

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

Sequential server fetching causes unnecessary latency

Each fetchDeployApiJobs call is awaited in sequence. With multiple servers, the total time is the sum of all individual request latencies. Using Promise.all would fetch all servers concurrently:

Suggested change
}
rows.sort((a, b) => (b.timestamp ?? 0) - (a.timestamp ?? 0));
} else {
const jobs = await myQueue.getJobs();
const serverRowsArrays = await Promise.all(
servers.map(({ serverId }) => fetchDeployApiJobs(serverId)),
);
rows = serverRowsArrays.flat();

Cancel
</Button>
)}
</div>
Copy link
Contributor

Choose a reason for hiding this comment

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

colSpan is one more than the actual column count

The table has 9 columns (Job ID, Label, Type, State, Added, Processed, Finished, Error, Actions) but colSpan={10} is specified for the empty state cell. While browsers handle this gracefully, it should match the actual column count.

Suggested change
</div>
<TableCell colSpan={9} className="text-center py-12">

Comment on lines +238 to +240
const DEFAULT_MAX_EVENTS = 500;

const MAX_EVENTS = DEFAULT_MAX_EVENTS;
Copy link
Contributor

Choose a reason for hiding this comment

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

Constants defined after their first use

DEFAULT_MAX_EVENTS and MAX_EVENTS are declared at the bottom of the file (lines 238–240) but MAX_EVENTS is referenced in fetchInngestEvents at line 58. This works at runtime because the reference is inside a function body (evaluated lazily), but it is confusing to readers. Moving the constant declarations to the top of the file is the conventional approach:

Suggested change
const DEFAULT_MAX_EVENTS = 500;
const MAX_EVENTS = DEFAULT_MAX_EVENTS;
const DEFAULT_MAX_EVENTS = 500;
const MAX_EVENTS = DEFAULT_MAX_EVENTS;

(Place these lines near the top of the file, after the type definitions, and remove the current declarations at the bottom.)

Updated the event fetching logic to utilize Promise.all for concurrent API calls, enhancing performance. Adjusted the UI table layout by modifying the column span for better alignment and presentation of the empty queue state. Introduced constants for maximum events to improve code clarity.
@Siumauricio Siumauricio merged commit 6f21f1c into canary Mar 3, 2026
4 checks passed
@Siumauricio Siumauricio deleted the feat/show-org-deployment-level branch March 3, 2026 20:12
dosubot bot added a commit that referenced this pull request Mar 3, 2026
@dosubot dosubot bot mentioned this pull request Mar 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request size:XXL This PR changes 1000+ lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant