Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions options/locale/locale_en-US.json
Original file line number Diff line number Diff line change
Expand Up @@ -3796,6 +3796,7 @@
"actions.runners.delete_runner_header": "Confirm to delete this runner",
"actions.runners.delete_runner_notice": "If a task is running on this runner, it will be terminated and marked as failed. It may break building workflow.",
"actions.runners.none": "No runners available",
"actions.runners.per_page": "%d per page",

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

would make this a more generic num_per_page

"actions.runners.status.unspecified": "Unknown",
"actions.runners.status.idle": "Idle",
"actions.runners.status.active": "Active",
Expand Down
16 changes: 15 additions & 1 deletion routers/web/shared/actions/runners.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"fmt"
"net/http"
"net/url"
"slices"

actions_model "gitea.dev/models/actions"
"gitea.dev/models/db"
Expand All @@ -34,6 +35,11 @@ const (
tplUserRunnerEdit templates.TplName = "user/settings/runner_edit"
)

// runnersPageSizes are the selectable "runners per page" values on the runner management page.
var runnersPageSizes = []int{25, 50, 100, 200}

const runnersDefaultPageSize = 100
Comment on lines +38 to +41

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here also comes a question: what benefits does the "selectable items per page" bring?

Isn't it "the more the better" in most cases?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so what do you suggest? showing always all?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mean maybe a default 50 or 100 is good enough? No need to make it "selectable". We never did so on other pages. If we'd really like to make the "limit" selectable, we need a plan to consider all pages.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It just annoyed me yesterday as I have 102 runners 😂

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I could agree 100 seems too many ...

So reduce it to 50?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's too less...

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, I misunderstood. Maybe you mean you need a large limit to see all?


From UI/UX perspective, I don't see why a list should show too many items, it exceeds human processing capabilities. When the list is large, usually it needs to support "search" or "filter".

And, Gitea already has a lot of config options under [ui] [ui.admin] [ui.user] etc, some preference settings are stored in local storage, etc. There were also discussions about "adding per-user setting", etc.


So overall there are already many different approaches. If we don't have a plan, and the problem is trivial, I'd prefer to keep things simple until we a design which is universally applicable to most pages, instead of ad-hoc "improvements"

@wxiaoguang wxiaoguang Aug 29, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually I also have a question: now you have 102 runners and would like to add "limit=200", then some days later, if you have 202 or 1002 runners, would you add "limit=300/500/2000" then?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Totally agree - maybe instead of having a lot of config options for pagination we could add one global which triggers for all.
Just an idea...


type runnersCtx struct {
OwnerID int64
RepoID int64
Expand Down Expand Up @@ -111,10 +117,15 @@ func Runners(ctx *context.Context) {

page := max(ctx.FormInt("page"), 1)

pageSize := ctx.FormInt("limit")
if !slices.Contains(runnersPageSizes, pageSize) {
pageSize = runnersDefaultPageSize
}

opts := actions_model.FindRunnerOptions{
ListOptions: db.ListOptions{
Page: page,
PageSize: 100,
PageSize: pageSize,
},
Sort: ctx.Req.URL.Query().Get("sort"),
Filter: ctx.Req.URL.Query().Get("q"),
Expand Down Expand Up @@ -160,8 +171,11 @@ func Runners(ctx *context.Context) {
ctx.Data["RunnerRepoID"] = opts.RepoID
ctx.Data["SortType"] = opts.Sort
ctx.Data["AllowBulkActions"] = rCtx.IsAdmin
ctx.Data["PageSize"] = pageSize
ctx.Data["PageSizes"] = runnersPageSizes

pager := context.NewPagination(count, opts.PageSize, opts.Page, 5)
pager.AddParamFromRequest(ctx.Req)

ctx.Data["Page"] = pager

Expand Down
18 changes: 16 additions & 2 deletions templates/shared/actions/runner_list.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,24 @@

</div>
</h4>
<div class="ui attached segment">
<form class="ui form ignore-dirty" id="user-list-search-form" action="{{$.Link}}">
<div class="ui attached segment flex-text-block">
<form class="ui form ignore-dirty tw-flex-1" id="user-list-search-form" action="{{$.Link}}">
{{if .SortType}}<input type="hidden" name="sort" value="{{.SortType}}">{{end}}
<input type="hidden" name="limit" value="{{.PageSize}}">
{{template "shared/search/combo" dict "Value" .Keyword "Placeholder" (ctx.Locale.Tr "search.runner_kind")}}
</form>
{{$queryLink := QueryBuild "?" "q" $.Keyword "sort" $.SortType}}
<div class="ui dropdown jump">
<button class="ui small button">
{{ctx.Locale.Tr "actions.runners.per_page" .PageSize}}
{{svg "octicon-triangle-down" 14 "dropdown icon"}}
</button>
<div class="menu">
{{range .PageSizes}}
<a class="item{{if eq . $.PageSize}} active selected{{end}}" href="{{QueryBuild $queryLink "limit" .}}">{{ctx.Locale.Tr "actions.runners.per_page" .}}</a>
{{end}}
</div>
</div>
</div>
{{if .AllowBulkActions}}
<div class="ui attached segment tw-hidden" data-global-init="initRunnerBulkToolbar">
Expand Down
34 changes: 34 additions & 0 deletions tests/integration/actions_runner_modify_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,44 @@ import (
"gitea.dev/modules/base"
"gitea.dev/tests"

"github.com/PuerkitoBio/goquery"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func TestActionsRunnerListPagination(t *testing.T) {
defer tests.PrepareTestEnv(t)()

ctx := t.Context()
require.NoError(t, db.DeleteAllRecords("action_runner"))
for i := range 26 {
require.NoError(t, actions_model.CreateRunner(ctx, &actions_model.ActionRunner{
Name: fmt.Sprintf("global-runner-%02d", i),
TokenHash: fmt.Sprintf("h%d", i),
UUID: fmt.Sprintf("h%d", i),
}))
}

session := loginUser(t, "user1")
req := NewRequest(t, "GET", "/-/admin/actions/runners?sort=newest&limit=25")
resp := session.MakeRequest(t, req, http.StatusOK)
htmlDoc := NewHTMLParser(t, resp.Body)

// the chosen page size is reflected in the per-page selector
assert.Positive(t, htmlDoc.Find(`.dropdown .menu a.item.active[href*="limit=25"]`).Length())

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

First, the active is abused. active doesn't mean selected, you can take a look at the source code.

Second, I really doubt about the value of such TestActionsRunnerListPagination test. It only queries some links on the page loosely, while the links are all built by framework AddParamFromRequest and QueryBuild. I don't see what kind of regression bugs the test would catch in the future.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe we need this first: refactor: pagination/pager - #39162

Then the page links are always correct. It doesn't make sense to keep testing all the links again and again for all pages.


// pagination links carry both the sort and the page size across pages
var pagerHrefs []string
htmlDoc.Find(".page.buttons a[href]").Each(func(_ int, s *goquery.Selection) {
pagerHrefs = append(pagerHrefs, s.AttrOr("href", ""))
})
require.NotEmpty(t, pagerHrefs)
for _, href := range pagerHrefs {
assert.Contains(t, href, "sort=newest", "pagination link must keep the sort: %s", href)
assert.Contains(t, href, "limit=25", "pagination link must keep the page size: %s", href)
}
}

func TestActionsRunnerModify(t *testing.T) {
defer tests.PrepareTestEnv(t)()

Expand Down
Loading