5.1. Custom Action Types
💡 First Principle: An action is a directory containing an action.yml and whatever code that file points at — nothing more — and the runs.using value in that file selects one of three execution models whose differences in speed, portability, and packaging determine which one you should reach for.
Why care: the type decision is irreversible in practice (rewriting a Docker action as JavaScript means rewriting the action), and it's the single most testable authoring topic. Pick Docker for a step that must run on Windows and it simply won't; pick JavaScript when you needed a specific system toolchain and you'll fight dependency installation forever; pick composite when you were really just sequencing existing steps and you've saved yourself a build pipeline.
⚠️ Common Misconception: "Composite actions can only run shell commands — they can't call other actions." That was true of the original 2019 implementation and is false today: composite actions support uses: steps, so they can wrap and sequence other actions alongside run: steps. Expect this as a distractor.