Skip to content

eslint-factory: no-github-request-interpolated-route — diagnostic remedy is inapplicable for opaque whole-route helpers (\\$\{ [Content truncated due to length] #45207

Description

@github-actions

Rule

no-github-request-interpolated-route (eslint-factory/src/rules/no-github-request-interpolated-route.ts).

Summary

The single diagnostic message always prescribes the value-into-known-path remedy:

Use the typed placeholder form instead — e.g. github.request("GET /repos/{owner}/{repo}", { owner, repo }) — to preserve typed dispatch and prevent malformed paths.

That advice fits the `.../${owner}/${repo}/...` case (e.g. route_slash_command.cjs:180), where the fix is to swap interpolated values for {owner}/{repo} placeholders. But it does not fit the other grounded shape in the corpus: a generic helper that interpolates an entire, opaque route path received as a parameter.

Grounding (live corpus)

Three production sites interpolate a whole dynamic route rather than individual path segments:

  • actions/setup/js/add_reaction.cjs:193github.request(`POST ${endpoint}`, ...) (endpoint is a function parameter)
  • actions/setup/js/add_reaction_and_edit_comment.cjs:266github.request(`POST ${endpoint}`, ...)
  • actions/setup/js/add_workflow_run_comment.cjs:444github.request("POST " + endpoint, ...) (concatenation form)

For these, there is no {placeholder} rewrite: the route is opaque at the call site, so the emitted remedy ("GET /repos/{owner}/{repo}", { owner, repo }) is not actionable and can mislead a maintainer into thinking a mechanical fix exists. The real remediation is structural — thread a typed route down from the callers, or accept the route as dynamic — which is a different message than "use placeholders".

Proposed refinement

Distinguish the whole-route-dynamic shape — a TemplateLiteral / + concatenation whose only non-literal content is a single interpolated expression preceded by a leading HTTP-method-plus-space literal (`POST ${x}` / "POST " + x) — and either:

  1. Emit a tailored message for that shape (e.g. "the entire route is dynamic; pass a typed route string from the caller instead of interpolating an opaque path"), or
  2. Keep flagging it (the strictness is defensible) but drop the inapplicable {owner}/{repo} example from that variant's message, or
  3. At minimum, document in the README that opaque `${METHOD} ${routeVar}` helpers are intentionally flagged and require threading a typed route, so the three sites above are not mistaken for a mechanical placeholder fix.

(No autofix is proposed — the rewrite is not mechanical.)

Acceptance criteria

  • The rule differentiates value-into-path interpolation from whole-route interpolation (`${METHOD} ${routeVar}` / "METHOD " + routeVar) and their messages/guidance differ, OR the README explicitly documents the opaque-route case with the three grounded sites.
  • Unit tests assert the correct messageId/data for both shapes; existing tests stay green.
  • The value-into-path true positives at route_slash_command.cjs:180/192/204/216 continue to be flagged with the placeholder remedy.

Generated by 🤖 ESLint Refiner · 411.7 AIC · ⌖ 13 AIC · ⊞ 4.6K ·

  • expires on Jul 19, 2026, 10:32 PM UTC-08:00

Metadata

Metadata

Labels

cookieIssue Monster Loves Cookies!eslint

Type

No type

Fields

No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions