Skip to content

Commit 6c82530

Browse files
committed
wip3
1 parent d24ca89 commit 6c82530

7 files changed

Lines changed: 68 additions & 64 deletions

File tree

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ export class BranchesPresenter {
135135
});
136136

137137
// Limits
138-
const limits = await checkBranchLimit(this.#prismaClient, project.organizationId, project.id);
138+
const limits = await checkBranchLimit({ prisma: this.#prismaClient, organizationId: project.organizationId, projectId: project.id });
139139

140140
const [currentPlan, plans] = await Promise.all([
141141
getCurrentPlan(project.organizationId),

apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.branches/route.tsx

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ import { BranchesPresenter } from "~/presenters/v3/BranchesPresenter.server";
6767
import { logger } from "~/services/logger.server";
6868
import { getCurrentPlan, getSelfServePurchaseBlockReason } from "~/services/platform.v3.server";
6969
import { requireUserId } from "~/services/session.server";
70-
import { UpsertBranchService } from "~/services/upsertBranch.server";
70+
import { UpsertBranchService, CreateBranchOptions } from "~/services/upsertBranch.server";
7171
import { cn } from "~/utils/cn";
7272
import {
7373
branchesPath,
@@ -114,14 +114,6 @@ export const loader = async ({ request, params }: LoaderFunctionArgs) => {
114114
}
115115
};
116116

117-
export const CreateBranchOptions = z.object({
118-
parentEnvironmentId: z.string(),
119-
branchName: z.string().min(1),
120-
git: GitMeta.optional(),
121-
});
122-
123-
export type CreateBranchOptions = z.infer<typeof CreateBranchOptions>;
124-
125117
export const schema = CreateBranchOptions.and(
126118
z.object({
127119
failurePath: z.string(),

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

Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { json, type LoaderFunctionArgs, type ActionFunctionArgs } from "@remix-run/server-runtime";
22
import { tryCatch, UpsertBranchRequestBody } from "@trigger.dev/core/v3";
3+
import invariant from "tiny-invariant";
34
import { z } from "zod";
45
import { prisma } from "~/db.server";
56
import { authenticateRequest } from "~/services/apiAuth.server";
@@ -47,12 +48,12 @@ export async function action({ request, params }: ActionFunctionArgs) {
4748
authenticationResult.type === "organizationAccessToken"
4849
? { id: authenticationResult.result.organizationId }
4950
: {
50-
members: {
51-
some: {
52-
userId: authenticationResult.result.userId,
53-
},
51+
members: {
52+
some: {
53+
userId: authenticationResult.result.userId,
5454
},
5555
},
56+
},
5657
},
5758
});
5859
if (!project) {
@@ -69,33 +70,31 @@ export async function action({ request, params }: ActionFunctionArgs) {
6970
return json({ error: parsed.error.message }, { status: 400 });
7071
}
7172

72-
const previewEnvironment = await prisma.runtimeEnvironment.findFirst({
73-
select: {
74-
id: true,
75-
},
76-
where: {
77-
projectId: project.id,
78-
slug: "preview",
79-
},
80-
});
73+
const { branch, env, git } = parsed.data;
8174

82-
if (!previewEnvironment) {
75+
if (env === "development" && authenticationResult.type === "organizationAccessToken") {
8376
return json(
84-
{ error: "You don't have preview branches setup. Go to the dashboard to enable them." },
77+
{ error: "Cannot create dev branches with organization access tokens." },
8578
{ status: 400 }
8679
);
8780
}
8881

89-
const { branch, env, git } = parsed.data;
82+
if (env === "development" && branch === "default") {
83+
return json(
84+
{ error: "Cannot create dev branch with name 'default'." },
85+
{ status: 400 }
86+
);
87+
}
9088

9189
const service = new UpsertBranchService();
9290
const result = await service.call(
9391
authenticationResult.type === "organizationAccessToken"
9492
? { type: "orgId", organizationId: authenticationResult.result.organizationId }
9593
: { type: "userMembership", userId: authenticationResult.result.userId },
9694
{
95+
env,
9796
branchName: branch,
98-
parentEnvironmentId: previewEnvironment.id,
97+
projectId: project.id,
9998
git,
10099
}
101100
);

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

Lines changed: 35 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,21 @@ import { type PrismaClient, type PrismaClientOrTransaction } from "@trigger.dev/
22
import slug from "slug";
33
import { prisma } from "~/db.server";
44
import { createApiKeyForEnv, createPkApiKeyForEnv } from "~/models/api-key.server";
5-
import { type CreateBranchOptions } from "~/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.branches/route";
65
import { isValidGitBranchName, sanitizeBranchName } from "@trigger.dev/core/v3/utils/gitBranch";
76
import { logger } from "./logger.server";
87
import { getCurrentPlan, getLimit } from "./platform.v3.server";
8+
import { GitMeta } from "@trigger.dev/core/v3";
9+
import { z } from "zod";
10+
import invariant from "tiny-invariant";
11+
12+
export const CreateBranchOptions = z.object({
13+
projectId: z.string(),
14+
env: z.enum(["preview", "development"]),
15+
branchName: z.string().min(1),
16+
git: GitMeta.optional(),
17+
});
18+
19+
type CreateBranchOptions = z.infer<typeof CreateBranchOptions>;
920

1021
export class UpsertBranchService {
1122
#prismaClient: PrismaClient;
@@ -22,8 +33,12 @@ export class UpsertBranchService {
2233
orgFilter:
2334
| { type: "userMembership"; userId: string }
2435
| { type: "orgId"; organizationId: string },
25-
{ parentEnvironmentId, branchName, git }: CreateBranchOptions
36+
{ projectId, env, branchName, git }: CreateBranchOptions
2637
) {
38+
39+
40+
const parentEnvSlug = env === "preview" ? "preview" : "dev";
41+
2742
const sanitizedBranchName = sanitizeBranchName(branchName);
2843
if (!sanitizedBranchName) {
2944
return {
@@ -42,16 +57,17 @@ export class UpsertBranchService {
4257
try {
4358
const parentEnvironment = await this.#prismaClient.runtimeEnvironment.findFirst({
4459
where: {
45-
id: parentEnvironmentId,
60+
projectId,
61+
slug: parentEnvSlug,
4662
organization:
4763
orgFilter.type === "userMembership"
4864
? {
49-
members: {
50-
some: {
51-
userId: orgFilter.userId,
52-
},
65+
members: {
66+
some: {
67+
userId: orgFilter.userId,
5368
},
54-
}
69+
},
70+
}
5571
: { id: orgFilter.organizationId },
5672
},
5773
include: {
@@ -72,6 +88,7 @@ export class UpsertBranchService {
7288
});
7389

7490
if (!parentEnvironment) {
91+
invariant(env === "preview", "No default dev runtime environment setup");
7592
return {
7693
success: false as const,
7794
error: "You don't have preview branches setup. Go to the dashboard to enable them.",
@@ -81,16 +98,12 @@ export class UpsertBranchService {
8198
if (!parentEnvironment.isBranchableEnvironment) {
8299
return {
83100
success: false as const,
84-
error: "Your preview environment is not branchable",
101+
error: `Your ${env} environment is not branchable`,
85102
};
86103
}
87104

88105
const limits = await checkBranchLimit(
89-
this.#prismaClient,
90-
parentEnvironment.organization.id,
91-
parentEnvironment.project.id,
92-
sanitizedBranchName
93-
);
106+
{ prisma: this.#prismaClient, organizationId: parentEnvironment.organization.id, projectId: parentEnvironment.project.id, newBranchName: sanitizedBranchName });
94107

95108
if (limits.isAtLimit) {
96109
return {
@@ -159,11 +172,11 @@ export class UpsertBranchService {
159172
}
160173

161174
export async function checkBranchLimit(
162-
prisma: PrismaClientOrTransaction,
163-
organizationId: string,
164-
projectId: string,
165-
newBranchName?: string
166-
) {
175+
{ prisma, organizationId, projectId, env, newBranchName }:
176+
{ prisma: PrismaClientOrTransaction; organizationId: string; projectId: string; env: "preview" | "development"; newBranchName?: string; }) {
177+
178+
179+
167180
const usedEnvs = await prisma.runtimeEnvironment.findMany({
168181
where: {
169182
projectId,
@@ -177,7 +190,9 @@ export async function checkBranchLimit(
177190
const count = newBranchName
178191
? usedEnvs.filter((env) => env.branchName !== newBranchName).length
179192
: usedEnvs.length;
180-
const baseLimit = await getLimit(organizationId, "branches", 100_000_000);
193+
194+
const limitName = env === "preview" ? "branches" : "branchesDev";
195+
const baseLimit = await getLimit(organizationId, limitName, 100_000_000);
181196
const currentPlan = await getCurrentPlan(organizationId);
182197
const purchasedBranches = currentPlan?.v3Subscription?.addOns?.branches?.purchased ?? 0;
183198
const limit = baseLimit + purchasedBranches;

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@
9090
"@remix-run/router@1.23.2": "patches/@remix-run__router@1.23.2.patch"
9191
},
9292
"overrides": {
93+
"@trigger.dev/platform": "link:../cloud/packages/platform",
9394
"typescript": "5.5.4",
9495
"@types/node": "20.14.14",
9596
"express@^4>body-parser": "1.20.3",

packages/cli-v3/src/commands/dev.ts

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,13 @@ import { installMcpServer } from "./install-mcp.js";
2727
import { tryCatch } from "@trigger.dev/core/utils";
2828
import { VERSION } from "@trigger.dev/core";
2929
import { initiateSkillsInstallWizard } from "./skills.js";
30+
import { getDevBranch } from "@trigger.dev/core/v3";
3031

3132
const DevCommandOptions = CommonCommandOptions.extend({
3233
debugOtel: z.boolean().default(false),
3334
config: z.string().optional(),
3435
projectRef: z.string().optional(),
35-
branch: z.string().optional().default("branch"),
36+
branch: z.string().optional(),
3637
skipUpdateCheck: z.boolean().default(false),
3738
skipPlatformNotifications: z.boolean().default(false),
3839
envFile: z.string().optional(),
@@ -61,7 +62,6 @@ export function configureDevCommand(program: Command) {
6162
.option(
6263
"-b, --branch <branch>",
6364
"The dev branch to use. If not provided, we'll use the default branch."
64-
"default",
6565
)
6666
.option(
6767
"--env-file <env file>",
@@ -203,10 +203,12 @@ async function startDev(options: StartDevOptions) {
203203
logger.loggerLevel = options.logLevel;
204204
}
205205

206+
const apiClient = new CliApiClient(options.login.auth.apiUrl, options.login.auth.accessToken);
207+
206208
const notificationPromise = options.skipPlatformNotifications
207209
? undefined
208210
: fetchPlatformNotification({
209-
apiClient: new CliApiClient(options.login.auth.apiUrl, options.login.auth.accessToken),
211+
apiClient,
210212
projectRef: options.projectRef,
211213
});
212214

@@ -251,6 +253,12 @@ async function startDev(options: StartDevOptions) {
251253

252254
logger.debug("Initial config", watcher.config);
253255

256+
const branch = getDevBranch({ specified: options.branch });
257+
258+
if (branch !== "default") {
259+
apiClient.upsertBranch(watcher.config.project, { branch, env: "development" });
260+
}
261+
254262
// eslint-disable-next-line no-inner-declarations
255263
async function bootDevSession(configParam: ResolvedConfig) {
256264
const projectClient = await getProjectClient({

pnpm-lock.yaml

Lines changed: 3 additions & 14 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)