Skip to content

Commit 055b078

Browse files
committed
fix(api): Fix preview branch targeting in environment variable API routes
This PR fixes the `x-trigger-branch` header support for targeting specific preview branches when managing environment variables. The header was documented but not actually being extracted or used in the environment variable API routes. Additionally, the query logic in `authenticatedEnvironmentForAuthentication` was fundamentally broken—it searched for environments with both `slug: "preview"` (parent environment property) AND a specific `branchName` (child environment property), which no environment could satisfy simultaneously. The fix extracts the branch name using `branchNameFromRequest()` and correctly queries for child branch environments using `type: "PREVIEW"` and the specific `branchName`. This ensures that environment variable operations (create, update, get, list) properly target individual preview branches instead of affecting all preview environments.
1 parent 6464eee commit 055b078

6 files changed

+27
-13
lines changed

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { env as processEnv } from "~/env.server";
55
import {
66
authenticatedEnvironmentForAuthentication,
77
authenticateRequest,
8+
branchNameFromRequest,
89
} from "~/services/apiAuth.server";
910

1011
const ParamsSchema = z.object({
@@ -32,7 +33,8 @@ export async function loader({ request, params }: LoaderFunctionArgs) {
3233
const environment = await authenticatedEnvironmentForAuthentication(
3334
authenticationResult,
3435
projectRef,
35-
env
36+
env,
37+
branchNameFromRequest(request)
3638
);
3739

3840
const result: GetProjectEnvResponse = {

apps/webapp/app/routes/api.v1.projects.$projectRef.background-workers.$envSlug.$version.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { prisma } from "~/db.server";
44
import {
55
authenticateRequest,
66
authenticatedEnvironmentForAuthentication,
7+
branchNameFromRequest,
78
} from "~/services/apiAuth.server";
89
import zlib from "node:zlib";
910

@@ -29,7 +30,8 @@ export async function loader({ params, request }: LoaderFunctionArgs) {
2930
const environment = await authenticatedEnvironmentForAuthentication(
3031
authenticationResult,
3132
parsedParams.data.projectRef,
32-
parsedParams.data.envSlug
33+
parsedParams.data.envSlug,
34+
branchNameFromRequest(request)
3335
);
3436

3537
// Find the background worker and tasks and files

apps/webapp/app/routes/api.v1.projects.$projectRef.envvars.$slug.$name.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { prisma } from "~/db.server";
55
import {
66
authenticateRequest,
77
authenticatedEnvironmentForAuthentication,
8+
branchNameFromRequest,
89
} from "~/services/apiAuth.server";
910
import { EnvironmentVariablesRepository } from "~/v3/environmentVariables/environmentVariablesRepository.server";
1011

@@ -30,7 +31,8 @@ export async function action({ params, request }: ActionFunctionArgs) {
3031
const environment = await authenticatedEnvironmentForAuthentication(
3132
authenticationResult,
3233
parsedParams.data.projectRef,
33-
parsedParams.data.slug
34+
parsedParams.data.slug,
35+
branchNameFromRequest(request)
3436
);
3537

3638
// Find the environment variable
@@ -106,7 +108,8 @@ export async function loader({ params, request }: LoaderFunctionArgs) {
106108
const environment = await authenticatedEnvironmentForAuthentication(
107109
authenticationResult,
108110
parsedParams.data.projectRef,
109-
parsedParams.data.slug
111+
parsedParams.data.slug,
112+
branchNameFromRequest(request)
110113
);
111114

112115
// Find the environment variable

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

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { z } from "zod";
44
import {
55
authenticateRequest,
66
authenticatedEnvironmentForAuthentication,
7+
branchNameFromRequest,
78
} from "~/services/apiAuth.server";
89
import { EnvironmentVariablesRepository } from "~/v3/environmentVariables/environmentVariablesRepository.server";
910

@@ -28,7 +29,8 @@ export async function action({ params, request }: ActionFunctionArgs) {
2829
const environment = await authenticatedEnvironmentForAuthentication(
2930
authenticationResult,
3031
parsedParams.data.projectRef,
31-
parsedParams.data.slug
32+
parsedParams.data.slug,
33+
branchNameFromRequest(request)
3234
);
3335

3436
const jsonBody = await request.json();
@@ -75,7 +77,8 @@ export async function loader({ params, request }: LoaderFunctionArgs) {
7577
const environment = await authenticatedEnvironmentForAuthentication(
7678
authenticationResult,
7779
parsedParams.data.projectRef,
78-
parsedParams.data.slug
80+
parsedParams.data.slug,
81+
branchNameFromRequest(request)
7982
);
8083

8184
const repository = new EnvironmentVariablesRepository();

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

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -497,7 +497,9 @@ export async function authenticatedEnvironmentForAuthentication(
497497
throw json({ error: "Project not found" }, { status: 404 });
498498
}
499499

500-
if (!branch) {
500+
const sanitizedBranch = sanitizeBranchName(branch);
501+
502+
if (!sanitizedBranch) {
501503
const environment = await prisma.runtimeEnvironment.findFirst({
502504
where: {
503505
projectId: project.id,
@@ -526,8 +528,8 @@ export async function authenticatedEnvironmentForAuthentication(
526528
const environment = await prisma.runtimeEnvironment.findFirst({
527529
where: {
528530
projectId: project.id,
529-
slug: slug,
530-
branchName: sanitizeBranchName(branch),
531+
type: "PREVIEW",
532+
branchName: sanitizedBranch,
531533
archivedAt: null,
532534
},
533535
include: {
@@ -574,7 +576,9 @@ export async function authenticatedEnvironmentForAuthentication(
574576
throw json({ error: "Project not found" }, { status: 404 });
575577
}
576578

577-
if (!branch) {
579+
const sanitizedBranch = sanitizeBranchName(branch);
580+
581+
if (!sanitizedBranch) {
578582
const environment = await prisma.runtimeEnvironment.findFirst({
579583
where: {
580584
projectId: project.id,
@@ -596,8 +600,8 @@ export async function authenticatedEnvironmentForAuthentication(
596600
const environment = await prisma.runtimeEnvironment.findFirst({
597601
where: {
598602
projectId: project.id,
599-
slug: slug,
600-
branchName: sanitizeBranchName(branch),
603+
type: "PREVIEW",
604+
branchName: sanitizedBranch,
601605
archivedAt: null,
602606
},
603607
include: {

apps/webapp/app/v3/gitBranch.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ export function isValidGitBranchName(branch: string): boolean {
2929
return true;
3030
}
3131

32-
export function sanitizeBranchName(ref: string): string | null {
32+
export function sanitizeBranchName(ref: string | undefined): string | null {
3333
if (!ref) return null;
3434
if (ref.startsWith("refs/heads/")) return ref.substring("refs/heads/".length);
3535
if (ref.startsWith("refs/remotes/")) return ref.substring("refs/remotes/".length);

0 commit comments

Comments
 (0)