mirror of
https://github.com/go-gitea/gitea.git
synced 2026-07-28 09:15:18 +02:00
Several small fixes to the Actions runner management UI.
### Runner task list links to the job, not the workflow run
Relabeled the first column from "Run" to "Job"; it now shows the job ID
and links to the specific job (`/actions/runs/{runID}/jobs/{jobID}`).
Renamed locale key `task_list.run` to `task_list.job`.
### Missing "Disabled" translation
The runner list rendered a grey label via `actions.runners.disabled`,
but that key
did not exist in `locale_en-US.json`, so the raw key string leaked into
the UI.
Replaced `"actions.runners.disabled"` with `"disabled"`.
### Status column sorting ignored active vs idle
Sorting by status ordered purely on `last_online`, but the displayed
status is
computed from both `last_online` (offline) and `last_active` (idle vs
active).
As a result idle runners were interleaved with active ones. Sorting now
ranks by
the computed status (active → idle → offline). Disabled runners sink to
the bottom
of their status group (`is_disabled` as a secondary key), with
`last_online`/`id`
as stable tiebreakers so pagination stays deterministic.
### Status label colors
Active and idle both rendered green. Idle is now yellow, active green,
and
offline/unknown grey; the separate grey "Disabled" badge is unchanged.
This keeps
connectivity visible even for disabled runners (e.g. a disabled runner
still shows
whether it is idle or offline).
<img width="715" height="406" alt="image"
src="https://github.com/user-attachments/assets/9ef06aa8-a870-4de5-9d94-603a58186908"
/>
---------
Co-authored-by: Zettat123 <zettat123@gmail.com>
84 lines
1.6 KiB
Go
84 lines
1.6 KiB
Go
// Copyright 2026 The Gitea Authors. All rights reserved.
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
package actions
|
|
|
|
import (
|
|
"testing"
|
|
"time"
|
|
|
|
"gitea.dev/modules/timeutil"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
)
|
|
|
|
func TestShouldPersistLastOnline(t *testing.T) {
|
|
now := time.Now()
|
|
tests := []struct {
|
|
name string
|
|
last timeutil.TimeStamp
|
|
want bool
|
|
}{
|
|
{
|
|
name: "fresh, skip write",
|
|
last: timeutil.TimeStamp(now.Add(-5 * time.Second).Unix()),
|
|
want: false,
|
|
},
|
|
{
|
|
name: "exactly at interval, write",
|
|
last: timeutil.TimeStamp(now.Add(-RunnerHeartbeatInterval).Unix()),
|
|
want: true,
|
|
},
|
|
{
|
|
name: "stale, write",
|
|
last: timeutil.TimeStamp(now.Add(-2 * RunnerHeartbeatInterval).Unix()),
|
|
want: true,
|
|
},
|
|
{
|
|
name: "zero (never seen), write",
|
|
last: 0,
|
|
want: true,
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
assert.Equal(t, tt.want, ShouldPersistLastOnline(tt.last, now))
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestShouldPersistLastActive(t *testing.T) {
|
|
now := time.Now()
|
|
tests := []struct {
|
|
name string
|
|
last timeutil.TimeStamp
|
|
want bool
|
|
}{
|
|
{
|
|
name: "fresh, skip write",
|
|
last: timeutil.TimeStamp(now.Add(-1 * time.Second).Unix()),
|
|
want: false,
|
|
},
|
|
{
|
|
name: "exactly at interval, write",
|
|
last: timeutil.TimeStamp(now.Add(-RunnerActiveInterval).Unix()),
|
|
want: true,
|
|
},
|
|
{
|
|
name: "stale, write",
|
|
last: timeutil.TimeStamp(now.Add(-2 * RunnerActiveInterval).Unix()),
|
|
want: true,
|
|
},
|
|
{
|
|
name: "zero (never seen), write",
|
|
last: 0,
|
|
want: true,
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
assert.Equal(t, tt.want, ShouldPersistLastActive(tt.last, now))
|
|
})
|
|
}
|
|
}
|