Skip to content

Commit f39bc44

Browse files
committed
Projects ✨
- Deploy a new VM when a push event comes through - Live updating project overview page
1 parent 4fabd48 commit f39bc44

File tree

65 files changed

+2521
-281
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

65 files changed

+2521
-281
lines changed

.changeset/shaggy-hounds-appear.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@trigger.dev/sdk": patch
3+
---
4+
5+
SDK now passes through the project ID from the env var

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,4 +45,5 @@ yarn-error.log*
4545
.output
4646
apps/**/public/build
4747
.tests-container-id.txt
48-
.sentryclirc
48+
.sentryclirc
49+
.buildt

.warp/triggerdotdev.yaml.example

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,9 @@ windows:
5252
- cwd: /Users/eric/code/triggerdotdev/trigger.dev
5353
commands:
5454
- exec: ./scripts/proxy-pizzly.sh <your-pizzly-dev>
55+
- cwd: /Users/eric/code/triggerdotdev/trigger.dev
56+
commands:
57+
- exec: ./scripts/proxy-wss.sh <your-wss-dev>
5558
- title: wss and examples
5659
layout:
5760
split_direction: horizontal
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import { useLocales } from "./LocaleProvider";
2+
3+
type IntlDateProps = {
4+
date: Date;
5+
timeZone?: string;
6+
};
7+
8+
export const IntlDate = ({ date, timeZone }: IntlDateProps) => {
9+
const locales = useLocales();
10+
const isoString = date.toISOString();
11+
const formattedDate = new Intl.DateTimeFormat(locales, {
12+
year: "numeric",
13+
month: "short",
14+
day: "numeric",
15+
timeZone,
16+
}).format(date);
17+
18+
const formattedTime = new Intl.DateTimeFormat(locales, {
19+
hour: "numeric",
20+
minute: "numeric",
21+
timeZone,
22+
}).format(date);
23+
24+
return (
25+
<time dateTime={isoString}>
26+
{formattedDate} at {formattedTime}
27+
</time>
28+
);
29+
};
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import type { ReactNode } from "react";
2+
import { useContext } from "react";
3+
import { createContext } from "react";
4+
5+
type LocaleContext = {
6+
locales: string[];
7+
};
8+
9+
type LocaleContextProviderProps = {
10+
locales: string[];
11+
children: ReactNode;
12+
};
13+
14+
const Context = createContext<LocaleContext | null>(null);
15+
16+
export const LocaleContextProvider = ({
17+
locales,
18+
children,
19+
}: LocaleContextProviderProps) => {
20+
const value = { locales };
21+
22+
return <Context.Provider value={value}>{children}</Context.Provider>;
23+
};
24+
25+
const throwIfNoProvider = () => {
26+
throw new Error("Please wrap your application in a LocaleContextProvider.");
27+
};
28+
29+
export const useLocales = () => {
30+
const { locales } = useContext(Context) ?? throwIfNoProvider();
31+
return locales;
32+
};

apps/webapp/app/components/navigation/SideMenu.tsx

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,13 @@ import {
88
ArrowTopRightOnSquareIcon,
99
BeakerIcon,
1010
ChevronLeftIcon,
11+
CloudArrowUpIcon,
1112
Cog6ToothIcon,
1213
EnvelopeIcon,
1314
ForwardIcon,
1415
PhoneArrowUpRightIcon,
1516
PlusCircleIcon,
17+
QueueListIcon,
1618
Squares2X2Icon,
1719
SquaresPlusIcon,
1820
UsersIcon,
@@ -27,6 +29,7 @@ import {
2729
} from "~/hooks/useOrganizations";
2830
import { useCurrentWorkflow } from "~/hooks/useWorkflows";
2931
import { EnvironmentIcon } from "~/routes/resources/environment";
32+
import { CurrentProject } from "~/routes/__app/orgs/$organizationSlug/projects/$projectP";
3033
import { titleCase } from "~/utils";
3134
import { CopyTextPanel } from "../CopyTextButton";
3235
import { TertiaryA, TertiaryButton } from "../primitives/Buttons";
@@ -152,6 +155,43 @@ export function WorkflowsSideMenu() {
152155
);
153156
}
154157

158+
export function ProjectSideMenu({
159+
project,
160+
backPath,
161+
}: {
162+
project: CurrentProject;
163+
backPath: string;
164+
}) {
165+
if (!project) {
166+
return null;
167+
}
168+
169+
const items: SideMenuItem[] = [
170+
{
171+
name: "Overview",
172+
icon: <ArrowsRightLeftIcon className={iconStyle} />,
173+
to: ``,
174+
},
175+
{
176+
name: "Deploys",
177+
icon: <CloudArrowUpIcon className={iconStyle} />,
178+
to: `deploys`,
179+
},
180+
{
181+
name: "Logs",
182+
icon: <QueueListIcon className={iconStyle} />,
183+
to: `logs`,
184+
},
185+
{
186+
name: "Settings",
187+
icon: <Cog6ToothIcon className={iconStyle} />,
188+
to: `settings`,
189+
},
190+
];
191+
192+
return <SideMenu title={project.name} items={items} backPath={backPath} />;
193+
}
194+
155195
const defaultStyle =
156196
"group flex items-center gap-2 px-3 py-3 text-base rounded transition text-slate-300 hover:bg-slate-850 hover:text-white";
157197
const activeStyle =

apps/webapp/app/entry.client.tsx

Lines changed: 26 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3,30 +3,36 @@ import { hydrateRoot } from "react-dom/client";
33
import * as Sentry from "@sentry/remix";
44
import { useEffect } from "react";
55
import posthog from "posthog-js";
6+
import { LocaleContextProvider } from "./components/LocaleProvider";
67

7-
hydrateRoot(document, <RemixBrowser />);
8+
hydrateRoot(
9+
document,
10+
<LocaleContextProvider locales={window.navigator.languages as string[]}>
11+
<RemixBrowser />
12+
</LocaleContextProvider>
13+
);
814

915
//hack because the type is not exported
1016
type SentryIntegration = (typeof Sentry.defaultIntegrations)[number];
1117

1218
if (process.env.NODE_ENV === "production") {
13-
Sentry.init({
14-
dsn: "https://bf96820b08004fa4b2e1506f2ac74a14@o4504419574087680.ingest.sentry.io/4504419607052288",
15-
tracesSampleRate: 1,
16-
integrations: [
17-
new Sentry.BrowserTracing({
18-
routingInstrumentation: Sentry.remixRouterInstrumentation(
19-
useEffect,
20-
useLocation,
21-
useMatches
22-
),
23-
}),
24-
//casted because TypeScript is unhappy about the type from PostHog
25-
new posthog.SentryIntegration(
26-
posthog,
27-
"triggerdev",
28-
4504419607052288
29-
) as SentryIntegration,
30-
],
31-
});
19+
Sentry.init({
20+
dsn: "https://bf96820b08004fa4b2e1506f2ac74a14@o4504419574087680.ingest.sentry.io/4504419607052288",
21+
tracesSampleRate: 1,
22+
integrations: [
23+
new Sentry.BrowserTracing({
24+
routingInstrumentation: Sentry.remixRouterInstrumentation(
25+
useEffect,
26+
useLocation,
27+
useMatches
28+
),
29+
}),
30+
//casted because TypeScript is unhappy about the type from PostHog
31+
new posthog.SentryIntegration(
32+
posthog,
33+
"triggerdev",
34+
4504419607052288
35+
) as SentryIntegration,
36+
],
37+
});
3238
}

apps/webapp/app/entry.server.tsx

Lines changed: 29 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@ import { renderToPipeableStream } from "react-dom/server";
55
import { RemixServer } from "@remix-run/react";
66
import { Response } from "@remix-run/node"; // or cloudflare/deno
77
import type { EntryContext, Headers } from "@remix-run/node"; // or cloudflare/deno
8+
import { parseAcceptLanguage } from "intl-parse-accept-language";
89
import isbot from "isbot";
10+
import { LocaleContextProvider } from "./components/LocaleProvider";
911

1012
const ABORT_DELAY = 30000;
1113

@@ -15,6 +17,11 @@ export default function handleRequest(
1517
responseHeaders: Headers,
1618
remixContext: EntryContext
1719
) {
20+
const acceptLanguage = request.headers.get("accept-language");
21+
const locales = parseAcceptLanguage(acceptLanguage, {
22+
validate: Intl.DateTimeFormat.supportedLocalesOf,
23+
});
24+
1825
// If the request is from a bot, we want to wait for the full
1926
// response to render before sending it to the client. This
2027
// ensures that bots can see the full page content.
@@ -23,31 +30,36 @@ export default function handleRequest(
2330
request,
2431
responseStatusCode,
2532
responseHeaders,
26-
remixContext
33+
remixContext,
34+
locales
2735
);
2836
}
2937

3038
return serveBrowsers(
3139
request,
3240
responseStatusCode,
3341
responseHeaders,
34-
remixContext
42+
remixContext,
43+
locales
3544
);
3645
}
3746

3847
function serveTheBots(
3948
request: Request,
4049
responseStatusCode: number,
4150
responseHeaders: Headers,
42-
remixContext: EntryContext
51+
remixContext: EntryContext,
52+
locales: string[]
4353
) {
4454
return new Promise((resolve, reject) => {
4555
const { pipe, abort } = renderToPipeableStream(
46-
<RemixServer
47-
context={remixContext}
48-
url={request.url}
49-
abortDelay={ABORT_DELAY}
50-
/>,
56+
<LocaleContextProvider locales={locales}>
57+
<RemixServer
58+
context={remixContext}
59+
url={request.url}
60+
abortDelay={ABORT_DELAY}
61+
/>
62+
</LocaleContextProvider>,
5163
{
5264
// Use onAllReady to wait for the entire document to be ready
5365
onAllReady() {
@@ -74,16 +86,19 @@ function serveBrowsers(
7486
request: Request,
7587
responseStatusCode: number,
7688
responseHeaders: Headers,
77-
remixContext: EntryContext
89+
remixContext: EntryContext,
90+
locales: string[]
7891
) {
7992
return new Promise((resolve, reject) => {
8093
let didError = false;
8194
const { pipe, abort } = renderToPipeableStream(
82-
<RemixServer
83-
context={remixContext}
84-
url={request.url}
85-
abortDelay={ABORT_DELAY}
86-
/>,
95+
<LocaleContextProvider locales={locales}>
96+
<RemixServer
97+
context={remixContext}
98+
url={request.url}
99+
abortDelay={ABORT_DELAY}
100+
/>
101+
</LocaleContextProvider>,
87102
{
88103
// use onShellReady to wait until a suspense boundary is triggered
89104
onShellReady() {

apps/webapp/app/env.server.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@ const EnvironmentSchema = z.object({
5757
GITHUB_APP_WEBHOOK_SECRET: z.string().optional(),
5858
INTEGRATIONS_API_KEY: z.string(),
5959
INTEGRATIONS_API_ORIGIN: z.string(),
60+
CAKEWORK_API_KEY: z.string(),
61+
TRIGGER_WSS_URL: z.string().default("wss://wss.trigger.dev/ws"),
6062
});
6163

6264
export type Environment = z.infer<typeof EnvironmentSchema>;
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import {
2+
CakeworkApiClient,
3+
CakeworkApiEnvironment,
4+
} from "@cakework/client/dist";
5+
import { env } from "~/env.server";
6+
7+
export const cakework = new CakeworkApiClient({
8+
environment: CakeworkApiEnvironment.Production,
9+
xApiKey: env.CAKEWORK_API_KEY,
10+
});

0 commit comments

Comments
 (0)