Skip to content

Commit f02b361

Browse files
committed
Refine Health Check for GitHub Workflow Server #7480
1 parent 25ea946 commit f02b361

5 files changed

Lines changed: 101 additions & 13 deletions

File tree

.github/ISSUE/epic-architect-github-workflow-as-mcp.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ We will employ a rapid and agile development approach. The scope and API specifi
2424
- **Goal:** Establish the server's foundation and define the initial API for PR interactions.
2525
- **Sub-Tasks:**
2626
- `ticket-define-initial-openapi-spec.md`: Create and refine an `openapi.yaml` specification, focusing first on health checks and core PR operations (list, checkout, diff).
27+
- `ticket-scaffold-github-workflow-server.md`: Scaffold the server structure, including directories, core files, and middleware, mirroring the memory server.
28+
- `ticket-refine-healthcheck-for-github-workflow-server.md`: Implement a robust health check to verify `gh` installation, authentication, and version.
2729

2830
### Future Scope
2931
- Implementation of the API endpoints.
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
---
2+
title: Refine Health Check for GitHub Workflow Server
3+
labels: enhancement, AI
4+
---
5+
6+
GH ticket id: #7380
7+
8+
**Epic:** #7477
9+
**Phase:** 1
10+
**Assignee:** tobiu
11+
**Status:** Done
12+
13+
## Description
14+
15+
The initial health check for the GitHub Workflow MCP server was a simple placeholder. This ticket covers the work to make it more robust and meaningful by incorporating the more detailed verification logic from the existing `buildScripts/ai/verifyGhSetup.mjs` script.
16+
17+
The new health check now verifies three critical conditions:
18+
1. That the `gh` CLI is installed.
19+
2. That the CLI is authenticated.
20+
3. That the CLI version meets a minimum requirement.
21+
22+
This ensures that the server only reports as "healthy" if it is fully capable of performing its duties.
23+
24+
## Acceptance Criteria
25+
26+
1. The `ai/mcp/server/github-workflow/services/healthService.mjs` file is updated.
27+
2. The `buildHealthResponse` function now performs separate checks for `gh` installation, authentication, and version.
28+
3. The JSON response from the `/healthcheck` endpoint now includes a more detailed `githubCli` object with separate booleans for `installed`, `authenticated`, and `versionOk`.
29+
4. The overall health status is set to `unhealthy` if any of the checks fail, with a descriptive error message included in the response.

ai/mcp/server/github-workflow/app.mjs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import morgan from 'morgan';
44
import swaggerUi from 'swagger-ui-express';
55
import yaml from 'js-yaml';
66
import healthRouter from './routes/health.mjs';
7-
// import pullRequestsRouter from './routes/pullRequests.mjs'; // To be enabled later
7+
import pullRequestsRouter from './routes/pullRequests.mjs';
88
import errorHandler from './middleware/errorHandler.mjs';
99
import notFoundHandler from './middleware/notFoundHandler.mjs';
1010
import serverConfig from './config.mjs';
@@ -21,7 +21,7 @@ app.use('/docs', swaggerUi.serve, swaggerUi.setup(openApiDocument, {explorer: tr
2121

2222
// Routes
2323
app.use('/', healthRouter);
24-
// app.use('/', pullRequestsRouter); // To be enabled later
24+
app.use('/', pullRequestsRouter);
2525

2626
// 404 + Error handlers
2727
app.use(notFoundHandler);

ai/mcp/server/github-workflow/services/healthService.mjs

Lines changed: 67 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,43 @@ import {exec} from 'child_process';
22
import {promisify} from 'util';
33

44
const execAsync = promisify(exec);
5+
const MIN_GH_VERSION = '2.0.0';
6+
7+
async function checkGhInstalled() {
8+
try {
9+
await execAsync('gh --version');
10+
return {installed: true};
11+
} catch (e) {
12+
return {installed: false, error: 'GitHub CLI is not installed. Please install it.'};
13+
}
14+
}
15+
16+
async function checkGhAuth() {
17+
try {
18+
await execAsync('gh auth status');
19+
return {authenticated: true};
20+
} catch (e) {
21+
return {authenticated: false, error: 'GitHub CLI is not authenticated. Please run "gh auth login".'};
22+
}
23+
}
24+
25+
async function checkGhVersion() {
26+
try {
27+
const {stdout} = await execAsync('gh --version');
28+
const versionMatch = stdout.match(/gh version ([\d.]+)/);
29+
if (versionMatch) {
30+
const currentVersion = versionMatch[1];
31+
if (currentVersion >= MIN_GH_VERSION) {
32+
return {versionOk: true, version: currentVersion};
33+
} else {
34+
return {versionOk: false, version: currentVersion, error: `gh version (${currentVersion}) is outdated. Please upgrade to at least ${MIN_GH_VERSION}.`};
35+
}
36+
}
37+
return {versionOk: false, error: 'Could not parse gh version.'};
38+
} catch (e) {
39+
return {versionOk: false, error: 'Could not get gh version.'};
40+
}
41+
}
542

643
/**
744
* Checks the status of the GitHub CLI integration.
@@ -12,25 +49,44 @@ async function buildHealthResponse() {
1249
status : 'healthy',
1350
timestamp: new Date().toISOString(),
1451
githubCli: {
15-
installed : true,
16-
authenticated: true,
17-
details : ''
52+
installed : false,
53+
authenticated: false,
54+
versionOk : false,
55+
version : null,
56+
details : []
1857
}
1958
};
2059

21-
try {
22-
const {stdout} = await execAsync('gh auth status');
23-
payload.githubCli.details = stdout.trim();
24-
} catch (error).
60+
const installedCheck = await checkGhInstalled();
61+
payload.githubCli.installed = installedCheck.installed;
62+
if (!installedCheck.installed) {
63+
payload.status = 'unhealthy';
64+
payload.githubCli.details.push(installedCheck.error);
65+
return payload;
66+
}
67+
68+
const authCheck = await checkGhAuth();
69+
payload.githubCli.authenticated = authCheck.authenticated;
70+
if (!authCheck.authenticated) {
2571
payload.status = 'unhealthy';
26-
payload.githubCli.installed = !error.message.includes('command not found');
27-
payload.githubCli.authenticated = false;
28-
payload.githubCli.details = error.stderr.trim();
72+
payload.githubCli.details.push(authCheck.error);
73+
}
74+
75+
const versionCheck = await checkGhVersion();
76+
payload.githubCli.versionOk = versionCheck.versionOk;
77+
payload.githubCli.version = versionCheck.version;
78+
if (!versionCheck.versionOk) {
79+
payload.status = 'unhealthy';
80+
payload.githubCli.details.push(versionCheck.error);
81+
}
82+
83+
if (payload.status === 'healthy') {
84+
payload.githubCli.details.push('GitHub CLI is installed, authenticated, and up to date.');
2985
}
3086

3187
return payload;
3288
}
3389

3490
export {
3591
buildHealthResponse
36-
};
92+
};

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
"ai:query-memory" : "node buildScripts/ai/queryMemory.mjs",
2525
"ai:verify-gh-setup" : "node buildScripts/ai/verifyGhSetup.mjs",
2626
"ai:server" : "chroma run --path ./chroma",
27+
"ai:server-github-workflow-mcp": "node ai/mcp/server/github-workflow/index.mjs",
2728
"ai:server-memory" : "chroma run --path ./chroma-memory --port 8001",
2829
"ai:server-memory-mcp" : "node ai/mcp/server/memory/index.mjs",
2930
"ai:setup-memory-db" : "node buildScripts/ai/setupMemoryDB.mjs",

0 commit comments

Comments
 (0)