bypass Vercel deployment protection on preview API calls
action API calls to preview deployments were getting 401'd by Vercel's deployment protection. add x-vercel-protection-bypass header to the 3 server-to-server fetch sites when VERCEL_AUTOMATION_BYPASS_SECRET is set. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
committed by
pullfrog[bot]
parent
d7759734f2
commit
dc611c9f78
@@ -139418,7 +139418,14 @@ var Octokit2 = Octokit.plugin(requestLog, legacyRestEndpointMethods, paginateRes
|
|||||||
|
|
||||||
// utils/apiUrl.ts
|
// utils/apiUrl.ts
|
||||||
function getApiUrl() {
|
function getApiUrl() {
|
||||||
return process.env.API_URL || "https://pullfrog.com";
|
const url4 = process.env.API_URL || "https://pullfrog.com";
|
||||||
|
log.debug(`resolved API_URL: ${url4}`);
|
||||||
|
return url4;
|
||||||
|
}
|
||||||
|
function getVercelBypassHeaders() {
|
||||||
|
const secret = process.env.VERCEL_AUTOMATION_BYPASS_SECRET;
|
||||||
|
if (!secret) return {};
|
||||||
|
return { "x-vercel-protection-bypass": secret };
|
||||||
}
|
}
|
||||||
|
|
||||||
// utils/retry.ts
|
// utils/retry.ts
|
||||||
@@ -139477,7 +139484,8 @@ async function acquireTokenViaOIDC(opts) {
|
|||||||
method: "POST",
|
method: "POST",
|
||||||
headers: {
|
headers: {
|
||||||
Authorization: `Bearer ${oidcToken}`,
|
Authorization: `Bearer ${oidcToken}`,
|
||||||
"Content-Type": "application/json"
|
"Content-Type": "application/json",
|
||||||
|
...getVercelBypassHeaders()
|
||||||
},
|
},
|
||||||
signal: controller.signal
|
signal: controller.signal
|
||||||
};
|
};
|
||||||
@@ -144014,7 +144022,8 @@ function UploadFileTool(ctx) {
|
|||||||
method: "POST",
|
method: "POST",
|
||||||
headers: {
|
headers: {
|
||||||
Authorization: `Bearer ${ctx.apiToken}`,
|
Authorization: `Bearer ${ctx.apiToken}`,
|
||||||
"Content-Type": "application/json"
|
"Content-Type": "application/json",
|
||||||
|
...getVercelBypassHeaders()
|
||||||
},
|
},
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
filename,
|
filename,
|
||||||
@@ -146731,7 +146740,8 @@ async function fetchRunContext(params) {
|
|||||||
method: "GET",
|
method: "GET",
|
||||||
headers: {
|
headers: {
|
||||||
Authorization: `Bearer ${params.token}`,
|
Authorization: `Bearer ${params.token}`,
|
||||||
"Content-Type": "application/json"
|
"Content-Type": "application/json",
|
||||||
|
...getVercelBypassHeaders()
|
||||||
},
|
},
|
||||||
signal: controller.signal
|
signal: controller.signal
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25682,7 +25682,14 @@ import { createSign } from "node:crypto";
|
|||||||
|
|
||||||
// utils/apiUrl.ts
|
// utils/apiUrl.ts
|
||||||
function getApiUrl() {
|
function getApiUrl() {
|
||||||
return process.env.API_URL || "https://pullfrog.com";
|
const url = process.env.API_URL || "https://pullfrog.com";
|
||||||
|
log.debug(`resolved API_URL: ${url}`);
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
function getVercelBypassHeaders() {
|
||||||
|
const secret = process.env.VERCEL_AUTOMATION_BYPASS_SECRET;
|
||||||
|
if (!secret) return {};
|
||||||
|
return { "x-vercel-protection-bypass": secret };
|
||||||
}
|
}
|
||||||
|
|
||||||
// utils/retry.ts
|
// utils/retry.ts
|
||||||
@@ -25741,7 +25748,8 @@ async function acquireTokenViaOIDC(opts) {
|
|||||||
method: "POST",
|
method: "POST",
|
||||||
headers: {
|
headers: {
|
||||||
Authorization: `Bearer ${oidcToken}`,
|
Authorization: `Bearer ${oidcToken}`,
|
||||||
"Content-Type": "application/json"
|
"Content-Type": "application/json",
|
||||||
|
...getVercelBypassHeaders()
|
||||||
},
|
},
|
||||||
signal: controller.signal
|
signal: controller.signal
|
||||||
};
|
};
|
||||||
|
|||||||
+2
-1
@@ -2,7 +2,7 @@ import * as fs from "node:fs";
|
|||||||
import * as path from "node:path";
|
import * as path from "node:path";
|
||||||
import { type } from "arktype";
|
import { type } from "arktype";
|
||||||
import { fileTypeFromBuffer } from "file-type";
|
import { fileTypeFromBuffer } from "file-type";
|
||||||
import { getApiUrl } from "../utils/apiUrl.ts";
|
import { getApiUrl, getVercelBypassHeaders } from "../utils/apiUrl.ts";
|
||||||
import type { ToolContext } from "./server.ts";
|
import type { ToolContext } from "./server.ts";
|
||||||
import { execute, tool } from "./shared.ts";
|
import { execute, tool } from "./shared.ts";
|
||||||
|
|
||||||
@@ -32,6 +32,7 @@ export function UploadFileTool(ctx: ToolContext) {
|
|||||||
headers: {
|
headers: {
|
||||||
Authorization: `Bearer ${ctx.apiToken}`,
|
Authorization: `Bearer ${ctx.apiToken}`,
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
|
...getVercelBypassHeaders(),
|
||||||
},
|
},
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
filename,
|
filename,
|
||||||
|
|||||||
+16
-1
@@ -1,3 +1,5 @@
|
|||||||
|
import { log } from "./cli.ts";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* resolve the Pullfrog API base URL.
|
* resolve the Pullfrog API base URL.
|
||||||
*
|
*
|
||||||
@@ -5,5 +7,18 @@
|
|||||||
* in local dev: API_URL=http://localhost:3000 (from .env).
|
* in local dev: API_URL=http://localhost:3000 (from .env).
|
||||||
*/
|
*/
|
||||||
export function getApiUrl(): string {
|
export function getApiUrl(): string {
|
||||||
return process.env.API_URL || "https://pullfrog.com";
|
const url = process.env.API_URL || "https://pullfrog.com";
|
||||||
|
log.debug(`resolved API_URL: ${url}`);
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* returns headers needed to bypass Vercel deployment protection on preview deployments.
|
||||||
|
* when VERCEL_AUTOMATION_BYPASS_SECRET is set (preview repos), includes the bypass header.
|
||||||
|
* otherwise returns an empty object (production / local dev).
|
||||||
|
*/
|
||||||
|
export function getVercelBypassHeaders(): Record<string, string> {
|
||||||
|
const secret = process.env.VERCEL_AUTOMATION_BYPASS_SECRET;
|
||||||
|
if (!secret) return {};
|
||||||
|
return { "x-vercel-protection-bypass": secret };
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-1
@@ -2,7 +2,7 @@ import { createSign } from "node:crypto";
|
|||||||
import * as core from "@actions/core";
|
import * as core from "@actions/core";
|
||||||
import { throttling } from "@octokit/plugin-throttling";
|
import { throttling } from "@octokit/plugin-throttling";
|
||||||
import { Octokit } from "@octokit/rest";
|
import { Octokit } from "@octokit/rest";
|
||||||
import { getApiUrl } from "./apiUrl.ts";
|
import { getApiUrl, getVercelBypassHeaders } from "./apiUrl.ts";
|
||||||
import { retry } from "./retry.ts";
|
import { retry } from "./retry.ts";
|
||||||
|
|
||||||
export interface InstallationToken {
|
export interface InstallationToken {
|
||||||
@@ -109,6 +109,7 @@ async function acquireTokenViaOIDC(opts?: AcquireTokenOptions): Promise<string>
|
|||||||
headers: {
|
headers: {
|
||||||
Authorization: `Bearer ${oidcToken}`,
|
Authorization: `Bearer ${oidcToken}`,
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
|
...getVercelBypassHeaders(),
|
||||||
},
|
},
|
||||||
signal: controller.signal,
|
signal: controller.signal,
|
||||||
};
|
};
|
||||||
|
|||||||
+2
-1
@@ -1,5 +1,5 @@
|
|||||||
import type { AgentName, BashPermission, PushPermission, ToolPermission } from "../external.ts";
|
import type { AgentName, BashPermission, PushPermission, ToolPermission } from "../external.ts";
|
||||||
import { getApiUrl } from "./apiUrl.ts";
|
import { getApiUrl, getVercelBypassHeaders } from "./apiUrl.ts";
|
||||||
import type { RepoContext } from "./github.ts";
|
import type { RepoContext } from "./github.ts";
|
||||||
|
|
||||||
export interface Mode {
|
export interface Mode {
|
||||||
@@ -65,6 +65,7 @@ export async function fetchRunContext(params: {
|
|||||||
headers: {
|
headers: {
|
||||||
Authorization: `Bearer ${params.token}`,
|
Authorization: `Bearer ${params.token}`,
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
|
...getVercelBypassHeaders(),
|
||||||
},
|
},
|
||||||
signal: controller.signal,
|
signal: controller.signal,
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user