Skip to content

Commit db4ac88

Browse files
feat: add pre/post test command hooks for dynamic configuration
Adds three new optional fields to TestConfiguration for lifecycle hooks: - pre_test_command: runs before starting the MCP server - pre_test_wait_ms: wait time after pre_test_command before probing - post_test_command: cleanup command after stopping the server This enables testing servers with dynamic dependencies like mock services. Also removes hardcoded version string from startup output. Closes #11
1 parent 8029fdd commit db4ac88

6 files changed

Lines changed: 135 additions & 21 deletions

File tree

dist/index.js

Lines changed: 55 additions & 5 deletions
Large diffs are not rendered by default.

dist/index.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/types.d.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,12 @@ export interface TestConfiguration {
1010
headers?: Record<string, string>;
1111
env_vars?: string;
1212
custom_messages?: CustomMessage[];
13+
/** Command to run before starting the MCP server for this config */
14+
pre_test_command?: string;
15+
/** Milliseconds to wait after pre_test_command before starting the server */
16+
pre_test_wait_ms?: number;
17+
/** Command to run after stopping the MCP server for this config (cleanup) */
18+
post_test_command?: string;
1319
}
1420
export interface CustomMessage {
1521
id: number;

src/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,7 @@ async function runInitialBuild(inputs: ActionInputs): Promise<void> {
198198
*/
199199
async function run(): Promise<void> {
200200
try {
201-
core.info("🚀 MCP Conformance Action v2.0.0");
201+
core.info("🚀 MCP Conformance Action");
202202
core.info("");
203203

204204
// Get inputs

src/runner.ts

Lines changed: 66 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,43 @@ async function runBuild(dir: string, inputs: ActionInputs): Promise<void> {
171171
}
172172
}
173173

174+
/**
175+
* Sleep for a specified number of milliseconds
176+
*/
177+
function sleep(ms: number): Promise<void> {
178+
return new Promise((resolve) => setTimeout(resolve, ms));
179+
}
180+
181+
/**
182+
* Run pre-test command if specified
183+
*/
184+
async function runPreTestCommand(config: TestConfiguration, workDir: string): Promise<void> {
185+
if (config.pre_test_command) {
186+
core.info(` Running pre-test command: ${config.pre_test_command}`);
187+
await exec.exec("sh", ["-c", config.pre_test_command], { cwd: workDir });
188+
189+
if (config.pre_test_wait_ms && config.pre_test_wait_ms > 0) {
190+
core.info(` Waiting ${config.pre_test_wait_ms}ms for service to be ready...`);
191+
await sleep(config.pre_test_wait_ms);
192+
}
193+
}
194+
}
195+
196+
/**
197+
* Run post-test command if specified (cleanup)
198+
*/
199+
async function runPostTestCommand(config: TestConfiguration, workDir: string): Promise<void> {
200+
if (config.post_test_command) {
201+
core.info(` Running post-test command: ${config.post_test_command}`);
202+
try {
203+
await exec.exec("sh", ["-c", config.post_test_command], { cwd: workDir });
204+
} catch (error) {
205+
// Log but don't fail - cleanup errors shouldn't break the test
206+
core.warning(` Post-test command failed: ${error}`);
207+
}
208+
}
209+
}
210+
174211
/**
175212
* Probe a server with a specific configuration
176213
*/
@@ -186,6 +223,9 @@ async function probeWithConfig(
186223
const headers = { ...globalHeaders, ...config.headers };
187224
const customMessages = config.custom_messages || globalCustomMessages;
188225

226+
// Run pre-test command before probing
227+
await runPreTestCommand(config, workDir);
228+
189229
if (config.transport === "stdio") {
190230
const command = config.start_command || "";
191231
const parts = command.split(/\s+/);
@@ -304,13 +344,19 @@ export async function runSingleConfigTest(
304344
// Test current branch
305345
core.info("🔄 Testing current branch...");
306346
const branchStart = Date.now();
307-
const branchResult = await probeWithConfig(
308-
config,
309-
ctx.workDir,
310-
globalEnvVars,
311-
globalHeaders,
312-
globalCustomMessages
313-
);
347+
let branchResult: ProbeResult;
348+
try {
349+
branchResult = await probeWithConfig(
350+
config,
351+
ctx.workDir,
352+
globalEnvVars,
353+
globalHeaders,
354+
globalCustomMessages
355+
);
356+
} finally {
357+
// Always run post-test cleanup
358+
await runPostTestCommand(config, ctx.workDir);
359+
}
314360
result.branchTime = Date.now() - branchStart;
315361

316362
if (branchResult.error) {
@@ -346,13 +392,19 @@ export async function runSingleConfigTest(
346392
// Probe on base
347393
core.info("🔄 Testing comparison ref...");
348394
const baseStart = Date.now();
349-
const baseResult = await probeWithConfig(
350-
config,
351-
baseWorkDir,
352-
globalEnvVars,
353-
globalHeaders,
354-
globalCustomMessages
355-
);
395+
let baseResult: ProbeResult;
396+
try {
397+
baseResult = await probeWithConfig(
398+
config,
399+
baseWorkDir,
400+
globalEnvVars,
401+
globalHeaders,
402+
globalCustomMessages
403+
);
404+
} finally {
405+
// Always run post-test cleanup
406+
await runPostTestCommand(config, baseWorkDir);
407+
}
356408
result.baseTime = Date.now() - baseStart;
357409

358410
if (baseResult.error) {

src/types.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,12 @@ export interface TestConfiguration {
1111
headers?: Record<string, string>;
1212
env_vars?: string;
1313
custom_messages?: CustomMessage[];
14+
/** Command to run before starting the MCP server for this config */
15+
pre_test_command?: string;
16+
/** Milliseconds to wait after pre_test_command before starting the server */
17+
pre_test_wait_ms?: number;
18+
/** Command to run after stopping the MCP server for this config (cleanup) */
19+
post_test_command?: string;
1420
}
1521

1622
export interface CustomMessage {

0 commit comments

Comments
 (0)