A composite action with no steps still passes the checker #28

Closed
opened 2026-09-03 06:34:16 +00:00 by ahmad · 1 comment
Owner

Context

.forgejo/scripts/check-actions.py reports a runs: that is not a mapping, a steps: that is not a list, and any step that is not a mapping. One shape is still silent: runs: {using: composite} with no steps: key at all passes as ok (0 run step(s) checked).

Raised during the review of #27 and deliberately left out of it — the reviewer named it and declined to open a third round on the same theme, which was the right call. It is a weaker case than the others: the runner rejects such an action when it loads it, so this one fails loudly at use rather than reaching a consumer looking checked. That is why it is its own small issue rather than a blocker.

Scope

  • In: reporting a composite action that declares no steps.
  • Out: any other validation, and executing the actions.

Acceptance criteria

  • Given an action.yml with runs.using: composite and no steps: key, when the checker runs, then it reports the action and exits non-zero.
  • Given an action with steps: [], when the checker runs, then the behaviour is whatever this issue decides — state the choice in the pull request and say why. (An empty list is a real shape; today it passes.)
  • Given the six existing actions, when the checker runs, then they still pass.
### Context `.forgejo/scripts/check-actions.py` reports a `runs:` that is not a mapping, a `steps:` that is not a list, and any step that is not a mapping. One shape is still silent: `runs: {using: composite}` with **no** `steps:` key at all passes as `ok (0 run step(s) checked)`. Raised during the review of #27 and deliberately left out of it — the reviewer named it and declined to open a third round on the same theme, which was the right call. It is a weaker case than the others: the runner rejects such an action when it loads it, so this one fails loudly at use rather than reaching a consumer looking checked. That is why it is its own small issue rather than a blocker. ### Scope - In: reporting a composite action that declares no steps. - Out: any other validation, and executing the actions. ### Acceptance criteria - [ ] Given an `action.yml` with `runs.using: composite` and no `steps:` key, when the checker runs, then it reports the action and exits non-zero. - [ ] Given an action with `steps: []`, when the checker runs, then the behaviour is whatever this issue decides — state the choice in the pull request and say why. (An empty list is a real shape; today it passes.) - [ ] Given the six existing actions, when the checker runs, then they still pass.
ahmad self-assigned this 2026-09-04 03:33:43 +00:00
Author
Owner

Picking this up. Being explicit about why, since expiro#4 is still my open issue: its pull request is complete, reviewed and parked on the runner's Docker Hub egress — every image job on the fleet has failed for four hours — so there is no work left on it, only waiting. This repository's pipeline is validate alone and pulls no base images, so it is the one place a change can actually be finished tonight.

The gap. In check_action, steps absent means steps is not None and ... is false and isinstance(steps, list) is false, so both branches are skipped and nothing is reported. runs: {using: composite} with no steps: therefore prints ok (0 run step(s) checked).

The fix is to branch on the key's presence rather than its value, which also closes steps: written with an empty value — that lands as None today and is equally silent.

On the second criterion — steps: []. I am reporting it, and the reasoning is that it is the same defect written differently: a composite action that declares no steps does nothing, and the runner rejects it either way. Two messages rather than one, so the output says which shape it found, but the same exit code. If an empty list were ever a deliberate no-op action, that would be an argument for a comment in the file rather than for the checker staying quiet.

Scoped to composite actions only. A docker or node20 action legitimately has no steps:, so requiring them unconditionally would be wrong advice in a message. The checker already reports a using that is not composite, so nothing is missed by gating this on it.

Picking this up. Being explicit about why, since `expiro#4` is still my open issue: its pull request is complete, reviewed and parked on the runner's Docker Hub egress — every `image` job on the fleet has failed for four hours — so there is no work left on it, only waiting. This repository's pipeline is `validate` alone and pulls no base images, so it is the one place a change can actually be finished tonight. **The gap.** In `check_action`, `steps` absent means `steps is not None and ...` is false and `isinstance(steps, list)` is false, so both branches are skipped and nothing is reported. `runs: {using: composite}` with no `steps:` therefore prints `ok (0 run step(s) checked)`. **The fix** is to branch on the key's presence rather than its value, which also closes `steps:` written with an empty value — that lands as `None` today and is equally silent. **On the second criterion — `steps: []`.** I am reporting it, and the reasoning is that it is the same defect written differently: a composite action that declares no steps does nothing, and the runner rejects it either way. Two messages rather than one, so the output says which shape it found, but the same exit code. If an empty list were ever a deliberate no-op action, that would be an argument for a comment in the file rather than for the checker staying quiet. **Scoped to composite actions only.** A `docker` or `node20` action legitimately has no `steps:`, so requiring them unconditionally would be wrong advice in a message. The checker already reports a `using` that is not composite, so nothing is missed by gating this on it.
ahmad 2026-09-04 04:33:07 +00:00
Sign in to join this conversation.
No description provided.