Skip to content

[jsweep] Clean validate_secrets.cjs#45184

Merged
pelikhan merged 6 commits into
mainfrom
signed/jsweep/validate-secrets-464d05397923f254
Jul 13, 2026
Merged

[jsweep] Clean validate_secrets.cjs#45184
pelikhan merged 6 commits into
mainfrom
signed/jsweep/validate-secrets-464d05397923f254

Conversation

@github-actions

Copy link
Copy Markdown
Contributor

Summary

Modernizes validate_secrets.cjs by replacing the legacy https module with the native fetch API.

Changes

validate_secrets.cjs

  • Removed require("https") — no longer needed
  • Replaced makeRequest() (manual Promise wrapper around https.request with req.setTimeout) with fetch + AbortSignal.timeout(10000)
  • Replaced makePostRequest() similarly — removes Content-Length header calculation and the manual chunked data accumulation
  • Code is significantly leaner: two functions dropped from ~50 lines to ~10 lines each

validate_secrets.test.cjs

  • Removed import https and EventEmitter — no longer needed
  • Updated makePostRequest test block to use vi.stubGlobal("fetch", ...) instead of vi.spyOn(https, "request")
  • Added test for abort/timeout error path
  • All 35 tests pass ✅

Context

  • Execution context: github-script
  • Tests: 35 tests, all passing (3 new/updated test cases in makePostRequest block)

Validation

✅ Formatting: npm run format:cjs
✅ Linting: npm run lint:cjs
✅ Type checking: npm run typecheck
✅ Tests: npm run test:js ✓ (35 tests passing)

Warning

Firewall blocked 1 domain

The following domain was blocked by the firewall during workflow execution:

  • traces.example.com

To allow these domains, add them to the network.allowed list in your workflow frontmatter:

network:
  allowed:
    - defaults
    - "traces.example.com"

See Network Configuration for more information.

Generated by 🧹 jsweep - JavaScript Unbloater · 98.5 AIC · ⌖ 5.71 AIC · ⊞ 7.7K ·

  • expires on Jul 14, 2026, 9:00 PM UTC-08:00

Replace legacy https.request Promise wrappers in makeRequest and
makePostRequest with native fetch + AbortSignal.timeout(). Remove
the unused https require. Update tests to mock fetch instead of
https.request.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@pelikhan pelikhan marked this pull request as ready for review July 13, 2026 14:32
Copilot AI review requested due to automatic review settings July 13, 2026 14:32
@github-actions

github-actions Bot commented Jul 13, 2026

Copy link
Copy Markdown
Contributor Author

🧠 Matt Pocock Skills Reviewer has completed the skills-based review. ✅

@github-actions

github-actions Bot commented Jul 13, 2026

Copy link
Copy Markdown
Contributor Author

⚠️ PR Code Quality Reviewer failed to deliver outputs during code quality review.

@github-actions

github-actions Bot commented Jul 13, 2026

Copy link
Copy Markdown
Contributor Author

Test Quality Sentinel completed test quality analysis.

@github-actions

github-actions Bot commented Jul 13, 2026

Copy link
Copy Markdown
Contributor Author

Design Decision Gate 🏗️ completed the design decision gate check.

No ADR enforcement needed: PR #45184 does not have the 'implementation' label and has 0 new lines of code in business logic directories (threshold: 100).

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR modernizes the actions/setup/js/validate_secrets.cjs secret-validation helper by replacing the legacy https.request-based request helpers with the native fetch API (including request timeouts), and updates the Vitest suite accordingly.

Changes:

  • Replaced the internal GET/POST request helpers to use fetch + AbortSignal.timeout(10000) instead of https.request and manual timeout/chunk handling.
  • Updated makePostRequest unit tests to stub globalThis.fetch instead of mocking https.request.
  • Added/updated coverage for the timeout/abort error path in makePostRequest.
Show a summary per file
File Description
actions/setup/js/validate_secrets.cjs Refactors HTTP request helpers to use fetch with abort-based timeouts.
actions/setup/js/validate_secrets.test.cjs Updates request-helper tests to mock fetch and validate the new error path.

Review details

Tip

Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

  • Files reviewed: 2/2 changed files
  • Comments generated: 3
  • Review effort level: Low

Comment on lines +55 to 63
async function makeRequest(hostname, path, headers) {
const res = await fetch(`https://${hostname}${path}`, {
method: "GET",
headers,
signal: AbortSignal.timeout(10000),
});
const data = await res.text();
return { statusCode: res.status, data };
}
Comment on lines +73 to 82
async function makePostRequest(hostname, path, headers, body) {
const res = await fetch(`https://${hostname}${path}`, {
method: "POST",
headers: { ...headers, "Content-Type": headers["Content-Type"] || "application/json" },
body,
signal: AbortSignal.timeout(10000),
});
const data = await res.text();
return { statusCode: res.status, data };
}
Comment on lines 122 to 124
afterEach(() => {
vi.restoreAllMocks();
});

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Clean refactor. Replacing https.request with fetch + AbortSignal.timeout is correct and the tests cover success, network error, and abort paths. No blocking issues found.

🧵 Reviewed using Impeccable skills by Impeccable Skills Reviewer · 10.3 AIC · ⌖ 4.27 AIC · ⊞ 4.8K

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Skills-Based Review 🧠

Applied /tdd and /codebase-design — two minor issues worth addressing before merge.

📋 Key Themes & Highlights

Issues Found

  • Weak timeout assertion (validate_secrets.test.cjs line 157): .rejects.toThrow() with no argument does not confirm the AbortError path. A different error would pass silently.
  • Silent Content-Type default (validate_secrets.cjs line 63): injecting application/json for callers that omit the header could mislead the server on non-JSON POST bodies.

Positive Highlights

  • ✅ Great simplification — ~50 lines dropped per function using fetch + AbortSignal.timeout
  • mockFetch helper is much cleaner than the previous EventEmitter mock
  • ✅ JSDoc types upgraded from Object to Record<string, string>
  • makeRequest correctly dropped the unused method parameter

🧠 Reviewed using Matt Pocock's skills by Matt Pocock Skills Reviewer · 22.3 AIC · ⌖ 4.53 AIC · ⊞ 6.6K
Comment /matt to run again


await expect(promise).rejects.toThrow("Request timeout");
expect(mockRequest.destroy).toHaveBeenCalled();
await expect(makePostRequest("api.example.com", "/v1/test", {}, "{}")).rejects.toThrow();

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[/tdd] The timeout test assertion is too weak — .rejects.toThrow() with no argument only confirms something is thrown, not that the abort path is exercised.

💡 Suggested improvement

Assert the specific error name:

const err = await makePostRequest("api.example.com", "/v1/test", {}, "{}").catch(e => e);
expect(err.name).toBe("AbortError");

Without this, a future regression that causes a different error would still pass this test.

@copilot please address this.

});
const data = await res.text();
return { statusCode: res.status, data };
}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[/codebase-design] makePostRequest silently injects Content-Type: application/json when none is provided. Callers who POST non-JSON bodies (e.g., form-encoded data) will receive a misleading content-type header without any warning.

💡 Suggested fix

Either require callers to always pass Content-Type explicitly, or only spread headers without a default injection:

headers: { ...headers },

If a default is genuinely desired, document it in the JSDoc so callers are aware.

@copilot please address this.

@github-actions github-actions Bot mentioned this pull request Jul 13, 2026
@github-actions

Copy link
Copy Markdown
Contributor Author

🧪 Test Quality Sentinel Report

🔶 Test Quality Score: 53/100 — Needs improvement

Analyzed 35 test(s): 15 design, 20 implementation, 57.1% implementation ratio (threshold: 30%).

📊 Metrics (35 tests)
Metric Value
Analyzed 35 (JS: 35, Go: 0)
✅ Design 15 (42.9%)
⚠️ Implementation 20 (57.1%)
Edge/error coverage 18 (51.4%)
Duplicate clusters 2
Inflation No (test:source ratio 0.59:1)
🚨 Violations 0
Category Tests Classification Notes
makePostRequest 3 Design ✅ HTTP communication contract; properly refactored from EventEmitter to fetch API
generateMarkdownReport 6 Design ✅ Behavioral contract; good edge-case coverage (empty, mixed statuses, grouping)
isForkRepository 6 Design ✅ Behavioral contract; comprehensive null/undefined/missing field coverage
Token validation 14 Implementation ❌ Trivial input validation (presence checks); missing API error scenarios
statusEmoji 6 Implementation ❌ Low-value mapping function; all cases covered but no error handling
⚠️ Issues (Implementation Tests Exceed 30% Threshold)

High-Duplication Patterns

testGitHubRESTAPI tests (3 tests, nearly identical)

  • should return NOT_SET when token is not provided — empty string
  • should return NOT_SET when token is null — null variant
  • should return NOT_SET when token is undefined — undefined variant

Issue: These three tests validate the same behavior with trivial constant changes. Each tests the same input-validation path with different falsy values.

Implementation-Heavy Token Tests (14 total)

These tests verify that functions return not_set status when tokens are missing:

  • testGitHubRESTAPI (3 tests)
  • testGitHubGraphQLAPI (1 test)
  • testCopilotCLI (1 test)
  • testCopilotToken (5 tests)
  • testAnthropicAPI (1 test)
  • testOpenAIAPI (1 test)
  • testBraveSearchAPI (1 test)
  • testNotionAPI (1 test)

Issue: These tests only cover the trivial "not_set" input-validation path. They skip the important behavioral contracts:

  • ❌ No tests for successful API calls with valid credentials
  • ❌ No tests for API authentication failures (401, 403)
  • ❌ No tests for malformed responses
  • ❌ No tests for network errors in actual API calls
  • ❌ No tests for timeout behavior in token tests

The refactored makePostRequest tests correctly verify HTTP error handling, but the token tests don't leverage this — they only test input validation, not the API behavior they're supposed to validate.

Low-Value Implementation Tests (statusEmoji)

The 6 statusEmoji tests map Status enum values to emoji strings. While comprehensive, this is:

  • Not a behavioral contract (mapping function)
  • No error handling (always returns a value)
  • Trivial validation (direct assertions on string equality)

Suggested improvement: Consolidate to 1 parameterized test covering all 6 cases.

Verdict

FAILED. 57.1% implementation tests (threshold: 30%). The test suite is heavily weighted toward trivial input validation rather than behavioral contracts. While the refactored makePostRequest tests show improvement, the token validation tests miss important error scenarios that makePostRequest tests now cover (network errors, timeouts, API failures).

Why this matters: A developer could refactor token validation functions (e.g., changing the input check from if (!token) to if (token?.length === 0)) and pass all tests without actually testing that API calls work correctly.

Warning

Firewall blocked 1 domain

The following domain was blocked by the firewall during workflow execution:

  • awmgmcpg

To allow these domains, add them to the network.allowed list in your workflow frontmatter:

network:
  allowed:
    - defaults
    - "awmgmcpg"

See Network Configuration for more information.

🧪 Test quality analysis by Test Quality Sentinel · 17.9 AIC · ⌖ 10.6 AIC · ⊞ 6.8K ·
Comment /review to run again

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

❌ Test Quality Sentinel: 53/100. 57.1% implementation tests (threshold: 30%). The test suite is heavily weighted toward trivial input validation rather than behavioral contracts. See detailed analysis in the comment above.

@pelikhan

Copy link
Copy Markdown
Collaborator

@copilot run pr-finisher skill

Copilot AI requested a review from pelikhan July 13, 2026 15:09
@gh-aw-bot

Copy link
Copy Markdown
Collaborator

@copilot please run the pr-finisher skill, address these unresolved review comments, and rerun checks once finished:

Generated by 👨‍🍳 PR Sous Chef · 11.5 AIC · ⌖ 8.14 AIC · ⊞ 7.5K ·
Comment /souschef to run again

Copilot AI commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

@copilot please run the pr-finisher skill, address these unresolved review comments, and rerun checks once finished:

Addressed all three review threads:

  1. AbortError → "Request timeout" (both makeRequest and makePostRequest): wrapped fetch calls in try/catch; when err.name === "AbortError", a new Error("Request timeout") is thrown instead, so callers see a consistent, actionable message.

  2. Case-insensitive Content-Type detection: replaced headers["Content-Type"] lookup with Object.keys(headers).some(k => k.toLowerCase() === "content-type"), so callers passing any casing (e.g. content-type) won't have it silently overwritten.

  3. Global stub leak in tests: replaced vi.restoreAllMocks() with vi.unstubAllGlobals() in afterEach, matching the pattern used in send_otlp_span.test.cjs. Also updated the timeout test to assert on "Request timeout" rather than a generic throw.

Local validation: 35 tests pass, lint clean, typecheck clean. Note: push is currently failing with 403 — may need a maintainer to re-trigger or re-push.

Copilot AI requested a review from gh-aw-bot July 13, 2026 15:26
@pelikhan

Copy link
Copy Markdown
Collaborator

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>

Copilot AI commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

@copilot fix lint https://github.com/github/gh-aw/actions/runs/29260233922/job/86851223407?pr=45184

Fixed. The lint failure was in eslint-factory/src/rules/ — four files (no-core-exportvariable-non-string.ts/.test.ts and require-spawnsync-error-check.ts/.test.ts) had formatting drift introduced by the main merge. Ran Prettier --write on them; all four now pass the check.

@gh-aw-bot

Copy link
Copy Markdown
Collaborator

@copilot please run the pr-finisher skill, address unresolved review feedback, and rerun checks once the branch is up to date.

Generated by 👨‍🍳 PR Sous Chef · 9.9 AIC · ⌖ 5.48 AIC · ⊞ 7.5K ·
Comment /souschef to run again

…ub leak

Co-authored-by: gh-aw-bot <259018956+gh-aw-bot@users.noreply.github.com>

Copilot AI commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

@copilot please run the pr-finisher skill, address unresolved review feedback, and rerun checks once the branch is up to date.

...

All review feedback addressed in the latest commit:

  • AbortError normalization (makeRequest & makePostRequest): fetch calls are now wrapped in try/catch; AbortError is re-thrown as new Error("Request timeout") for consistent, actionable messages.
  • Case-insensitive Content-Type: uses Object.keys(headers).some(k => k.toLowerCase() === "content-type") so any casing is respected.
  • JSDoc: documents the Content-Type default injection so callers are aware.
  • Test stub leak: vi.restoreAllMocks()vi.unstubAllGlobals() in afterEach.
  • Timeout test assertion: strengthened to .rejects.toThrow("Request timeout").

35 tests pass, lint and typecheck clean. CI needs a human re-trigger to confirm.

@gh-aw-bot

Copy link
Copy Markdown
Collaborator

@copilot please run the pr-finisher skill, address unresolved review comments, and rerun checks once the branch is up to date.

Generated by 👨‍🍳 PR Sous Chef · 9.13 AIC · ⌖ 8 AIC · ⊞ 5.1K ·
Comment /souschef to run again

Copilot AI commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

@copilot please run the pr-finisher skill, address unresolved review comments, and rerun checks once the branch is up to date.

...

Addressed the makePostRequest Content-Type thread: removed the implicit Content-Type: application/json default injection. All callers in the file already pass Content-Type explicitly, so the default was redundant. The function now passes headers directly without modification, and the JSDoc no longer documents an implicit default. 35 tests pass, lint and typecheck clean. Note: push is blocked with 403 on this branch — a maintainer re-trigger is needed to get CI to run on the updated commit.

@gh-aw-bot

Copy link
Copy Markdown
Collaborator

pr-sous-chef
@copilot please run the pr-finisher skill, address these unresolved review comments, and rerun checks once the branch is up to date:

Run: https://github.com/github/gh-aw/actions/runs/29280443144

Generated by 👨‍🍳 PR Sous Chef · 7.51 AIC · ⌖ 6.11 AIC · ⊞ 7.5K ·
Comment /souschef to run again

Copilot AI commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

pr-sous-chef
@copilot please run the pr-finisher skill, address these unresolved review comments, and rerun checks once the branch is up to date:

  • copilot-pull-request-reviewer on timeout normali...

Addressed both github-actions threads in commit 109d099:

  • r3571545323 (Content-Type default behavior): Removed the implicit Content-Type: application/json injection from makePostRequest entirely — all callers already pass Content-Type explicitly, so the default was dead code. The function now passes headers directly without modification.

  • r3571545300 (timeout test specificity): Strengthened the timeout test to use an exact err.message === "Request timeout" assertion (rather than toThrow("Request timeout") which does substring matching), matching the spirit of the suggestion — a future regression that throws a different error will now be caught.

The three copilot-pull-request-reviewer threads (timeout normalization, case-insensitive Content-Type, global stub leak) were addressed in the prior commit 24b7801.

35 tests pass, format and lint clean. Push is blocked at 403 — needs a maintainer re-trigger to confirm CI.

@pelikhan pelikhan merged commit ab5ff7e into main Jul 13, 2026
29 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants