fix(actions): harden log cursor, activity type and actor filter handling (#39721)

Fixes a few Actions bugs where user input or nondeterminism caused
failures:

- The job log view indexed task steps with the client-supplied cursor
step without a bounds check, so an out-of-range value panicked and
returned a 500.
- Workflow activity type filters (`types:`) were compiled with
`glob.MustCompile`, so an invalid pattern in a workflow file panicked
during event detection. Invalid patterns now simply don't match.
- Listing workflow runs with an unknown `actor` returned a 500; it now
returns 404.
- The v4 artifact `ListArtifacts` response was built by ranging over a
map, so its order changed between calls. It now follows database order.
- The error from marshalling a workflow job when inserting run jobs was
silently ignored.

---------

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
This commit is contained in:
bircniandwxiaoguang authored and GitHub committed 2026-10-10 19:52:23 +00:00
1 parent 321d3ec104
commit 8a9e8c4e8c
13 files changed
+70 -28

No files matched your search

+18 -8
View File
@@ -532,7 +532,7 @@ func matchIssuesEvent(issuePayload *api.IssuePayload, evt *jobparser.Event) bool
}
for _, val := range vals {
if slices.ContainsFunc(actions, glob.MustCompile(val, '/').Match) {
if matchActivityType(val, actions...) {
matchTimes++
break
}
@@ -575,7 +575,7 @@ func matchPullRequestEvent(ctx context.Context, gitRepo *git.Repository, commit
}
log.Trace("matching pull_request %s with %v", action, vals)
for _, val := range vals {
if glob.MustCompile(val, '/').Match(string(action)) {
if matchActivityType(val, string(action)) {
activityTypeMatched = true
matchTimes++
break
@@ -678,7 +678,7 @@ func matchIssueCommentEvent(issueCommentPayload *api.IssueCommentPayload, evt *j
// NONE
for _, val := range vals {
if glob.MustCompile(val, '/').Match(string(issueCommentPayload.Action)) {
if matchActivityType(val, string(issueCommentPayload.Action)) {
matchTimes++
break
}
@@ -718,7 +718,7 @@ func matchPullRequestReviewEvent(prPayload *api.PullRequestPayload, evt *jobpars
}
for _, val := range vals {
if slices.ContainsFunc(actions, glob.MustCompile(val, '/').Match) {
if matchActivityType(val, actions...) {
matchTimes++
break
}
@@ -758,7 +758,7 @@ func matchPullRequestReviewCommentEvent(prPayload *api.PullRequestPayload, evt *
}
for _, val := range vals {
if slices.ContainsFunc(actions, glob.MustCompile(val, '/').Match) {
if matchActivityType(val, actions...) {
matchTimes++
break
}
@@ -795,7 +795,7 @@ func matchReleaseEvent(payload *api.ReleasePayload, evt *jobparser.Event) bool {
action = "edited"
}
for _, val := range vals {
if glob.MustCompile(val, '/').Match(string(action)) {
if matchActivityType(val, string(action)) {
matchTimes++
break
}
@@ -832,7 +832,7 @@ func matchPackageEvent(payload *api.PackagePayload, evt *jobparser.Event) bool {
action = "published"
}
for _, val := range vals {
if glob.MustCompile(val, '/').Match(string(action)) {
if matchActivityType(val, string(action)) {
matchTimes++
break
}
@@ -857,7 +857,7 @@ func matchWorkflowRunEvent(payload *api.WorkflowRunPayload, evt *jobparser.Event
case "types":
action := payload.Action
for _, val := range vals {
if glob.MustCompile(val, '/').Match(action) {
if matchActivityType(val, action) {
matchTimes++
break
}
@@ -893,3 +893,13 @@ func matchWorkflowRunEvent(payload *api.WorkflowRunPayload, evt *jobparser.Event
}
return matchTimes == len(evt.Acts())
}
// matchActivityType treats an invalid user-provided pattern as no match instead of panicking
func matchActivityType(pattern string, actions ...string) bool {
g, err := glob.Compile(pattern, '/')
if err != nil {
log.Debug("invalid activity type pattern %q: %v", pattern, err)
return false
}
return slices.ContainsFunc(actions, g.Match)
}
+7
View File
@@ -210,6 +210,13 @@ func TestDetectMatched(t *testing.T) {
yamlOn: "on:\n release:\n types: [published]",
expected: detectMatched,
},
{
desc: "HookEventRelease(release) doesn't match an invalid activity type pattern",
triggedEvent: webhook_module.HookEventRelease,
payload: &api.ReleasePayload{Action: api.HookReleasePublished},
yamlOn: "on:\n release:\n types: [\"[\"]",
expected: detectNotApplicable,
},
{
desc: "HookEventPackage(package) `created` action doesn't match GithubEventRegistryPackage(registry_package) with `updated` activity type",
triggedEvent: webhook_module.HookEventPackage,
+1 -1
View File
@@ -177,7 +177,7 @@ func initGlobCompiler(g *globCompiler, pattern string, separators []rune) (Glob,
regex, err := regexp.Compile(g.regexpPattern)
if err != nil {
return nil, fmt.Errorf("failed to compile regexp: %w", err)
return nil, fmt.Errorf("failed to compile glob regexp: %w", err)
}
g.regexp = regex