Add GitHub API compatibility for workflow runs filtering

Implements additional query parameters for the workflow runs API to match GitHub's REST API specification.

- Add `exclude_pull_requests` query parameter
- Add `check_suite_id` parameter
- Add `created` parameter with date range and comparison support
- Add workflow-specific endpoint `/repos/{owner}/{repo}/actions/workflows/{workflow_id}/runs`

Builds on the workflow API foundation from #33964 to provide additional GitHub API compatibility.

Reference: https://docs.github.com/en/rest/actions/workflow-runs?apiVersion=2022-11-28#list-workflow-runs-for-a-workflow
This commit is contained in:
Brice Ruth committed 2025-06-28 16:16:00 -05:00
1 parent 8df59fa11c
commit 18546ed73a
6 files changed
+505 -9

No files matched your search

+26 -9
View File
@@ -5,6 +5,7 @@ package actions
import (
"context"
"time"
"code.gitea.io/gitea/models/db"
repo_model "code.gitea.io/gitea/models/repo"
@@ -64,15 +65,19 @@ func (runs RunList) LoadRepos(ctx context.Context) error {
type FindRunOptions struct {
db.ListOptions
RepoID int64
OwnerID int64
WorkflowID string
Ref string // the commit/tag/… that caused this workflow
TriggerUserID int64
TriggerEvent webhook_module.HookEventType
Approved bool // not util.OptionalBool, it works only when it's true
Status []Status
CommitSHA string
RepoID int64
OwnerID int64
WorkflowID string
Ref string // the commit/tag/... that caused this workflow
TriggerUserID int64
TriggerEvent webhook_module.HookEventType
Approved bool // not util.OptionalBool, it works only when it's true
Status []Status
CommitSHA string
CreatedAfter time.Time
CreatedBefore time.Time
ExcludePullRequests bool
CheckSuiteID int64
}
func (opts FindRunOptions) ToConds() builder.Cond {
@@ -101,6 +106,18 @@ func (opts FindRunOptions) ToConds() builder.Cond {
if opts.CommitSHA != "" {
cond = cond.And(builder.Eq{"`action_run`.commit_sha": opts.CommitSHA})
}
if !opts.CreatedAfter.IsZero() {
cond = cond.And(builder.Gte{"`action_run`.created": opts.CreatedAfter})
}
if !opts.CreatedBefore.IsZero() {
cond = cond.And(builder.Lte{"`action_run`.created": opts.CreatedBefore})
}
if opts.ExcludePullRequests {
cond = cond.And(builder.Neq{"`action_run`.trigger_event": webhook_module.HookEventPullRequest})
}
if opts.CheckSuiteID > 0 {
cond = cond.And(builder.Eq{"`action_run`.check_suite_id": opts.CheckSuiteID})
}
return cond
}
+104
View File
@@ -0,0 +1,104 @@
// Copyright 2025 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package actions
import (
"testing"
"time"
"code.gitea.io/gitea/modules/webhook"
"github.com/stretchr/testify/assert"
"xorm.io/builder"
)
func TestFindRunOptions_ToConds_ExcludePullRequests(t *testing.T) {
// Test when ExcludePullRequests is true
opts := FindRunOptions{
ExcludePullRequests: true,
}
cond := opts.ToConds()
// Convert the condition to SQL for assertion
sql, args, err := builder.ToSQL(cond)
assert.NoError(t, err)
// The condition should contain the trigger_event not equal to pull_request
assert.Contains(t, sql, "`action_run`.trigger_event<>")
assert.Contains(t, args, webhook.HookEventPullRequest)
}
func TestFindRunOptions_ToConds_CheckSuiteID(t *testing.T) {
// Test when CheckSuiteID is set
const testSuiteID int64 = 12345
opts := FindRunOptions{
CheckSuiteID: testSuiteID,
}
cond := opts.ToConds()
// Convert the condition to SQL for assertion
sql, args, err := builder.ToSQL(cond)
assert.NoError(t, err)
// The condition should contain the check_suite_id equal to the test value
assert.Contains(t, sql, "`action_run`.check_suite_id=")
assert.Contains(t, args, testSuiteID)
}
func TestFindRunOptions_ToConds_CreatedDateRange(t *testing.T) {
// Test when CreatedAfter and CreatedBefore are set
startDate := time.Date(2023, 1, 1, 0, 0, 0, 0, time.UTC)
endDate := time.Date(2023, 12, 31, 23, 59, 59, 0, time.UTC)
opts := FindRunOptions{
CreatedAfter: startDate,
CreatedBefore: endDate,
}
cond := opts.ToConds()
// Convert the condition to SQL for assertion
sql, args, err := builder.ToSQL(cond)
assert.NoError(t, err)
// The condition should contain created >= startDate and created <= endDate
assert.Contains(t, sql, "`action_run`.created>=")
assert.Contains(t, sql, "`action_run`.created<=")
assert.Contains(t, args, startDate)
assert.Contains(t, args, endDate)
}
func TestFindRunOptions_ToConds_CreatedAfterOnly(t *testing.T) {
// Test when only CreatedAfter is set
startDate := time.Date(2023, 1, 1, 0, 0, 0, 0, time.UTC)
opts := FindRunOptions{
CreatedAfter: startDate,
}
cond := opts.ToConds()
// Convert the condition to SQL for assertion
sql, args, err := builder.ToSQL(cond)
assert.NoError(t, err)
// The condition should contain created >= startDate
assert.Contains(t, sql, "`action_run`.created>=")
assert.Contains(t, args, startDate)
// But should not contain created <= endDate
assert.NotContains(t, sql, "`action_run`.created<=")
}
func TestFindRunOptions_ToConds_CreatedBeforeOnly(t *testing.T) {
// Test when only CreatedBefore is set
endDate := time.Date(2023, 12, 31, 23, 59, 59, 0, time.UTC)
opts := FindRunOptions{
CreatedBefore: endDate,
}
cond := opts.ToConds()
// Convert the condition to SQL for assertion
sql, args, err := builder.ToSQL(cond)
assert.NoError(t, err)
// The condition should contain created <= endDate
assert.Contains(t, sql, "`action_run`.created<=")
assert.Contains(t, args, endDate)
// But should not contain created >= startDate
assert.NotContains(t, sql, "`action_run`.created>=")
}