From 12ff6daf32e8f017373bafa7fd58d0074db1dcd1 Mon Sep 17 00:00:00 2001 From: Anthony Ettinger Date: Sat, 23 May 2026 11:00:03 +0000 Subject: [PATCH] Use fresh GitHub token permissions for action installs --- .../actions/[actionId]/install/route.ts | 35 ++++++++++++++----- 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/sites/sh1pt.com/app/api/v1/github/installations/[id]/repos/[repoId]/actions/[actionId]/install/route.ts b/sites/sh1pt.com/app/api/v1/github/installations/[id]/repos/[repoId]/actions/[actionId]/install/route.ts index 11b2a881..0da22e73 100644 --- a/sites/sh1pt.com/app/api/v1/github/installations/[id]/repos/[repoId]/actions/[actionId]/install/route.ts +++ b/sites/sh1pt.com/app/api/v1/github/installations/[id]/repos/[repoId]/actions/[actionId]/install/route.ts @@ -74,15 +74,6 @@ export async function POST( if (!entry.manifest.compatibility.providers.includes('github')) { return NextResponse.json({ error: 'Action does not support GitHub' }, { status: 400 }); } - if (requiresWorkflowWrite(entry.manifest.files) && !hasWorkflowWrite(auth.installation.permissions)) { - return NextResponse.json( - { - error: - 'GitHub App needs Workflows: write permission to install actions into .github/workflows. Update the sh1pt GitHub App permissions, accept the installation update in GitHub, then retry.', - }, - { status: 403 }, - ); - } let render; try { @@ -102,6 +93,24 @@ export async function POST( if (!token.ok || !token.data) { return NextResponse.json({ error: token.error ?? 'Could not mint installation token' }, { status: token.status || 500 }); } + if (token.data.permissions) { + await admin + .from('github_installations') + .update({ permissions: token.data.permissions, updated_at: new Date().toISOString() }) + .eq('id', auth.installation.id); + } + if ( + requiresWorkflowWrite(entry.manifest.files) && + !hasFreshWorkflowWrite(token.data.permissions, auth.installation.permissions) + ) { + return NextResponse.json( + { + error: + 'GitHub App needs Workflows: write permission to install actions into .github/workflows. Update the sh1pt GitHub App permissions, accept the installation update in GitHub, then retry.', + }, + { status: 403 }, + ); + } const outcome = await openPackPullRequest({ client: { token: token.data.token }, @@ -145,6 +154,14 @@ function hasWorkflowWrite(permissions: Record | null | undefined return permissions?.workflows === 'write'; } +function hasFreshWorkflowWrite( + tokenPermissions: Record | null | undefined, + storedPermissions: Record | null | undefined, +): boolean { + if (tokenPermissions) return hasWorkflowWrite(tokenPermissions); + return hasWorkflowWrite(storedPermissions); +} + function normalizeInputs(value: unknown): { ok: true; value: RenderInputs } | { ok: false; error: string } { if (value === undefined) return { ok: true, value: {} }; if (!value || typeof value !== 'object' || Array.isArray(value)) {