Forward API calls from the preview repos (#211)

* Forward API calls from the preview repos

* tweak doc

* tweak

* fix workflow-run forwarding
This commit is contained in:
Mateusz Burzyński
2026-01-30 11:32:14 +00:00
committed by pullfrog[bot]
parent c1f8247077
commit 2b3bd97b86
4 changed files with 27 additions and 12 deletions
+9 -6
View File
@@ -162630,15 +162630,18 @@ var Timer = class {
}; };
// utils/workflowRun.ts // utils/workflowRun.ts
async function fetchWorkflowRunInfo(runId) { async function fetchWorkflowRunInfo(params) {
const apiUrl = process.env.API_URL || "https://pullfrog.com"; const apiUrl = process.env.API_URL || "https://pullfrog.com";
const timeoutMs = 3e4; const timeoutMs = 3e4;
const controller = new AbortController(); const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), timeoutMs); const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
try { try {
const response = await fetch(`${apiUrl}/api/workflow-run/${runId}`, { const response = await fetch(`${apiUrl}/api/workflow-run/${params.runId}`, {
method: "GET", method: "GET",
headers: { headers: {
// apiToken not strictly required (route only exposes public IDs)
// but claims in token enable preview API URL forwarding
Authorization: `Bearer ${params.apiToken}`,
"Content-Type": "application/json" "Content-Type": "application/json"
}, },
signal: controller.signal signal: controller.signal
@@ -162663,7 +162666,7 @@ async function resolveRun(params) {
throw new Error(`GITHUB_REPOSITORY env var must be set to "owner/repo", got: ${githubRepo}`); throw new Error(`GITHUB_REPOSITORY env var must be set to "owner/repo", got: ${githubRepo}`);
} }
const [owner, repo] = githubRepo.split("/"); const [owner, repo] = githubRepo.split("/");
const workflowRunInfo = runId ? await fetchWorkflowRunInfo(runId) : { progressCommentId: null }; const workflowRunInfo = runId ? await fetchWorkflowRunInfo({ runId, apiToken: params.apiToken }) : { progressCommentId: null };
if (workflowRunInfo.progressCommentId) { if (workflowRunInfo.progressCommentId) {
log.info(`\xBB using pre-created progress comment: ${workflowRunInfo.progressCommentId}`); log.info(`\xBB using pre-created progress comment: ${workflowRunInfo.progressCommentId}`);
} }
@@ -162692,14 +162695,14 @@ async function main() {
const timer = new Timer(); const timer = new Timer();
const tokenRef = __using(_stack2, await resolveInstallationToken(), true); const tokenRef = __using(_stack2, await resolveInstallationToken(), true);
const octokit = createOctokit(tokenRef.token); const octokit = createOctokit(tokenRef.token);
const runInfo = await resolveRun({ octokit }); const runContext = await resolveRunContextData({ octokit, token: tokenRef.token });
timer.checkpoint("runContextData");
const runInfo = await resolveRun({ octokit, apiToken: runContext.apiToken });
const toolState = initToolState({ runInfo }); const toolState = initToolState({ runInfo });
setupExitHandler(toolState); setupExitHandler(toolState);
try { try {
var _stack = []; var _stack = [];
try { try {
const runContext = await resolveRunContextData({ octokit, token: tokenRef.token });
timer.checkpoint("runContextData");
const payload = resolvePayload(runContext.repoSettings); const payload = resolvePayload(runContext.repoSettings);
if (payload.cwd && process.cwd() !== payload.cwd) { if (payload.cwd && process.cwd() !== payload.cwd) {
process.chdir(payload.cwd); process.chdir(payload.cwd);
+4 -3
View File
@@ -37,14 +37,15 @@ export async function main(): Promise<MainResult> {
await using tokenRef = await resolveInstallationToken(); await using tokenRef = await resolveInstallationToken();
const octokit = createOctokit(tokenRef.token); const octokit = createOctokit(tokenRef.token);
const runInfo = await resolveRun({ octokit }); const runContext = await resolveRunContextData({ octokit, token: tokenRef.token });
timer.checkpoint("runContextData");
const runInfo = await resolveRun({ octokit, apiToken: runContext.apiToken });
const toolState = initToolState({ runInfo }); const toolState = initToolState({ runInfo });
setupExitHandler(toolState); setupExitHandler(toolState);
try { try {
const runContext = await resolveRunContextData({ octokit, token: tokenRef.token });
timer.checkpoint("runContextData");
// resolve payload after runContextData so permissions can use DB settings // resolve payload after runContextData so permissions can use DB settings
// precedence: action inputs > json payload > repoSettings > fallbacks // precedence: action inputs > json payload > repoSettings > fallbacks
+4 -1
View File
@@ -4,6 +4,7 @@ import { fetchWorkflowRunInfo, type WorkflowRunInfo } from "./workflowRun.ts";
interface ResolveRunParams { interface ResolveRunParams {
octokit: OctokitWithPlugins; octokit: OctokitWithPlugins;
apiToken: string;
} }
export interface ResolveRunResult { export interface ResolveRunResult {
@@ -24,7 +25,9 @@ export async function resolveRun(params: ResolveRunParams): Promise<ResolveRunRe
} }
const [owner, repo] = githubRepo.split("/"); const [owner, repo] = githubRepo.split("/");
const workflowRunInfo = runId ? await fetchWorkflowRunInfo(runId) : { progressCommentId: null }; const workflowRunInfo = runId
? await fetchWorkflowRunInfo({ runId, apiToken: params.apiToken })
: { progressCommentId: null };
if (workflowRunInfo.progressCommentId) { if (workflowRunInfo.progressCommentId) {
log.info(`» using pre-created progress comment: ${workflowRunInfo.progressCommentId}`); log.info(`» using pre-created progress comment: ${workflowRunInfo.progressCommentId}`);
+10 -2
View File
@@ -2,20 +2,28 @@ export interface WorkflowRunInfo {
progressCommentId: string | null; progressCommentId: string | null;
} }
interface FetchWorkflowRunInfoParams {
runId: string;
apiToken: string;
}
/** /**
* Fetch workflow run info from the Pullfrog API. * Fetch workflow run info from the Pullfrog API.
* Returns the pre-created progress comment ID if one exists. * Returns the pre-created progress comment ID if one exists.
*/ */
export async function fetchWorkflowRunInfo(runId: string): Promise<WorkflowRunInfo> { export async function fetchWorkflowRunInfo(params: FetchWorkflowRunInfoParams): Promise<WorkflowRunInfo> {
const apiUrl = process.env.API_URL || "https://pullfrog.com"; const apiUrl = process.env.API_URL || "https://pullfrog.com";
const timeoutMs = 30000; const timeoutMs = 30000;
const controller = new AbortController(); const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), timeoutMs); const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
try { try {
const response = await fetch(`${apiUrl}/api/workflow-run/${runId}`, { const response = await fetch(`${apiUrl}/api/workflow-run/${params.runId}`, {
method: "GET", method: "GET",
headers: { headers: {
// apiToken not strictly required (route only exposes public IDs)
// but claims in token enable preview API URL forwarding
Authorization: `Bearer ${params.apiToken}`,
"Content-Type": "application/json", "Content-Type": "application/json",
}, },
signal: controller.signal, signal: controller.signal,