Skip to content

Commit 8da78dd

Browse files
committed
fix(dashboard-agent): keep the branch when scheduling a watch
1 parent 05e314e commit 8da78dd

2 files changed

Lines changed: 72 additions & 2 deletions

File tree

‎internal-packages/dashboard-agent/src/watch-tools.test.ts‎

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,75 @@ describe("schedule_watch project/environment override", () => {
117117
});
118118
});
119119

120+
describe("schedule_watch branch override", () => {
121+
// Parent and branch resolve to different env ids, so a dropped branch is caught by
122+
// the id (not just by the header sent).
123+
function stubBranchFetch() {
124+
return vi.fn(async (input: any, init: any) => {
125+
const url = typeof input === "string" ? input : input.url;
126+
calls.push(url);
127+
const branch = init?.headers?.["x-trigger-branch"];
128+
const match = url.match(/\/api\/v1\/projects\/([^/]+)\/([^/]+)\/jwt$/);
129+
if (match) {
130+
const sub = branch
131+
? `env_${match[1]}_${match[2]}_${branch}`
132+
: `env_${match[1]}_${match[2]}_parent`;
133+
return Response.json({ token: fakeJwt(sub) });
134+
}
135+
return new Response("not found", { status: 404 });
136+
});
137+
}
138+
139+
it("resolves the branch child's environment id, not the preview parent's", async () => {
140+
vi.stubGlobal("fetch", stubBranchFetch());
141+
const t = tools();
142+
143+
const result = await (t.schedule_watch as any).execute(
144+
{ watch: WATCH, project: "proj_other", environment: "preview", branch: "feat/x" },
145+
{} as any
146+
);
147+
148+
expect(result.error).toBeUndefined();
149+
expect(calls).toEqual([`${ORIGIN}/api/v1/projects/proj_other/preview/jwt`]);
150+
expect(result.intent).toEqual({
151+
kind: "watch",
152+
spec: WATCH,
153+
target: { projectRef: "proj_other", environmentId: "env_proj_other_preview_feat/x" },
154+
});
155+
});
156+
157+
it("resolves the branch child's environment id for a dev branch", async () => {
158+
vi.stubGlobal("fetch", stubBranchFetch());
159+
const t = tools();
160+
161+
const result = await (t.schedule_watch as any).execute(
162+
{ watch: WATCH, project: "proj_other", environment: "dev", branch: "feat/x" },
163+
{} as any
164+
);
165+
166+
expect(result.intent.target).toEqual({
167+
projectRef: "proj_other",
168+
environmentId: "env_proj_other_dev_feat/x",
169+
});
170+
});
171+
172+
it("resolves the current project's branch child when only branch is given", async () => {
173+
vi.stubGlobal("fetch", stubBranchFetch());
174+
const t = tools();
175+
176+
const result = await (t.schedule_watch as any).execute(
177+
{ watch: WATCH, branch: "feat/x" },
178+
{} as any
179+
);
180+
181+
expect(calls).toEqual([`${ORIGIN}/api/v1/projects/proj_current/prod/jwt`]);
182+
expect(result.intent.target).toEqual({
183+
projectRef: "proj_current",
184+
environmentId: "env_proj_current_prod_feat/x",
185+
});
186+
});
187+
});
188+
120189
describe("scheduleWatchSchema round-trip", () => {
121190
it("accepts project/environment and stays valid without them", () => {
122191
const inputSchema = scheduleWatchSchema.inputSchema as ZodTypeAny;

‎internal-packages/dashboard-agent/src/watch-tools.ts‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,12 @@ export function buildWatchTools(args: {
1616
// it, so the card owns consent, the cap and dedup.
1717
schedule_watch: tool({
1818
...scheduleWatchSchema,
19-
execute: async ({ watch, project, environment }) => {
19+
execute: async ({ watch, project, environment, branch }) => {
2020
let target: { projectRef: string; environmentId: string } | undefined;
2121

2222
// Only reached to spend a network call: the current-environment path (no
2323
// override) stays pure schema validation, unchanged from before.
24-
if (project || environment) {
24+
if (project || environment || branch) {
2525
if (!client.hasAuth) return NO_AUTH;
2626
const projectRef = project ?? ctx.projectRef;
2727
if (!projectRef) {
@@ -30,6 +30,7 @@ export function buildWatchTools(args: {
3030
const resolved = await client.resolveEnvironmentId({
3131
projectRef: project,
3232
environmentName: environment,
33+
branch,
3334
});
3435
if (isEnvUnavailable(resolved)) {
3536
if (resolved.envUnavailable === "missing") {

0 commit comments

Comments
 (0)