Skip to content

fix(eslint): resolve route/URL/control-flow lint violations in actions/setup/js#46100

Open
pelikhan with Copilot wants to merge 10 commits into
mainfrom
copilot/fix-route-url-core-failure-control-lint
Open

fix(eslint): resolve route/URL/control-flow lint violations in actions/setup/js#46100
pelikhan with Copilot wants to merge 10 commits into
mainfrom
copilot/fix-route-url-core-failure-control-lint

Conversation

Copilot AI commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

Three categories of custom ESLint rule violations across 10 files in actions/setup/js: interpolated github.request() routes, unguarded new URL() calls, and core.setFailed() without immediate control transfer.

Typed github.request() routes (no-github-request-interpolated-route)

Replaced whole-route interpolations and template-literal routes with typed placeholder form. This required refactoring resolveRestEndpoint / addReaction to return { route, params } objects instead of path strings, cascading through add_reaction_and_edit_comment.cjs and add_workflow_run_comment.cjs.

// Before
github.request(`POST ${endpoint}`, { content: reaction, ...context })
github.request(`POST /repos/${owner}/${repo}/issues/${issue_number}/reactions`, ...)

// After
github.request("POST /repos/{owner}/{repo}/issues/{issue_number}/reactions", {
  owner, repo, issue_number, content: reaction
})

Files: add_reaction.cjs, add_reaction_and_edit_comment.cjs, add_workflow_run_comment.cjs, route_slash_command.cjs

Guarded new URL() (require-new-url-try-catch)

Wrapped new URL(...) in try/catch in all flagged call sites.

Files: artifact_client.cjs (4 sites), generate_history_link.cjs, mcp_cli_bridge.cjs, mount_mcp_as_cli.cjs

Control transfer after core.setFailed() (require-return-after-core-setfailed)

  • check_team_member.cjs: moved setOutput before setFailed, added return
  • safe_output_handler_manager.cjs: captured failure message in a variable, deferred setFailed + return to after all output exports complete

Test updates

All affected test files updated to match the new { route, params } call signatures. 315 tests pass across 8 test files.

Copilot AI and others added 2 commits July 17, 2026 00:14
…up/js

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

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix route and URL core failure control lint findings fix(eslint): resolve route/URL/control-flow lint violations in actions/setup/js Jul 17, 2026
Copilot AI requested a review from pelikhan July 17, 2026 00:48
@github-actions

Copy link
Copy Markdown
Contributor

🤖 PR Triage

Field Value
Category chore (ESLint batch 3/3)
Risk 🟡 Medium
Score 30/100
Action defer
Batch pr-batch:eslint-setup-js

Score breakdown: Impact 10 + Urgency 7 + Quality 13

Rationale: Resolves route/URL/control-flow ESLint violations in 10 files in actions/setup/js/. DRAFT. Part of 3-PR ESLint batch with #46102 and #46101.

Run §29545908133

Generated by 🔧 PR Triage Agent · 181.7 AIC · ⌖ 5.04 AIC · ⊞ 5.6K ·

@pelikhan
pelikhan marked this pull request as ready for review July 17, 2026 02:41
Copilot AI review requested due to automatic review settings July 17, 2026 02:41
@github-actions

github-actions Bot commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

Test Quality Sentinel completed test quality analysis.

@github-actions

github-actions Bot commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

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

@github-actions

github-actions Bot commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

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

@github-actions

github-actions Bot commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

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

No ADR enforcement needed: PR #46100 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

Updates JavaScript action helpers to satisfy custom ESLint rules while preserving GitHub API behavior.

Changes:

  • Replaces interpolated REST endpoints with typed routes and parameters.
  • Guards URL construction and adds explicit errors.
  • Adds control flow after core.setFailed() and updates tests.
Show a summary per file
File Description
.github/workflows/release.lock.yml Refreshes generated action metadata.
actions/setup/js/add_reaction.cjs Uses typed reaction routes.
actions/setup/js/add_reaction.test.cjs Updates reaction route tests.
actions/setup/js/add_reaction_and_edit_comment.cjs Uses typed reaction/comment routes.
actions/setup/js/add_reaction_and_edit_comment.test.cjs Updates combined-action tests.
actions/setup/js/add_workflow_run_comment.cjs Uses typed comment routes.
actions/setup/js/add_workflow_run_comment.test.cjs Updates comment route tests.
actions/setup/js/artifact_client.cjs Guards artifact URL construction.
actions/setup/js/check_team_member.cjs Returns after failure handling.
actions/setup/js/generate_history_link.cjs Guards history URL construction.
actions/setup/js/mcp_cli_bridge.cjs Rejects malformed bridge URLs.
actions/setup/js/mount_mcp_as_cli.cjs Rejects malformed mounted-server URLs.
actions/setup/js/route_slash_command.cjs Uses typed immediate-reaction routes.
actions/setup/js/route_slash_command.test.cjs Updates slash-command route tests.
actions/setup/js/safe_output_handler_manager.cjs Defers failure until outputs are exported.

Review details

Tip

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

  • Files reviewed: 15/15 changed files
  • Comments generated: 2
  • Review effort level: Medium

Comment thread actions/setup/js/artifact_client.cjs Outdated
Comment on lines +85 to +91
const url = (() => {
try {
return new URL(`/twirp/${TWIRP_ARTIFACT_SERVICE}/${method}`, getResultsServiceOrigin()).toString();
} catch {
throw new Error(`Failed to construct twirp URL for method: ${method}`);
}
})();

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.

Fixed in 3bba3d7 and refined in 90c2fe7. twirpRequest now resolves getResultsServiceOrigin() before constructing the Twirp URL, so ACTIONS_RESULTS_URL validation errors remain visible instead of being masked by the construction guard.

Comment on lines +1640 to +1645
let failedOutputsMessage = null;
if (failureCount > 0) {
core.warning(`${failureCount} message(s) failed to process`);
const failedItemLines = fatalFailures.map(r => ` - ${r.type}: ${r.error || "Unknown error"}`);
const failedItems = failedItemLines.join("\n");
core.setFailed(`${failureCount} safe output(s) failed:\n${failedItems}`);
failedOutputsMessage = `${failureCount} safe output(s) failed:\n${failedItems}`;

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.

Addressed in 3bba3d7. I moved failedOutputsMessage to outer scope and updated the catch path to include it when later export logic throws, so primary safe-output failures are preserved alongside handler errors.

@github-actions github-actions Bot 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.

Review: ESLint lint-violation fixes

The changes correctly address all three lint violation categories:

Typed github.request() routesresolveRestEndpoint / resolveEventEndpoints now return { route, params } objects. The typed route strings use {placeholder} syntax and params are spread at the call site. Cascade updates to callers and tests are consistent.

Guarded new URL() — All 8 call sites in artifact_client.cjs, generate_history_link.cjs, mcp_cli_bridge.cjs, and mount_mcp_as_cli.cjs are wrapped in try/catch.

Control transfer after core.setFailed()check_team_member.cjs adds return after setFailed. safe_output_handler_manager.cjs correctly defers setFailed until after all outputs are exported, then returns — preventing any subsequent output after failure.

No correctness, security, or logic issues found. 315 tests pass.

🧵 Reviewed using Impeccable skills by Impeccable Skills Reviewer · 26.7 AIC · ⌖ 5.21 AIC · ⊞ 5K

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

Copy link
Copy Markdown
Contributor

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 · 47.1 AIC · ⌖ 8.41 AIC · ⊞ 6.8K ·
Comment /review to run again

@github-actions github-actions Bot 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.

Test Quality Sentinel: 73/100. 20% implementation tests (threshold: 30%). No guideline violations.

@github-actions github-actions Bot 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.

Skills-Based Review 🧠

Applied /codebase-design, /tdd, and /diagnosing-bugs — no blocking issues, three moderate suggestions.

📋 Key Themes & Highlights

Key Themes

  • Repeated IIFE try-catch pattern in artifact_client.cjs: four identical wrappers that beg for a shared parseURL helper.
  • Loose union type for endpoints: the { route, params } | string union requires typeof guards at every call site; a tagged union (kind: 'rest' | 'discussion') would be cleaner.
  • Log ordering quirk in safe_output_handler_manager.cjs: the 'completed' info log fires unconditionally even when the deferred setFailed is about to run.

Positive Highlights

  • ✅ Clean, consistent refactor of all route interpolations to the typed placeholder form.
  • ✅ Test suite updated in lock-step (315 passing) — the test assertions were also migrated to match exact typed routes, not loose string matchers.
  • check_team_member.cjs fix correctly moves setOutput before setFailed and adds return, fully satisfying the lint rule intent.

🧠 Reviewed using Matt Pocock's skills by Matt Pocock Skills Reviewer · 51.3 AIC · ⌖ 4.75 AIC · ⊞ 6.7K
Comment /matt to run again

Comment thread actions/setup/js/artifact_client.cjs Outdated
throw new Error("ACTIONS_RUNTIME_TOKEN is required for artifact upload");
}
const url = new URL(`/twirp/${TWIRP_ARTIFACT_SERVICE}/${method}`, getResultsServiceOrigin()).toString();
const url = (() => {

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.

[/codebase-design] Four identical IIFE try-catch wrappers around new URL() are spread across this file — a shared parseURL(url, base?) helper would eliminate the repetition and give one place to improve error messages later.

💡 Suggested helper
function parseURL(url, base) {
  try {
    return base ? new URL(url, base) : new URL(url);
  } catch {
    throw new Error(`Invalid URL: ${url}${base ? ` (base: ${base})` : ""}`);
  }
}

Each call site then becomes a readable one-liner.

@copilot please address this.

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.

Addressed in 3bba3d7. I added a shared parseURL(url, base, errorMessage) helper and replaced the repeated URL try/catch wrappers in this file with helper calls at each call site.

* @param {string} repo - Repository name
* @param {Record<string, any>} payload - The event payload
* @returns {Promise<{reactionEndpoint: string, commentUpdateEndpoint: string} | null>}
* @returns {Promise<{reactionEndpoint: { route: string, params: Record<string, unknown> } | string, commentUpdateEndpoint: { route: string, params: Record<string, unknown> } | string} | null>}

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.

[/codebase-design] The union return type { route: string, params: ... } | string leaks the discussion-special-case format into the type signature, causing defensive typeof endpoint === 'object' checks at every call site. Consider a tagged union to make the branching explicit and self-documenting.

💡 Suggested typed shape
// `@typedef` {{ kind: 'rest', route: string, params: Record<string, unknown> }} RestEndpoint
// `@typedef` {{ kind: 'discussion', nodeRef: string }} DiscussionEndpoint
// `@typedef` {RestEndpoint | DiscussionEndpoint} EventEndpoint

Call sites can then switch (endpoint.kind) instead of typeof checks.

@copilot please address this.

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.

Addressed in 3bba3d7 (with cleanup in 90c2fe7). I added explicit runtime endpoint-shape guards (expectRestEndpoint) so we no longer rely on unchecked casts. This avoids silent destructuring failures and gives a clear validation error if endpoint shape regresses.

core.setFailed(failedOutputsMessage);
return;
}
} catch (error) {

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.

[/diagnosing-bugs] The deferred core.setFailed() now runs after the finally block exits — but the finally block calls core.info('Safe Output Handler Manager completed') unconditionally. If the failure path is taken, that 'completed' log misleadingly appears before the failure message.

💡 Suggestion

Move the success-only log inside an else branch so it only fires when there is no failure:

if (failedOutputsMessage !== null) {
  core.setFailed(failedOutputsMessage);
  return;
} else {
  core.info("Safe Output Handler Manager completed");
}

@copilot please address this.

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.

Addressed in 3bba3d7. The completion log now runs only on success; when failedOutputsMessage is present we call setFailed(...) and return before emitting "Safe Output Handler Manager completed".

core.info(`Comment endpoint: ${typeof commentUpdateEndpoint === "object" ? commentUpdateEndpoint.route : commentUpdateEndpoint}`);
await addCommentWithWorkflowLink(commentUpdateEndpoint, runUrl, eventName, invocationContext);
} catch (error) {
if (isLockedError(error)) {

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.

[/tdd] The addReaction branch casts reactionEndpoint with /** @type {...} */ but no test covers the code path where reactionEndpoint is unexpectedly a plain string (e.g. from a future event type regression). Adding a test that passes a string here would catch silent destructuring failures early.

@copilot please address this.

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.

Addressed in 3bba3d7. I added a regression test that exercises the unexpected string endpoint path via expectRestEndpoint(...) and verifies it throws a validation error instead of failing later during destructuring.

@github-actions github-actions Bot 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.

REQUEST_CHANGES — Two correctness issues and one significant test-coverage regression must be addressed before merging.

### Blocking issues found

1. Deferred setFailed loses failure details on exception (safe_output_handler_manager.cjs)

The original code called core.setFailed(...) immediately after building the failure message. The new code defers it ~100 lines later. Any exception in the intervening export logic silences the N-safe-outputs-failed diagnostic — callers only see a generic validation error. See inline comment.

2. Unchecked type cast on reactionEndpoint (add_reaction_and_edit_comment.cjs)

The JSDoc union type (string | { route, params }) and a JS cast are doing the safety work instead of a runtime guard. If a new event type is added and the eventName guard is not updated, route and params will both be undefined and the error will be opaque. See inline comment.

3. Test assertions weakened: params no longer verified (add_workflow_run_comment.test.cjs)

Most add_workflow_run_comment tests dropped from asserting fully-resolved paths (which verified owner/repo/issue_number routing) to asserting only the route template string. This leaves cross-repo routing bugs invisible to the test suite. See inline comment.

🔎 Code quality review by PR Code Quality Reviewer · 346.8 AIC · ⌖ 4.91 AIC · ⊞ 5.6K
Comment /review to run again

Comments that could not be inline-anchored

actions/setup/js/safe_output_handler_manager.cjs:1744

Deferred setFailed swallows processing-failure details on exception: if any exception fires in the ~100 lines between setting failedOutputsMessage and calling setFailed, the failure-count summary is silently lost.

<details>
<summary>💡 Details and suggested fix</summary>

In the original code, setFailed was called immediately after building failedItems, so the failure message was always reported. The new code defers it to line ~1741, after a large block of output-export logic. If…

actions/setup/js/add_reaction_and_edit_comment.cjs:312

Unsafe cast on reactionEndpoint: the JSDoc type allows string | { route, params } but the cast on line 312 unconditionally treats it as the object form — if resolveEventEndpoints ever returns a string here (e.g., a discussion event falls through), this will throw a destructuring error.

<details>
<summary>💡 Details and suggested fix</summary>

The resolveEventEndpoints return type is declared as:

// `@returns` {Promise&lt;{reactionEndpoint: { route: string, params: ... } | stri…

</details>

<details><summary>actions/setup/js/add_workflow_run_comment.test.cjs:655</summary>

**Tests lost owner/repo/issue_number assertions**: the integration tests now only assert the route string (`&quot;POST /repos/{owner}/{repo}/issues/{issue_number}/comments&quot;`) but no longer verify that the correct `owner`, `repo`, or `issue_number` params are passed — exactly the bug this refactor was meant to prevent.

&lt;details&gt;
&lt;summary&gt;💡 Why this matters&lt;/summary&gt;

Before, the tests matched a fully-resolved path like `&quot;/repos/testowner/testrepo/issues/456/comments&quot;`, which implicitly proved the r…

</details>

@github-actions

Copy link
Copy Markdown
Contributor

🤖 PR Triage

Field Value
Category chore
Risk medium
Score 28/100 (impact:8, urgency:5, quality:15)
Action defer — batch: eslint-setup-js

Rationale: ESLint lint violation fixes (route interpolation, URL calls, control flow) in actions/setup/js. AI reviewer commented + GHA approved. CI running. Batch with #46102.

Generated by 🔧 PR Triage Agent · 166.4 AIC · ⌖ 6.15 AIC · ⊞ 5.6K ·

@gh-aw-bot

Copy link
Copy Markdown
Collaborator

Copilot AI and others added 2 commits July 17, 2026 07:49
Co-authored-by: gh-aw-bot <259018956+gh-aw-bot@users.noreply.github.com>
Co-authored-by: gh-aw-bot <259018956+gh-aw-bot@users.noreply.github.com>

Copilot AI commented Jul 17, 2026

Copy link
Copy Markdown
Contributor Author

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

Unresolved review thre...

Addressed the unresolved feedback in commit 2f8937b.

Changes include:

  • artifact_client.cjs: resolve ACTIONS_RESULTS_URL before guarded Twirp URL construction so origin validation errors stay visible, plus shared URL parsing helper usage.
  • safe_output_handler_manager.cjs: preserve and surface primary safe-output failure details even if later export logic throws, and only log "completed" on success.
  • Added endpoint-shape runtime guards (replacing unsafe casts) in reaction/comment helpers, with regression coverage.
  • route_slash_command.cjs: tightened reaction typing to satisfy JS typecheck failures from CI.

I also reviewed the failing check logs:

  • js-typecheck / impacted-js-tests were failing on endpoint union typing and reaction typing errors now fixed in this commit.
  • agent failed with No log sources found in the captured job logs.

I can’t re-run CI from this cloud-agent push path; please re-trigger checks from a maintainer context (close/reopen PR, workflow_dispatch, or maintainer push).

Co-authored-by: gh-aw-bot <259018956+gh-aw-bot@users.noreply.github.com>
Copilot AI requested a review from gh-aw-bot July 17, 2026 08:25
@gh-aw-bot

Copy link
Copy Markdown
Collaborator

@copilot please run the pr-finisher skill, resolve any still-unresolved review threads, and rerun checks once the branch is current. The latest replies indicate some prior feedback was addressed, but there are still open review threads on this PR that need explicit resolution or follow-up before a maintainer can verify merge readiness.

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

Copilot AI commented Jul 17, 2026

Copy link
Copy Markdown
Contributor Author

@copilot please run the pr-finisher skill, resolve any still-unresolved review threads, and rerun checks once the branch is current. The latest replies indicate some prior feedback was addressed, bu...

Ran pr-finisher and completed a fresh pass.

  • I re-triaged the PR and reviewed all currently unresolved in-scope review threads (discussion_r3600053059, r3600053084, r3600069256, r3600069260, r3600069263, r3600069265). Each already has an @copilot follow-up reply tied to the latest fixes on 90c2fe7; no additional code changes were needed in this pass.
  • I investigated the previously failed checks from logs:
    • js-typecheck and impacted-js-tests failed on TS typing errors in add_reaction_and_edit_comment.cjs, add_workflow_run_comment.cjs, route_slash_command.cjs, and safe_output_handler_manager.cjs that are addressed by current HEAD.
    • agent failed with No log sources found.
  • Local validation on current HEAD is green: make fmt, make lint, make test-unit, make test, and make recompile all passed.

I still can’t re-run GitHub checks from this cloud-agent path, and unresolved-thread state itself is not writable through the available tool path here. Please have a maintainer re-trigger CI (close/reopen PR, workflow_dispatch, or maintainer push) and resolve threads if the existing follow-ups are satisfactory.

@pelikhan

Copy link
Copy Markdown
Collaborator

@copilot merge main and recompile

Copilot AI and others added 3 commits July 17, 2026 09:32
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>

Copilot AI commented Jul 17, 2026

Copy link
Copy Markdown
Contributor Author

@copilot merge main and recompile

Done in 2da7bfbee6.

Merged origin/main into this branch and ran make recompile. I also ran make test-unit after the merge; it 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.

[eslint-monster] [Code Quality] actions/setup/js: fix route/URL/core failure-control lint findings

4 participants