From 4b3c4cfab48bd92148ba968b4683e5b3c63e9f53 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 14 Jul 2026 04:49:33 +0000 Subject: [PATCH 1/2] jsweep: add @ts-check and tests to harness_retry_config.cjs - Add // @ts-check to enable type checking - Export parseRetryConfigNumber for testability - Create harness_retry_config.test.cjs with 18 test cases covering: - parseRetryConfigNumber: empty/missing env vars, valid integers, floats, exponential/hex rejection, minimum enforcement, whitespace trimming, logger callback - resolveRetryConfig: defaults, env var overrides, maxRetries capping, maxDelayMs clamping, process.env fallback Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- actions/setup/js/harness_retry_config.cjs | 2 + .../setup/js/harness_retry_config.test.cjs | 115 ++++++++++++++++++ 2 files changed, 117 insertions(+) create mode 100644 actions/setup/js/harness_retry_config.test.cjs diff --git a/actions/setup/js/harness_retry_config.cjs b/actions/setup/js/harness_retry_config.cjs index 3d5f6c16281..756e22a1d6b 100644 --- a/actions/setup/js/harness_retry_config.cjs +++ b/actions/setup/js/harness_retry_config.cjs @@ -1,3 +1,4 @@ +// @ts-check "use strict"; // Maximum number of retry attempts after the initial run @@ -106,4 +107,5 @@ function resolveRetryConfig(env = process.env, logger = () => {}) { module.exports = { resolveRetryConfig, + parseRetryConfigNumber, }; diff --git a/actions/setup/js/harness_retry_config.test.cjs b/actions/setup/js/harness_retry_config.test.cjs new file mode 100644 index 00000000000..e91c503f5c9 --- /dev/null +++ b/actions/setup/js/harness_retry_config.test.cjs @@ -0,0 +1,115 @@ +// @ts-check + +import { describe, it, expect } from "vitest"; +import { resolveRetryConfig, parseRetryConfigNumber } from "./harness_retry_config.cjs"; + +describe("parseRetryConfigNumber", () => { + it("returns defaultValue when env var is not set", () => { + const result = parseRetryConfigNumber({}, { envVar: "MY_VAR", defaultValue: 42, minimum: 0 }); + expect(result).toBe(42); + }); + + it("returns defaultValue when env var is empty string", () => { + const result = parseRetryConfigNumber({ MY_VAR: "" }, { envVar: "MY_VAR", defaultValue: 42, minimum: 0 }); + expect(result).toBe(42); + }); + + it("parses a valid integer", () => { + const result = parseRetryConfigNumber({ MY_VAR: "10" }, { envVar: "MY_VAR", defaultValue: 5, minimum: 0 }); + expect(result).toBe(10); + }); + + it("rejects exponential notation integers", () => { + const result = parseRetryConfigNumber({ MY_VAR: "1e3" }, { envVar: "MY_VAR", defaultValue: 5, minimum: 0 }); + expect(result).toBe(5); + }); + + it("rejects hex notation", () => { + const result = parseRetryConfigNumber({ MY_VAR: "0x10" }, { envVar: "MY_VAR", defaultValue: 5, minimum: 0 }); + expect(result).toBe(5); + }); + + it("returns defaultValue when value is below minimum", () => { + const result = parseRetryConfigNumber({ MY_VAR: "0" }, { envVar: "MY_VAR", defaultValue: 5, minimum: 1 }); + expect(result).toBe(5); + }); + + it("accepts float when allowFloat is true", () => { + const result = parseRetryConfigNumber({ MY_VAR: "1.5" }, { envVar: "MY_VAR", defaultValue: 2, minimum: 1, allowFloat: true }); + expect(result).toBe(1.5); + }); + + it("rejects float when allowFloat is false (default)", () => { + const result = parseRetryConfigNumber({ MY_VAR: "1.5" }, { envVar: "MY_VAR", defaultValue: 2, minimum: 1 }); + expect(result).toBe(2); + }); + + it("calls logger on invalid value", () => { + /** @type {string[]} */ + const logs = []; + parseRetryConfigNumber({ MY_VAR: "bad" }, { envVar: "MY_VAR", defaultValue: 5, minimum: 0, logger: m => logs.push(m) }); + expect(logs.length).toBeGreaterThan(0); + expect(logs[0]).toContain("MY_VAR"); + }); + + it("trims whitespace from value", () => { + const result = parseRetryConfigNumber({ MY_VAR: " 7 " }, { envVar: "MY_VAR", defaultValue: 5, minimum: 0 }); + expect(result).toBe(7); + }); +}); + +describe("resolveRetryConfig", () => { + it("returns defaults when no env vars are set", () => { + const config = resolveRetryConfig({}); + expect(config).toEqual({ + maxRetries: 3, + initialDelayMs: 5000, + backoffMultiplier: 2, + maxDelayMs: 60000, + }); + }); + + it("reads maxRetries from env", () => { + const config = resolveRetryConfig({ GH_AW_HARNESS_MAX_RETRIES: "5" }); + expect(config.maxRetries).toBe(5); + }); + + it("clamps maxRetries to MAX_RETRIES_CAP (100)", () => { + /** @type {string[]} */ + const logs = []; + const config = resolveRetryConfig({ GH_AW_HARNESS_MAX_RETRIES: "200" }, m => logs.push(m)); + expect(config.maxRetries).toBe(100); + expect(logs.some(m => m.includes("clamping"))).toBe(true); + }); + + it("reads initialDelayMs from env", () => { + const config = resolveRetryConfig({ GH_AW_HARNESS_INITIAL_DELAY_MS: "1000" }); + expect(config.initialDelayMs).toBe(1000); + }); + + it("reads backoffMultiplier as float from env", () => { + const config = resolveRetryConfig({ GH_AW_HARNESS_BACKOFF_MULTIPLIER: "1.5" }); + expect(config.backoffMultiplier).toBe(1.5); + }); + + it("clamps maxDelayMs to initialDelayMs when lower", () => { + /** @type {string[]} */ + const logs = []; + const config = resolveRetryConfig({ GH_AW_HARNESS_INITIAL_DELAY_MS: "5000", GH_AW_HARNESS_MAX_DELAY_MS: "1000" }, m => logs.push(m)); + expect(config.maxDelayMs).toBe(5000); + expect(logs.some(m => m.includes("clamping max delay"))).toBe(true); + }); + + it("reads maxDelayMs from env", () => { + const config = resolveRetryConfig({ GH_AW_HARNESS_MAX_DELAY_MS: "30000" }); + expect(config.maxDelayMs).toBe(30000); + }); + + it("uses process.env when no env argument provided", () => { + const config = resolveRetryConfig(); + expect(config).toHaveProperty("maxRetries"); + expect(config).toHaveProperty("initialDelayMs"); + expect(config).toHaveProperty("backoffMultiplier"); + expect(config).toHaveProperty("maxDelayMs"); + }); +}); From ad1f38675c777c26bfea9aed9b0b200080047a76 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 14 Jul 2026 09:04:41 +0000 Subject: [PATCH 2/2] fix: use require() for CJS module import in harness_retry_config.test.cjs Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- actions/setup/js/harness_retry_config.test.cjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actions/setup/js/harness_retry_config.test.cjs b/actions/setup/js/harness_retry_config.test.cjs index e91c503f5c9..c69d4c381f7 100644 --- a/actions/setup/js/harness_retry_config.test.cjs +++ b/actions/setup/js/harness_retry_config.test.cjs @@ -1,7 +1,7 @@ // @ts-check import { describe, it, expect } from "vitest"; -import { resolveRetryConfig, parseRetryConfigNumber } from "./harness_retry_config.cjs"; +const { resolveRetryConfig, parseRetryConfigNumber } = require("./harness_retry_config.cjs"); describe("parseRetryConfigNumber", () => { it("returns defaultValue when env var is not set", () => {