Skip to content

Commit 4e80195

Browse files
committed
wip4
1 parent 6c82530 commit 4e80195

24 files changed

Lines changed: 238 additions & 95 deletions

apps/webapp/app/models/member.server.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,7 @@ export async function acceptInvite({
215215
organization: invite.organization,
216216
project,
217217
type: "DEVELOPMENT",
218-
isBranchableEnvironment: false,
218+
isBranchableEnvironment: true,
219219
member,
220220
prismaClient: tx,
221221
});

apps/webapp/app/models/project.server.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ export async function createProject(
126126
organization,
127127
project,
128128
type: "DEVELOPMENT",
129-
isBranchableEnvironment: false,
129+
isBranchableEnvironment: true,
130130
member,
131131
});
132132
}

apps/webapp/app/presenters/OrganizationsPresenter.server.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,7 @@ export class OrganizationsPresenter {
244244

245245
//otherwise show their dev environment
246246
const yourDevEnvironment = environments.find(
247-
(env) => env.type === "DEVELOPMENT" && env.orgMember?.userId === user.id
247+
(env) => env.type === "DEVELOPMENT" && env.branchName === null && env.orgMember?.userId === user.id
248248
);
249249
if (yourDevEnvironment) {
250250
return yourDevEnvironment;

apps/webapp/app/presenters/SelectBestEnvironmentPresenter.server.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import {
22
type RuntimeEnvironment,
33
type PrismaClient,
4-
RuntimeEnvironmentType,
4+
type RuntimeEnvironmentType,
55
} from "@trigger.dev/database";
66
import { prisma } from "~/db.server";
77
import { logger } from "~/services/logger.server";
@@ -140,7 +140,7 @@ export class SelectBestEnvironmentPresenter {
140140
}
141141

142142
async selectBestEnvironment<
143-
T extends { id: string; type: RuntimeEnvironmentType; orgMember: { userId: string } | null }
143+
T extends { id: string; type: RuntimeEnvironmentType; slug: string; orgMember: { userId: string } | null }
144144
>(projectId: string, user: UserFromSession, environments: T[]): Promise<T> {
145145
//try get current environment from prefs
146146
const currentEnvironmentId: string | undefined =
@@ -153,7 +153,8 @@ export class SelectBestEnvironmentPresenter {
153153

154154
//otherwise show their dev environment
155155
const yourDevEnvironment = environments.find(
156-
(env) => env.type === "DEVELOPMENT" && env.orgMember?.userId === user.id
156+
// Return the default dev environment, not a branch
157+
(env) => env.type === "DEVELOPMENT" && env.slug === "dev" && env.orgMember?.userId === user.id
157158
);
158159
if (yourDevEnvironment) {
159160
return yourDevEnvironment;

apps/webapp/app/presenters/v3/BranchesPresenter.server.ts

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ export class BranchesPresenter {
9292
},
9393
where: {
9494
projectId: project.id,
95+
type: "PREVIEW",
9596
isBranchableEnvironment: true,
9697
},
9798
});
@@ -124,18 +125,18 @@ export class BranchesPresenter {
124125
projectId: project.id,
125126
branchName: search
126127
? {
127-
contains: search,
128-
mode: "insensitive",
129-
}
128+
contains: search,
129+
mode: "insensitive",
130+
}
130131
: {
131-
not: null,
132-
},
132+
not: null,
133+
},
133134
...(showArchived ? {} : { archivedAt: null }),
134135
},
135136
});
136137

137138
// Limits
138-
const limits = await checkBranchLimit({ prisma: this.#prismaClient, organizationId: project.organizationId, projectId: project.id });
139+
const limits = await checkBranchLimit({ prisma: this.#prismaClient, organizationId: project.organizationId, projectId: project.id, env: "preview" });
139140

140141
const [currentPlan, plans] = await Promise.all([
141142
getCurrentPlan(project.organizationId),
@@ -163,12 +164,12 @@ export class BranchesPresenter {
163164
projectId: project.id,
164165
branchName: search
165166
? {
166-
contains: search,
167-
mode: "insensitive",
168-
}
167+
contains: search,
168+
mode: "insensitive",
169+
}
169170
: {
170-
not: null,
171-
},
171+
not: null,
172+
},
172173
...(showArchived ? {} : { archivedAt: null }),
173174
},
174175
orderBy: {

apps/webapp/app/routes/api.v1.projects.$projectRef.branches.archive.ts

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ const ParamsSchema = z.object({
1111
});
1212

1313
const BodySchema = z.object({
14+
env: z.enum(["preview", "development"]),
1415
branch: z.string(),
1516
});
1617

@@ -49,6 +50,9 @@ export async function action({ request, params }: ActionFunctionArgs) {
4950
return json({ error: parsed.error.message }, { status: 400 });
5051
}
5152

53+
const { env, branch } = parsed.data;
54+
55+
const environmentType = env === "preview" ? "PREVIEW" : "DEVELOPMENT";
5256
const environments = await prisma.runtimeEnvironment.findMany({
5357
select: {
5458
id: true,
@@ -59,16 +63,17 @@ export async function action({ request, params }: ActionFunctionArgs) {
5963
authenticationResult.type === "organizationAccessToken"
6064
? { id: authenticationResult.result.organizationId }
6165
: {
62-
members: {
63-
some: {
64-
userId: authenticationResult.result.userId,
65-
},
66+
members: {
67+
some: {
68+
userId: authenticationResult.result.userId,
6669
},
6770
},
71+
},
6872
project: {
6973
externalRef: projectRef,
7074
},
71-
branchName: parsed.data.branch,
75+
type: environmentType,
76+
branchName: branch,
7277
},
7378
});
7479

apps/webapp/app/routes/resources.branches.archive.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ export function ArchiveButton({
9191
<div className="mt-2 flex flex-col gap-4">
9292
<Form
9393
method="post"
94-
action="/resources/branches/archive"
94+
action="/resources/branssches/archive"
9595
{...form.props}
9696
className="w-full"
9797
>

apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.dev.presence.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ export const loader = createSSELoader({
1414
const userId = await requireUserId(request);
1515
const { organizationSlug, projectParam } = ProjectParamSchema.parse(params);
1616

17+
// TODO support branch dev envs
1718
const environment = await $replica.runtimeEnvironment.findFirst({
1819
where: {
1920
type: "DEVELOPMENT",

apps/webapp/app/services/apiAuth.server.ts

Lines changed: 29 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -305,26 +305,26 @@ function getApiKeyResult(apiKey: string): {
305305
const type = isPublicApiKey(apiKey)
306306
? "PUBLIC"
307307
: isSecretApiKey(apiKey)
308-
? "PRIVATE"
309-
: isPublicJWT(apiKey)
310-
? "PUBLIC_JWT"
311-
: "PRIVATE"; // Fallback to private key
308+
? "PRIVATE"
309+
: isPublicJWT(apiKey)
310+
? "PUBLIC_JWT"
311+
: "PRIVATE"; // Fallback to private key
312312
return { apiKey, type };
313313
}
314314

315315
export type AuthenticationResult =
316316
| {
317-
type: "personalAccessToken";
318-
result: PersonalAccessTokenAuthenticationResult;
319-
}
317+
type: "personalAccessToken";
318+
result: PersonalAccessTokenAuthenticationResult;
319+
}
320320
| {
321-
type: "organizationAccessToken";
322-
result: OrganizationAccessTokenAuthenticationResult;
323-
}
321+
type: "organizationAccessToken";
322+
result: OrganizationAccessTokenAuthenticationResult;
323+
}
324324
| {
325-
type: "apiKey";
326-
result: ApiAuthenticationResult;
327-
};
325+
type: "apiKey";
326+
result: ApiAuthenticationResult;
327+
};
328328

329329
type AuthenticationMethod = "personalAccessToken" | "organizationAccessToken" | "apiKey";
330330

@@ -341,11 +341,11 @@ type FilteredAuthenticationResult<
341341
T extends AllowedAuthenticationMethods = AllowedAuthenticationMethods
342342
> =
343343
| (T["personalAccessToken"] extends true
344-
? Extract<AuthenticationResult, { type: "personalAccessToken" }>
345-
: never)
344+
? Extract<AuthenticationResult, { type: "personalAccessToken" }>
345+
: never)
346346
| (T["organizationAccessToken"] extends true
347-
? Extract<AuthenticationResult, { type: "organizationAccessToken" }>
348-
: never)
347+
? Extract<AuthenticationResult, { type: "organizationAccessToken" }>
348+
: never)
349349
| (T["apiKey"] extends true ? Extract<AuthenticationResult, { type: "apiKey" }> : never);
350350

351351
/**
@@ -501,10 +501,10 @@ export async function authenticatedEnvironmentForAuthentication(
501501
slug: slug,
502502
...(slug === "dev"
503503
? {
504-
orgMember: {
505-
userId: user.id,
506-
},
507-
}
504+
orgMember: {
505+
userId: user.id,
506+
},
507+
}
508508
: {}),
509509
},
510510
include: authIncludeBase,
@@ -520,7 +520,9 @@ export async function authenticatedEnvironmentForAuthentication(
520520
const environment = await $replica.runtimeEnvironment.findFirst({
521521
where: {
522522
projectId: project.id,
523-
type: "PREVIEW",
523+
type: {
524+
in: ["PREVIEW", "DEVELOPMENT"],
525+
},
524526
branchName: sanitizedBranch,
525527
archivedAt: null,
526528
},
@@ -532,10 +534,10 @@ export async function authenticatedEnvironmentForAuthentication(
532534
}
533535

534536
if (!environment.parentEnvironment) {
535-
throw json({ error: "Branch not associated with a preview environment" }, { status: 400 });
537+
throw json({ error: "Branch not associated with a parent environment" }, { status: 400 });
536538
}
537539

538-
// PREVIEW envs reuse the parent's apiKey for downstream auth flows
540+
// PREVIEW envs (and DEVELOPMENT branches) reuse the parent's apiKey for downstream auth flows
539541
// (signed JWTs, internal-fetch helpers). Override before mapping so
540542
// the slim shape carries the parent's key.
541543
return toAuthenticated({
@@ -586,7 +588,9 @@ export async function authenticatedEnvironmentForAuthentication(
586588
const environment = await $replica.runtimeEnvironment.findFirst({
587589
where: {
588590
projectId: project.id,
589-
type: "PREVIEW",
591+
type: {
592+
in: ["PREVIEW", "DEVELOPMENT"],
593+
},
590594
branchName: sanitizedBranch,
591595
archivedAt: null,
592596
},

apps/webapp/app/services/archiveBranch.server.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,13 +56,20 @@ export class ArchiveBranchService {
5656
},
5757
});
5858

59-
if (!environment.parentEnvironmentId) {
59+
if (!environment.parentEnvironmentId || environment.isBranchableEnvironment) {
6060
return {
6161
success: false as const,
6262
error: "This isn't a branch, and cannot be archived.",
6363
};
6464
}
6565

66+
if (environment.type === "DEVELOPMENT" && environment.branchName === null) {
67+
return {
68+
success: false as const,
69+
error: "The default development branch cannot be archived.",
70+
};
71+
}
72+
6673
const slug = `${environment.slug}-${nanoid(6)}`;
6774
const shortcode = slug;
6875

0 commit comments

Comments
 (0)