Skip to content

Commit 4347499

Browse files
authored
fix(api): Fix preview branch targeting in environment variable API routes (#2697)
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 abee783 commit 4347499

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
@@ -495,7 +495,9 @@ export async function authenticatedEnvironmentForAuthentication(
495495
throw json({ error: "Project not found" }, { status: 404 });
496496
}
497497

498-
if (!branch) {
498+
const sanitizedBranch = sanitizeBranchName(branch);
499+
500+
if (!sanitizedBranch) {
499501
const environment = await prisma.runtimeEnvironment.findFirst({
500502
where: {
501503
projectId: project.id,
@@ -524,8 +526,8 @@ export async function authenticatedEnvironmentForAuthentication(
524526
const environment = await prisma.runtimeEnvironment.findFirst({
525527
where: {
526528
projectId: project.id,
527-
slug: slug,
528-
branchName: sanitizeBranchName(branch),
529+
type: "PREVIEW",
530+
branchName: sanitizedBranch,
529531
archivedAt: null,
530532
},
531533
include: {
@@ -572,7 +574,9 @@ export async function authenticatedEnvironmentForAuthentication(
572574
throw json({ error: "Project not found" }, { status: 404 });
573575
}
574576

575-
if (!branch) {
577+
const sanitizedBranch = sanitizeBranchName(branch);
578+
579+
if (!sanitizedBranch) {
576580
const environment = await prisma.runtimeEnvironment.findFirst({
577581
where: {
578582
projectId: project.id,
@@ -594,8 +598,8 @@ export async function authenticatedEnvironmentForAuthentication(
594598
const environment = await prisma.runtimeEnvironment.findFirst({
595599
where: {
596600
projectId: project.id,
597-
slug: slug,
598-
branchName: sanitizeBranchName(branch),
601+
type: "PREVIEW",
602+
branchName: sanitizedBranch,
599603
archivedAt: null,
600604
},
601605
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)