Skip to content

hypatia: detect required-check dependency listed only in optionalDependencies (from #333 cohort, pattern 2) #361

@hyperpolymath

Description

@hyperpolymath

Detector spec (from hypatia#333 Pattern 2)

Pattern 2 — Required-check depends on a package only listed in optionalDependencies

Severity: high (contradiction: required check that can't be installed)

Detection (Hypatia.Rules.CicdRules):

  • For each workflow job listed in branches/main/protection.required_status_checks.contexts:
    • Scan its run: steps. If any step does require("X") (or imports X) and X appears in a sibling package.json's optionalDependencies block but not in dependencies or devDependencies, flag it.
  • The combination of "required" + "optional install" is a structural contradiction.

Worked example (this session):

  • affinescript/editors/vscode/out/extension.cjs runtime-requires @hyperpolymath/affine-vscode.
  • affinescript/editors/vscode/package.json lists it in optionalDependencies (so npm install doesn't 404 when the package is missing).
  • vscode-smoke was NOT required (correct), but the same pattern in a required check would be silently broken. Was masked here by continue-on-error: true (see Pattern 5).
  • Fix: affinescript#380 embedded the adapter source at codegen time so the runtime no longer needs the optional dep at all.

Remediation guidance to emit:

Either move the dep out of optionalDependencies so installs are reliable, or remove the runtime require (embed the source / inline the adapter / use a different lookup path).

Implementation pointers

  • Detection algorithm: For each job in branches/main/protection.required_status_checks.contexts, scan run: steps for require("X")/imports; flag if X is in sibling package.json's optionalDependencies only (not in dependencies/devDependencies).
  • Real-world example: affinescript/editors/vscode/out/extension.cjs runtime-requires @hyperpolymath/affine-vscode while package.json lists it in optionalDependencies only. Masked by continue-on-error: true; would have silently broken any required check.
  • Landed fix (reference): affinescript#380 (embedded adapter source at codegen time, removing the runtime require).
  • Rule statement: Either move the dep out of optionalDependencies so installs are reliable, or remove the runtime require (embed the source / inline the adapter / use a different lookup path).

Acceptance

  • Rule encoded in hypatia (file path follows existing rule naming convention — lib/rules/<name>.ex if Elixir, or matching the repo's rule DSL)
  • Test fixture exercising the positive case + at least one negative case
  • Smoke test passes against the cited landed-fix repo

Source cohort: hypatia#333.

Metadata

Metadata

Assignees

No one assigned

    Labels

    cicdCI/CD pipeline, GitHub Actions, workflows, rulesets, releasesenhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions