Skip to content

Commit e685a0e

Browse files
Copilotpelikhan
andauthored
Remove duplicate Token Usage rendering from MCP Gateway step summary (#27406)
* Initial plan * fix: avoid duplicate token usage section in MCP gateway summary Agent-Logs-Url: https://github.com/github/gh-aw/sessions/33877792-b58e-434e-b075-1cdc46ba043c Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> * test: fix fs mock re-entrancy and cleanup leakage in gateway parser test Agent-Logs-Url: https://github.com/github/gh-aw/sessions/957ae36f-3fbf-4138-ba0f-60599a8dff97 Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> Co-authored-by: Peli de Halleux <pelikhan@users.noreply.github.com>
1 parent 1f26fd9 commit e685a0e

File tree

2 files changed

+74
-7
lines changed

2 files changed

+74
-7
lines changed

actions/setup/js/parse_mcp_gateway_log.cjs

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -167,9 +167,8 @@ function generateTokenUsageSummary(summary) {
167167
}
168168

169169
/**
170-
* Appends the token usage section to the step summary if data is present, then writes it.
171-
* Also exports GH_AW_EFFECTIVE_TOKENS as a GitHub Actions environment variable so
172-
* subsequent steps can display the ET value in generated footers.
170+
* Writes the step summary and exports GH_AW_EFFECTIVE_TOKENS when token usage data exists.
171+
* Token Usage rendering is handled by parse_token_usage.cjs to avoid duplicate sections.
173172
* This is the final call in each main() exit path — it consolidates the summary write
174173
* so callers don't need to chain addRaw() + write() themselves.
175174
* @param {typeof import('@actions/core')} coreObj - The GitHub Actions core object
@@ -182,10 +181,6 @@ function writeStepSummaryWithTokenUsage(coreObj) {
182181
if (content?.trim()) {
183182
coreObj.info(`Found token-usage.jsonl (${content.length} bytes)`);
184183
const parsedSummary = parseTokenUsageJsonl(content);
185-
const markdown = generateTokenUsageSummary(parsedSummary);
186-
if (markdown.length > 0) {
187-
coreObj.summary.addDetails("Token Usage", "\n\n" + markdown);
188-
}
189184
// Export total effective tokens as a GitHub Actions env var for use in
190185
// generated footers (GH_AW_EFFECTIVE_TOKENS is read by messages_footer.cjs)
191186
if (parsedSummary && parsedSummary.totalEffectiveTokens > 0) {

actions/setup/js/parse_mcp_gateway_log.test.cjs

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -335,6 +335,78 @@ Some content here.`;
335335
fs.rmSync(tmpDir, { recursive: true, force: true });
336336
}
337337
});
338+
339+
test("does not append token usage details when token usage file exists", async () => {
340+
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "mcp-test-"));
341+
const gatewayMdPath = path.join(tmpDir, "gateway.md");
342+
const tokenUsagePath = path.join(tmpDir, "token-usage.jsonl");
343+
const originalExistsSync = fs.existsSync;
344+
const originalReadFileSync = fs.readFileSync;
345+
346+
try {
347+
fs.writeFileSync(gatewayMdPath, "# Gateway Summary\n\nSome markdown content");
348+
fs.writeFileSync(
349+
tokenUsagePath,
350+
JSON.stringify({
351+
model: "claude-haiku-4-5-20251001",
352+
input_tokens: 42,
353+
output_tokens: 2765,
354+
cache_read_tokens: 141738,
355+
cache_write_tokens: 38170,
356+
duration_ms: 26500,
357+
})
358+
);
359+
360+
const mockCore = {
361+
info: vi.fn(),
362+
debug: vi.fn(),
363+
startGroup: vi.fn(),
364+
endGroup: vi.fn(),
365+
notice: vi.fn(),
366+
warning: vi.fn(),
367+
error: vi.fn(),
368+
setFailed: vi.fn(),
369+
exportVariable: vi.fn(),
370+
setOutput: vi.fn(),
371+
summary: {
372+
addRaw: vi.fn().mockReturnThis(),
373+
addDetails: vi.fn().mockReturnThis(),
374+
write: vi.fn(),
375+
},
376+
};
377+
378+
fs.existsSync = vi.fn(filepath => {
379+
if (filepath === "/tmp/gh-aw/mcp-logs/gateway.md") return true;
380+
if (filepath === "/tmp/gh-aw/sandbox/firewall/logs/api-proxy-logs/token-usage.jsonl") return true;
381+
return originalExistsSync(filepath);
382+
});
383+
384+
fs.readFileSync = vi.fn((filepath, encoding) => {
385+
if (filepath === "/tmp/gh-aw/mcp-logs/gateway.md") {
386+
return originalReadFileSync(gatewayMdPath, encoding);
387+
}
388+
if (filepath === "/tmp/gh-aw/sandbox/firewall/logs/api-proxy-logs/token-usage.jsonl") {
389+
return originalReadFileSync(tokenUsagePath, encoding);
390+
}
391+
return originalReadFileSync(filepath, encoding);
392+
});
393+
394+
global.core = mockCore;
395+
396+
const { main } = require("./parse_mcp_gateway_log.cjs");
397+
await main();
398+
399+
expect(mockCore.summary.addRaw).toHaveBeenCalledWith(expect.stringContaining("Gateway Summary"));
400+
expect(mockCore.summary.addDetails).not.toHaveBeenCalledWith("Token Usage", expect.any(String));
401+
expect(mockCore.exportVariable).toHaveBeenCalledWith("GH_AW_EFFECTIVE_TOKENS", expect.any(String));
402+
expect(mockCore.summary.write).toHaveBeenCalled();
403+
} finally {
404+
fs.existsSync = originalExistsSync;
405+
fs.readFileSync = originalReadFileSync;
406+
delete global.core;
407+
fs.rmSync(tmpDir, { recursive: true, force: true });
408+
}
409+
});
338410
});
339411

340412
describe("printAllGatewayFiles", () => {

0 commit comments

Comments
 (0)