diff --git a/actions/setup/js/awf_reflect_summary.cjs b/actions/setup/js/awf_reflect_summary.cjs index 37af29e18a9..8277dfbd6d1 100644 --- a/actions/setup/js/awf_reflect_summary.cjs +++ b/actions/setup/js/awf_reflect_summary.cjs @@ -1,6 +1,8 @@ // @ts-check /// +require("./shim.cjs"); + const fs = require("fs"); const AWF_CONFIG_PATH = "/tmp/gh-aw/awf-config.json"; @@ -260,6 +262,8 @@ async function main() { } const markdown = buildReflectSummary(reflectData, { awfConfigData, runtimeModelsData }); + // shim.cjs ensures core.summary.addRaw()/write() are available in environments + // without native GitHub Actions step-summary support. await core.summary.addRaw(markdown).write(); core.info("AWF reflect summary written to step summary"); } diff --git a/actions/setup/js/awf_reflect_summary.test.cjs b/actions/setup/js/awf_reflect_summary.test.cjs index 4eaf9ce4e8a..6437ac675bd 100644 --- a/actions/setup/js/awf_reflect_summary.test.cjs +++ b/actions/setup/js/awf_reflect_summary.test.cjs @@ -1,5 +1,8 @@ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; import fs from "fs"; +import { createRequire } from "module"; + +const require = createRequire(import.meta.url); const mockCore = { info: vi.fn(), @@ -380,5 +383,32 @@ describe("awf_reflect_summary.cjs", () => { expect(mockCore.summary.write).toHaveBeenCalledTimes(1); expect(mockCore.info).toHaveBeenCalledWith(expect.stringContaining("AWF reflect summary written")); }); + + it("uses shimmed summary methods when step summary API is missing", async () => { + const originalSummary = global.core.summary; + try { + global.core.summary = undefined; + const shimPath = require.resolve("./shim.cjs"); + delete require.cache[shimPath]; + require("./shim.cjs"); + const addRawSpy = vi.spyOn(global.core.summary, "addRaw"); + const writeSpy = vi.spyOn(global.core.summary, "write"); + fs.writeFileSync(REFLECT_PATH, JSON.stringify(SAMPLE_REFLECT), "utf8"); + + await module.main(); + + expect(addRawSpy).toHaveBeenCalledTimes(1); + expect(writeSpy).toHaveBeenCalledTimes(1); + const summary = addRawSpy.mock.calls[0][0]; + expect(summary).toContain("AWF API proxy"); + expect(summary).toContain("openai"); + expect(mockCore.info).toHaveBeenCalledWith(expect.stringContaining("AWF reflect summary written")); + } finally { + global.core.summary = originalSummary; + const shimPath = require.resolve("./shim.cjs"); + delete require.cache[shimPath]; + require("./shim.cjs"); + } + }); }); }); diff --git a/actions/setup/js/pick_experiment.cjs b/actions/setup/js/pick_experiment.cjs index 7fd9c61fe46..858c70f661b 100644 --- a/actions/setup/js/pick_experiment.cjs +++ b/actions/setup/js/pick_experiment.cjs @@ -234,7 +234,7 @@ async function writeSummary(assignments, configs, state, core) { lines.push(`| \`${name}\` | **${selected}** | ${thisCount} / ${totalCount} |`); const cfg = configs[name] || {}; - const minSamples = Number.isInteger(cfg.min_samples) && cfg.min_samples > 0 ? cfg.min_samples : null; + const minSamples = typeof cfg.min_samples === "number" && Number.isInteger(cfg.min_samples) && cfg.min_samples > 0 ? cfg.min_samples : null; const analysisType = cfg.analysis_type || "n/a"; const tags = Array.isArray(cfg.tags) ? cfg.tags.filter(t => typeof t === "string" && t.length > 0) : []; const notifyTargets = []; diff --git a/actions/setup/js/shim.cjs b/actions/setup/js/shim.cjs index c3f628f0013..f051446bed6 100644 --- a/actions/setup/js/shim.cjs +++ b/actions/setup/js/shim.cjs @@ -33,6 +33,16 @@ if (!global.core) { }; } +const coreSummary = global.core.summary && typeof global.core.summary === "object" ? global.core.summary : (global.core.summary = {}); + +if (typeof coreSummary.addRaw !== "function") { + coreSummary.addRaw = () => coreSummary; +} + +if (typeof coreSummary.write !== "function") { + coreSummary.write = async () => {}; +} + if (!global.context) { // Build a context object from GitHub Actions environment variables, // mirroring the shape of @actions/github's Context class.