@@ -2,8 +2,10 @@ import { getWebhooksDb } from '@/db';
22import { webhookDeliveries } from '@/db/schemas/github/webhooks' ;
33import { desc , gt , and , like } from 'drizzle-orm' ;
44import { createGitHubIssue , createGitHubComment , updateGitHubIssue } from '@/ai/mcp/tools/github/github' ;
5- import { HealthStepResult } from '@/health/health-check ' ;
5+ import { HealthStepResult } from '@/health/types ' ;
66import { getGithubConfig } from '@utils/github/configs' ;
7+ import { getGitHubPrivateKey , getGitHubAppId } from '@/utils/secrets' ;
8+ import { App } from 'octokit' ;
79
810export async function checkGitHubAPIHealth ( env : Env ) : Promise < HealthStepResult > {
911 const start = Date . now ( ) ;
@@ -66,6 +68,51 @@ export async function checkWebhooksHealth(env: Env): Promise<HealthStepResult> {
6668 }
6769}
6870
71+ export async function checkGitHubAppAuthHealth ( env : Env ) : Promise < HealthStepResult > {
72+ const start = Date . now ( ) ;
73+ const details : any = { auth : { status : 'pending' , test : 'octokit_app_init' } } ;
74+
75+ try {
76+ const appId = await getGitHubAppId ( env ) ;
77+ const privateKey = await getGitHubPrivateKey ( env ) ;
78+
79+ if ( ! appId || ! privateKey ) {
80+ throw new Error ( "Missing GitHub App ID or Private Key in bindings" ) ;
81+ }
82+
83+ // Initialize the Octokit App class.
84+ // If the private key is in PKCS#1 format (invalid), or malformed,
85+ // this instantiation or the subsequent JWT generation will throw.
86+ const app = new App ( {
87+ appId,
88+ privateKey,
89+ } ) ;
90+
91+ // Make an authenticated app-level request to force JWT generation
92+ // to strictly validate the key format internally
93+ const response = await app . octokit . request ( "GET /app" ) ;
94+
95+ details . auth . status = 'success' ;
96+ details . auth . appName = response . data ?. name || "Unknown" ;
97+
98+ return {
99+ name : 'GitHub App Authentication' ,
100+ status : 'success' ,
101+ message : 'App initialized and JWT generated successfully (PKCS#8 confirmed)' ,
102+ details : details ,
103+ durationMs : Date . now ( ) - start
104+ } ;
105+ } catch ( e : any ) {
106+ return {
107+ name : 'GitHub App Authentication' ,
108+ status : 'failure' ,
109+ message : e . message || 'Failed to initialize Octokit App or generate JWT' ,
110+ details : { ...details , stack : e . stack , name : e . name } ,
111+ durationMs : Date . now ( ) - start
112+ } ;
113+ }
114+ }
115+
69116async function checkWebhookGaps ( env : Env ) {
70117 const db = getWebhooksDb ( env . DB_WEBHOOKS ) ;
71118 const lastEvents = await db . select ( ) . from ( webhookDeliveries ) . orderBy ( desc ( webhookDeliveries . created_at ) ) . limit ( 1 ) ;
@@ -81,7 +128,7 @@ async function checkWebhookGaps(env: Env) {
81128async function runApiChecks ( env : Env ) {
82129 const owner = getGithubConfig ( env , 'owner' ) ;
83130 const repo = env . HEALTH_TEST_REPO_NAME ;
84- const steps = [ ] ;
131+ const steps : any [ ] = [ ] ;
85132 let issueNumber : number | null = null ;
86133
87134 try {
0 commit comments