fix(actions): reject workflow_dispatch for workflows without that trigger (#37660) (#37895)

Backport #37660 by @jorgeortiz85

## Summary

Fixes #37528

This PR makes the workflow dispatch API reject workflows that do not
declare `workflow_dispatch`. Previously, `POST
/repos/{owner}/{repo}/actions/workflows/{workflow_id}/dispatches` could
create an `ActionRun` for a workflow that only declared another event
such as `push`.

The service now validates that the target workflow has a
`workflow_dispatch` trigger before inserting the run. The API maps that
validation failure to `422 Unprocessable Entity`, matching existing
validation failures in this handler.

The regression test creates a push-only workflow, dispatches it through
the public API, asserts the `workflow_dispatch` validation message, and
verifies that no run was inserted.

## Testing

- `go test ./services/actions`
- `TAGS="sqlite sqlite_unlock_notify" make
test-integration#TestWorkflowDispatchPublicApiRequiresWorkflowDispatchTrigger`
- `TAGS="sqlite sqlite_unlock_notify" make
test-integration#TestWorkflowDispatchPublicApi`

## Disclosure

Developed with assistance from OpenAI Codex.

Co-authored-by: Jorge Ortiz <jorge.ortiz@gmail.com>
Co-authored-by: Nicolas <bircni@icloud.com>
This commit is contained in:
Giteabot
2026-05-28 20:09:08 -07:00
committed by GitHub
parent 094eeee365
commit 8bf445e86a
3 changed files with 82 additions and 4 deletions
+2
View File
@@ -1074,6 +1074,8 @@ func ActionsDispatchWorkflow(ctx *context.APIContext) {
ctx.APIError(http.StatusNotFound, err)
} else if errors.Is(err, util.ErrPermissionDenied) {
ctx.APIError(http.StatusForbidden, err)
} else if errors.Is(err, util.ErrInvalidArgument) {
ctx.APIError(http.StatusUnprocessableEntity, err)
} else {
ctx.APIErrorInternal(err)
}