chore: increase test coverage of runner management (#10490)

Ensures that admins, users, etc. see the runners they are allowed to see.

Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/10490
Reviewed-by: Gusted <gusted@noreply.codeberg.org>
Co-authored-by: Andreas Ahlenstorf <andreas@ahlenstorf.ch>
Co-committed-by: Andreas Ahlenstorf <andreas@ahlenstorf.ch>
This commit is contained in:
Andreas Ahlenstorf 2025-12-20 15:29:40 +01:00 committed by Gusted
parent 8ef34a56d1
commit 0e6f9439ee
3 changed files with 219 additions and 0 deletions

View file

@ -140,3 +140,98 @@ func TestDeleteOfflineRunnersErrorOnInvalidOlderThanValue(t *testing.T) {
defer timeutil.MockUnset()
require.Error(t, DeleteOfflineRunners(db.DefaultContext, timeutil.TimeStampNow(), false))
}
func TestRunnerEditable(t *testing.T) {
testCases := []struct {
name string
runner *ActionRunner
ownerID int64
repoID int64
editable bool
}{
{
name: "admin-can-edit-global-runner",
runner: &ActionRunner{Name: "global-runner", OwnerID: 0, RepoID: 0},
ownerID: 0,
repoID: 0,
editable: true,
},
{
name: "admin-can-edit-user-runner",
runner: &ActionRunner{Name: "user-runner", OwnerID: 36, RepoID: 0},
ownerID: 0,
repoID: 0,
editable: true,
},
{
name: "admin-can-edit-repository-runner",
runner: &ActionRunner{Name: "user-runner", OwnerID: 0, RepoID: 110},
ownerID: 0,
repoID: 0,
editable: true,
},
{
name: "user-can-edit-its-runner",
runner: &ActionRunner{Name: "user-runner", OwnerID: 469, RepoID: 0},
ownerID: 469,
repoID: 0,
editable: true,
},
{
name: "user-cannot-edit-global-runner",
runner: &ActionRunner{Name: "global-runner", OwnerID: 0, RepoID: 0},
ownerID: 469,
repoID: 0,
editable: false,
},
{
name: "user-cannot-edit-other-users-runner",
runner: &ActionRunner{Name: "user-runner", OwnerID: 892, RepoID: 0},
ownerID: 469,
repoID: 0,
editable: false,
},
{
name: "user-cannot-edit-repo-runner",
runner: &ActionRunner{Name: "repo-runner", OwnerID: 0, RepoID: 151},
ownerID: 469,
repoID: 0,
editable: false,
},
{
name: "repo-can-edit-its-runner",
runner: &ActionRunner{Name: "repo-runner", OwnerID: 0, RepoID: 693},
ownerID: 0,
repoID: 693,
editable: true,
},
{
name: "repo-cannot-edit-other-repo-runner",
runner: &ActionRunner{Name: "repo-runner", OwnerID: 0, RepoID: 519},
ownerID: 0,
repoID: 693,
editable: false,
},
{
name: "repo-cannot-edit-global-runner",
runner: &ActionRunner{Name: "global-runner", OwnerID: 0, RepoID: 0},
ownerID: 0,
repoID: 693,
editable: false,
},
{
name: "repo-cannot-edit-user-runner",
runner: &ActionRunner{Name: "user-runner", OwnerID: 6, RepoID: 0},
ownerID: 0,
repoID: 693,
editable: false,
},
}
for _, testCase := range testCases {
t.Run(testCase.name, func(t *testing.T) {
result := testCase.runner.Editable(testCase.ownerID, testCase.repoID)
assert.Equal(t, testCase.editable, result)
})
}
}

View file

@ -0,0 +1,54 @@
- id: 719931
uuid: "8f940b0b-32a2-479a-9d48-06ab8d8a0b90"
name: "runner-1"
version: "dev"
owner_id: 3
repo_id: 0
description: "A superb runner"
agent_labels: ["debian", "gpu"]
deleted: 0
- id: 719932
uuid: "3a20ad8d-d5d6-4b7b-ba55-841ac8264c17"
name: "runner-2"
version: "11.3.1"
owner_id: 2
repo_id: 0
description: "An exclusive runner"
agent_labels: ["docker"]
deleted: 0
- id: 719933
uuid: "11c9a6da-0a92-46ea-a4f1-b6c98f8c781c"
name: "runner-3"
version: "11.3.1"
owner_id: 17
repo_id: 0
description: "Another fine runner"
agent_labels: ["fedora"]
deleted: 0
- id: 719934
uuid: "1ef59b64-93b7-4ad4-ade4-21ca13db49c0"
name: "runner-4"
version: "12.2.0"
owner_id: 0
repo_id: 0
description: "A runner for everyone"
agent_labels: ["docker"]
deleted: 0
- id: 719935
uuid: "69d29449-1de5-4d17-845d-e3ae11a04a1b"
name: "runner-5"
version: "12.0.0"
owner_id: 1
repo_id: 0
description: ""
agent_labels: ["debian"]
deleted: 0
- id: 719936
uuid: "9da25fbb-89a5-4520-a35a-d55fc94e4b76"
name: "runner-6"
version: "12.1.0"
owner_id: 0
repo_id: 62
description: ""
agent_labels: ["debian"]
deleted: 0

View file

@ -121,3 +121,73 @@ func TestRunnerModification(t *testing.T) {
})
})
}
func TestRunnerVisibility(t *testing.T) {
defer unittest.OverrideFixtures("tests/integration/fixtures/TestRunnerVisibility")()
defer tests.PrepareTestEnv(t)()
admin := unittest.AssertExistsAndLoadBean(t, &user_model.User{IsAdmin: true})
user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
runnerOne := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionRunner{ID: 719931})
runnerTwo := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionRunner{ID: 719932})
runnerThree := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionRunner{ID: 719933})
runnerFour := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionRunner{ID: 719934})
runnerFive := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionRunner{ID: 719935})
runnerSix := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionRunner{ID: 719936})
testCases := []struct {
name string
user *user_model.User
url string
expectedRunners []*actions_model.ActionRunner
unexpectedRunners []*actions_model.ActionRunner
}{
{
name: "admin-sees-all",
user: admin,
url: "/admin/actions/runners",
expectedRunners: []*actions_model.ActionRunner{runnerOne, runnerTwo, runnerThree, runnerFour, runnerFive, runnerSix},
unexpectedRunners: []*actions_model.ActionRunner{},
},
{
name: "user-sees-own-and-global",
user: user2,
url: "user/settings/actions/runners",
expectedRunners: []*actions_model.ActionRunner{runnerTwo, runnerFour},
unexpectedRunners: []*actions_model.ActionRunner{runnerOne, runnerThree, runnerFive, runnerSix},
},
{
name: "org-sees-own-and-global",
user: user2,
url: "/org/org3/settings/actions/runners",
expectedRunners: []*actions_model.ActionRunner{runnerOne, runnerFour},
unexpectedRunners: []*actions_model.ActionRunner{runnerTwo, runnerThree, runnerFive, runnerSix},
},
{
name: "user-repo-sees-own-and-users-and-global",
user: user2,
url: "/user2/test_workflows/settings/actions/runners",
expectedRunners: []*actions_model.ActionRunner{runnerTwo, runnerFour, runnerSix},
unexpectedRunners: []*actions_model.ActionRunner{runnerOne, runnerThree, runnerFive},
},
}
for _, testCase := range testCases {
t.Run(testCase.name, func(t *testing.T) {
session := loginUser(t, testCase.user.Name)
request := NewRequest(t, "GET", testCase.url)
response := session.MakeRequest(t, request, http.StatusOK)
htmlDoc := NewHTMLParser(t, response.Body)
for _, expectedRunner := range testCase.expectedRunners {
selector := fmt.Sprintf("td:contains('%s')", expectedRunner.Name)
assert.Equal(t, 1, htmlDoc.Find(selector).Length(), "runner '%s' could not be found", expectedRunner.Name)
}
for _, unexpectedRunner := range testCase.unexpectedRunners {
selector := fmt.Sprintf("td:contains('%s')", unexpectedRunner.Name)
assert.Zero(t, htmlDoc.Find(selector).Length(), "runner '%s' is unexpectedly present", unexpectedRunner.Name)
}
})
}
}