From 0b87fa0e1299577be3316f37bfa00b655d532f24 Mon Sep 17 00:00:00 2001 From: Codeflash Bot Date: Wed, 21 Jan 2026 16:04:13 +0200 Subject: [PATCH] Refactor GitHub App installation error handling in code context hash endpoints. Introduced a dedicated assertion function to streamline error validation and improve logging for installation issues. --- js/cf-api/endpoints/code-context-hash.ts | 61 ++++++++++++------------ 1 file changed, 31 insertions(+), 30 deletions(-) diff --git a/js/cf-api/endpoints/code-context-hash.ts b/js/cf-api/endpoints/code-context-hash.ts index 652e56dc0..b70c36f27 100644 --- a/js/cf-api/endpoints/code-context-hash.ts +++ b/js/cf-api/endpoints/code-context-hash.ts @@ -1,5 +1,6 @@ import { prisma } from "@codeflash-ai/common" import { Request, Response } from "express" +import { Octokit } from "@octokit/core" import { githubApp } from "../github/github-app.js" import { getInstallationOctokitByOwner, isUserCollaborator } from "../github/github-utils.js" import { userNickname } from "../auth0-mgmt.js" @@ -16,6 +17,34 @@ import { githubInstallationError, } from "../exceptions/index.js" +const GITHUB_APP_INSTALL_LINK = "https://github.com/apps/codeflash-ai/installations/select_target" + +/** + * Validates the installation octokit result and throws appropriate errors if it's an Error. + * Uses TypeScript assertion to narrow the type to Octokit on success. + */ +function assertInstallationOctokit( + octokit: Octokit | Error, + owner: string, + repo: string, + req: Request, +): asserts octokit is Octokit { + if (!(octokit instanceof Error)) return + + const repoPath = `${owner}/${repo}` + const errorMessage = octokit.message + + if (errorMessage.includes("not installed")) { + logger.warn("GitHub App not installed on repository", req, { + repo: repoPath, + installationLink: GITHUB_APP_INSTALL_LINK, + }) + throw githubInstallationNotFound(`${repoPath}. Please install the GitHub App at: ${GITHUB_APP_INSTALL_LINK}`) + } else { + throw githubInstallationError(errorMessage) + } +} + export async function is_code_being_optimized_again(req: Request, res: Response) { try { const { owner, repo, pr_number, code_contexts } = req.body @@ -29,21 +58,7 @@ export async function is_code_being_optimized_again(req: Request, res: Response) throw unauthorized("") } const octokit = await getInstallationOctokitByOwner(githubApp, owner, repo, userId) - if (octokit instanceof Error) { - const errorMessage = octokit.message - if (errorMessage.includes("not installed")) { - const installationLink = "https://github.com/apps/codeflash-ai/installations/select_target" - logger.warn("GitHub App not installed on repository", req, { - repo: `${owner}/${repo}`, - installationLink, - }) - throw githubInstallationNotFound( - `${owner}/${repo}. Please install the GitHub App at: ${installationLink}`, - ) - } else { - throw githubInstallationError(errorMessage) - } - } + assertInstallationOctokit(octokit, owner, repo, req) // Check collaborator status with error handling try { @@ -177,21 +192,7 @@ export async function add_optimized_code_context(req: Request, res: Response) { } const octokit = await getInstallationOctokitByOwner(githubApp, owner, repo, userId) - if (octokit instanceof Error) { - const errorMessage = octokit.message - if (errorMessage.includes("not installed")) { - const installationLink = "https://github.com/apps/codeflash-ai/installations/select_target" - logger.warn("GitHub App not installed on repository", req, { - repo: `${owner}/${repo}`, - installationLink, - }) - throw githubInstallationNotFound( - `${owner}/${repo}. Please install the GitHub App at: ${installationLink}`, - ) - } else { - throw githubInstallationError(errorMessage) - } - } + assertInstallationOctokit(octokit, owner, repo, req) // Check collaborator status with error handling try {