2024-05-19 10:46:15 +00:00
|
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
|
|
|
|
|
|
package actions
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"encoding/binary"
|
|
|
|
|
"fmt"
|
|
|
|
|
"testing"
|
2025-06-08 00:13:37 +02:00
|
|
|
"time"
|
2024-05-19 10:46:15 +00:00
|
|
|
|
2025-03-27 19:40:14 +00:00
|
|
|
auth_model "forgejo.org/models/auth"
|
|
|
|
|
"forgejo.org/models/db"
|
feat: add form-based runner management (#11516)
Forgejo Runner is deprecating the runner registration token. It is too powerful, requires tooling, and is unnecessary. As a consequence, users need new mechanisms for managing runners in Forgejo. https://codeberg.org/forgejo/forgejo/pulls/10677 added an HTTP API for runner registration. This PR adds the ability to manage runners using Forgejo's web interface.
Runners can be added, modified, and deleted. It is also possible to regenerate a runner's token. When a runner is added or a runner's token is regenerated, setup instructions are displayed. They explain how to alter Forgejo Runner's configuration file or how to launch `forgejo-runner daemon` (yet to be implemented). The existing details page has been overhauled and is now accessible to all users that are allowed to use a particular runner. The details page displays additional information that had to be removed from the list of runners due to space constraints. The task list is filtered. That means it only lists jobs of the respective repository, user, or organization.
The runner registration token has been marked as deprecated.
See https://code.forgejo.org/forgejo/forgejo-actions-feature-requests/issues/88 for context and design considerations.
## Checklist
The [contributor guide](https://forgejo.org/docs/next/contributor/) contains information that will be helpful to first time contributors. There also are a few [conditions for merging Pull Requests in Forgejo repositories](https://codeberg.org/forgejo/governance/src/branch/main/PullRequestsAgreement.md). You are also welcome to join the [Forgejo development chatroom](https://matrix.to/#/#forgejo-development:matrix.org).
### Tests for Go changes
(can be removed for JavaScript changes)
- I added test coverage for Go changes...
- [x] in their respective `*_test.go` for unit tests.
- [x] in the `tests/integration` directory if it involves interactions with a live Forgejo server.
- I ran...
- [x] `make pr-go` before pushing
### Tests for JavaScript changes
(can be removed for Go changes)
- I added test coverage for JavaScript changes...
- [ ] in `web_src/js/*.test.js` if it can be unit tested.
- [x] in `tests/e2e/*.test.e2e.js` if it requires interactions with a live Forgejo server (see also the [developer guide for JavaScript testing](https://codeberg.org/forgejo/forgejo/src/branch/forgejo/tests/e2e/README.md#end-to-end-tests)).
### Documentation
- [ ] I created a pull request [to the documentation](https://codeberg.org/forgejo/docs) to explain to Forgejo users how to use this change.
- [x] I did not document these changes and I do not expect someone else to do it.
### Release notes
- [x] This change will be noticed by a Forgejo user or admin (feature, bug fix, performance, etc.). I suggest to include a release note for this change.
- [ ] This change is not visible to a Forgejo user or admin (refactor, dependency upgrade, etc.). I think there is no need to add a release note for this change.
*The decision if the pull request will be shown in the release notes is up to the mergers / release team.*
The content of the `release-notes/<pull request number>.md` file will serve as the basis for the release notes. If the file does not exist, the title of the pull request will be used instead.
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/11516
Reviewed-by: Mathieu Fenniak <mfenniak@noreply.codeberg.org>
Co-authored-by: Andreas Ahlenstorf <andreas@ahlenstorf.ch>
Co-committed-by: Andreas Ahlenstorf <andreas@ahlenstorf.ch>
2026-03-12 02:14:45 +01:00
|
|
|
"forgejo.org/models/repo"
|
2025-03-27 19:40:14 +00:00
|
|
|
"forgejo.org/models/unittest"
|
2025-06-08 00:13:37 +02:00
|
|
|
"forgejo.org/modules/timeutil"
|
2024-05-19 10:46:15 +00:00
|
|
|
|
|
|
|
|
"github.com/stretchr/testify/assert"
|
2024-07-22 11:55:43 +02:00
|
|
|
"github.com/stretchr/testify/require"
|
2024-05-19 10:46:15 +00:00
|
|
|
)
|
|
|
|
|
|
2024-07-22 11:55:43 +02:00
|
|
|
// TestUpdateSecret checks that ActionRunner.UpdateSecret() sets the Token,
|
|
|
|
|
// TokenSalt and TokenHash fields based on the specified token.
|
|
|
|
|
func TestUpdateSecret(t *testing.T) {
|
|
|
|
|
runner := ActionRunner{}
|
|
|
|
|
token := "0123456789012345678901234567890123456789"
|
|
|
|
|
|
|
|
|
|
err := runner.UpdateSecret(token)
|
|
|
|
|
|
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
assert.Equal(t, token, runner.Token)
|
|
|
|
|
assert.Regexp(t, "^[0-9a-f]{32}$", runner.TokenSalt)
|
|
|
|
|
assert.Equal(t, runner.TokenHash, auth_model.HashToken(token, runner.TokenSalt))
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-19 10:46:15 +00:00
|
|
|
func TestDeleteRunner(t *testing.T) {
|
|
|
|
|
const recordID = 12345678
|
2024-07-30 19:41:10 +00:00
|
|
|
require.NoError(t, unittest.PrepareTestDatabase())
|
2024-05-19 10:46:15 +00:00
|
|
|
before := unittest.AssertExistsAndLoadBean(t, &ActionRunner{ID: recordID})
|
|
|
|
|
|
2025-01-25 08:51:59 +01:00
|
|
|
err := DeleteRunner(db.DefaultContext, &ActionRunner{ID: recordID})
|
2024-07-30 19:41:10 +00:00
|
|
|
require.NoError(t, err)
|
2024-05-19 10:46:15 +00:00
|
|
|
|
|
|
|
|
var after ActionRunner
|
|
|
|
|
found, err := db.GetEngine(db.DefaultContext).ID(recordID).Unscoped().Get(&after)
|
2024-07-30 19:41:10 +00:00
|
|
|
require.NoError(t, err)
|
2024-05-19 10:46:15 +00:00
|
|
|
assert.True(t, found)
|
|
|
|
|
|
|
|
|
|
// Most fields (namely Name, Version, OwnerID, RepoID, Description, Base, RepoRange,
|
|
|
|
|
// TokenHash, TokenSalt, LastOnline, LastActive, AgentLabels and Created) are unaffected
|
|
|
|
|
assert.Equal(t, before.Name, after.Name)
|
|
|
|
|
assert.Equal(t, before.Version, after.Version)
|
|
|
|
|
assert.Equal(t, before.OwnerID, after.OwnerID)
|
|
|
|
|
assert.Equal(t, before.RepoID, after.RepoID)
|
|
|
|
|
assert.Equal(t, before.Description, after.Description)
|
|
|
|
|
assert.Equal(t, before.Base, after.Base)
|
|
|
|
|
assert.Equal(t, before.RepoRange, after.RepoRange)
|
|
|
|
|
assert.Equal(t, before.TokenHash, after.TokenHash)
|
|
|
|
|
assert.Equal(t, before.TokenSalt, after.TokenSalt)
|
|
|
|
|
assert.Equal(t, before.LastOnline, after.LastOnline)
|
|
|
|
|
assert.Equal(t, before.LastActive, after.LastActive)
|
|
|
|
|
assert.Equal(t, before.AgentLabels, after.AgentLabels)
|
|
|
|
|
assert.Equal(t, before.Created, after.Created)
|
|
|
|
|
|
|
|
|
|
// Deleted contains a value
|
|
|
|
|
assert.NotNil(t, after.Deleted)
|
|
|
|
|
|
|
|
|
|
// UUID was modified
|
|
|
|
|
assert.NotEqual(t, before.UUID, after.UUID)
|
|
|
|
|
// UUID starts with ffffffff-ffff-ffff-
|
|
|
|
|
assert.Equal(t, "ffffffff-ffff-ffff-", after.UUID[:19])
|
|
|
|
|
// UUID ends with LE binary representation of record ID
|
|
|
|
|
idAsBinary := make([]byte, 8)
|
|
|
|
|
binary.LittleEndian.PutUint64(idAsBinary, uint64(recordID))
|
|
|
|
|
idAsHexadecimal := fmt.Sprintf("%.2x%.2x-%.2x%.2x%.2x%.2x%.2x%.2x", idAsBinary[0],
|
|
|
|
|
idAsBinary[1], idAsBinary[2], idAsBinary[3], idAsBinary[4], idAsBinary[5],
|
|
|
|
|
idAsBinary[6], idAsBinary[7])
|
|
|
|
|
assert.Equal(t, idAsHexadecimal, after.UUID[19:])
|
|
|
|
|
}
|
2025-06-08 00:13:37 +02:00
|
|
|
|
|
|
|
|
func TestDeleteOfflineRunnersRunnerGlobalOnly(t *testing.T) {
|
|
|
|
|
baseTime := time.Date(2024, 5, 19, 7, 40, 32, 0, time.UTC)
|
|
|
|
|
timeutil.MockSet(baseTime)
|
|
|
|
|
defer timeutil.MockUnset()
|
|
|
|
|
|
|
|
|
|
require.NoError(t, unittest.PrepareTestDatabase())
|
|
|
|
|
|
|
|
|
|
olderThan := timeutil.TimeStampNow().Add(-timeutil.Hour)
|
|
|
|
|
|
|
|
|
|
require.NoError(t, DeleteOfflineRunners(db.DefaultContext, olderThan, true))
|
|
|
|
|
|
|
|
|
|
// create at test base time
|
|
|
|
|
unittest.AssertExistsAndLoadBean(t, &ActionRunner{ID: 12345678})
|
|
|
|
|
// last_online test base time
|
|
|
|
|
unittest.AssertExistsAndLoadBean(t, &ActionRunner{ID: 10000001})
|
|
|
|
|
// created one month ago but a repo
|
|
|
|
|
unittest.AssertExistsAndLoadBean(t, &ActionRunner{ID: 10000002})
|
|
|
|
|
// last online one hour ago
|
|
|
|
|
unittest.AssertNotExistsBean(t, &ActionRunner{ID: 10000003})
|
|
|
|
|
// last online 10 seconds ago
|
|
|
|
|
unittest.AssertExistsAndLoadBean(t, &ActionRunner{ID: 10000004})
|
|
|
|
|
// created 1 month ago
|
|
|
|
|
unittest.AssertExistsAndLoadBean(t, &ActionRunner{ID: 10000005})
|
|
|
|
|
// created 1 hour ago
|
|
|
|
|
unittest.AssertExistsAndLoadBean(t, &ActionRunner{ID: 10000006})
|
|
|
|
|
// last online 1 hour ago
|
|
|
|
|
unittest.AssertExistsAndLoadBean(t, &ActionRunner{ID: 10000007})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestDeleteOfflineRunnersAll(t *testing.T) {
|
|
|
|
|
baseTime := time.Date(2024, 5, 19, 7, 40, 32, 0, time.UTC)
|
|
|
|
|
timeutil.MockSet(baseTime)
|
|
|
|
|
defer timeutil.MockUnset()
|
|
|
|
|
|
|
|
|
|
require.NoError(t, unittest.PrepareTestDatabase())
|
|
|
|
|
|
|
|
|
|
olderThan := timeutil.TimeStampNow().Add(-timeutil.Hour)
|
|
|
|
|
|
|
|
|
|
require.NoError(t, DeleteOfflineRunners(db.DefaultContext, olderThan, false))
|
|
|
|
|
|
|
|
|
|
// create at test base time
|
|
|
|
|
unittest.AssertExistsAndLoadBean(t, &ActionRunner{ID: 12345678})
|
|
|
|
|
// last_online test base time
|
|
|
|
|
unittest.AssertExistsAndLoadBean(t, &ActionRunner{ID: 10000001})
|
|
|
|
|
// created one month ago
|
|
|
|
|
unittest.AssertNotExistsBean(t, &ActionRunner{ID: 10000002})
|
|
|
|
|
// last online one hour ago
|
|
|
|
|
unittest.AssertNotExistsBean(t, &ActionRunner{ID: 10000003})
|
|
|
|
|
// last online 10 seconds ago
|
|
|
|
|
unittest.AssertExistsAndLoadBean(t, &ActionRunner{ID: 10000004})
|
|
|
|
|
// created 1 month ago
|
|
|
|
|
unittest.AssertNotExistsBean(t, &ActionRunner{ID: 10000005})
|
|
|
|
|
// created 1 hour ago
|
|
|
|
|
unittest.AssertExistsAndLoadBean(t, &ActionRunner{ID: 10000006})
|
|
|
|
|
// last online 1 hour ago
|
|
|
|
|
unittest.AssertExistsAndLoadBean(t, &ActionRunner{ID: 10000007})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestDeleteOfflineRunnersErrorOnInvalidOlderThanValue(t *testing.T) {
|
|
|
|
|
baseTime := time.Date(2024, 5, 19, 7, 40, 32, 0, time.UTC)
|
|
|
|
|
timeutil.MockSet(baseTime)
|
|
|
|
|
defer timeutil.MockUnset()
|
|
|
|
|
require.Error(t, DeleteOfflineRunners(db.DefaultContext, timeutil.TimeStampNow(), false))
|
|
|
|
|
}
|
2025-12-20 15:29:40 +01:00
|
|
|
|
|
|
|
|
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)
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
}
|
feat: add form-based runner management (#11516)
Forgejo Runner is deprecating the runner registration token. It is too powerful, requires tooling, and is unnecessary. As a consequence, users need new mechanisms for managing runners in Forgejo. https://codeberg.org/forgejo/forgejo/pulls/10677 added an HTTP API for runner registration. This PR adds the ability to manage runners using Forgejo's web interface.
Runners can be added, modified, and deleted. It is also possible to regenerate a runner's token. When a runner is added or a runner's token is regenerated, setup instructions are displayed. They explain how to alter Forgejo Runner's configuration file or how to launch `forgejo-runner daemon` (yet to be implemented). The existing details page has been overhauled and is now accessible to all users that are allowed to use a particular runner. The details page displays additional information that had to be removed from the list of runners due to space constraints. The task list is filtered. That means it only lists jobs of the respective repository, user, or organization.
The runner registration token has been marked as deprecated.
See https://code.forgejo.org/forgejo/forgejo-actions-feature-requests/issues/88 for context and design considerations.
## Checklist
The [contributor guide](https://forgejo.org/docs/next/contributor/) contains information that will be helpful to first time contributors. There also are a few [conditions for merging Pull Requests in Forgejo repositories](https://codeberg.org/forgejo/governance/src/branch/main/PullRequestsAgreement.md). You are also welcome to join the [Forgejo development chatroom](https://matrix.to/#/#forgejo-development:matrix.org).
### Tests for Go changes
(can be removed for JavaScript changes)
- I added test coverage for Go changes...
- [x] in their respective `*_test.go` for unit tests.
- [x] in the `tests/integration` directory if it involves interactions with a live Forgejo server.
- I ran...
- [x] `make pr-go` before pushing
### Tests for JavaScript changes
(can be removed for Go changes)
- I added test coverage for JavaScript changes...
- [ ] in `web_src/js/*.test.js` if it can be unit tested.
- [x] in `tests/e2e/*.test.e2e.js` if it requires interactions with a live Forgejo server (see also the [developer guide for JavaScript testing](https://codeberg.org/forgejo/forgejo/src/branch/forgejo/tests/e2e/README.md#end-to-end-tests)).
### Documentation
- [ ] I created a pull request [to the documentation](https://codeberg.org/forgejo/docs) to explain to Forgejo users how to use this change.
- [x] I did not document these changes and I do not expect someone else to do it.
### Release notes
- [x] This change will be noticed by a Forgejo user or admin (feature, bug fix, performance, etc.). I suggest to include a release note for this change.
- [ ] This change is not visible to a Forgejo user or admin (refactor, dependency upgrade, etc.). I think there is no need to add a release note for this change.
*The decision if the pull request will be shown in the release notes is up to the mergers / release team.*
The content of the `release-notes/<pull request number>.md` file will serve as the basis for the release notes. If the file does not exist, the title of the pull request will be used instead.
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/11516
Reviewed-by: Mathieu Fenniak <mfenniak@noreply.codeberg.org>
Co-authored-by: Andreas Ahlenstorf <andreas@ahlenstorf.ch>
Co-committed-by: Andreas Ahlenstorf <andreas@ahlenstorf.ch>
2026-03-12 02:14:45 +01:00
|
|
|
|
refactor: replace WithAvailable with WithVisible when fetching runners (#11657)
When fetching runners, the option `WithAvailable` can be enabled to fetch all runners that can be used by a repository, user, or organization, not only those that are owned by the respective repository, user, or organization. In the instance scope, `WithAvailable` has no meaning. You always get _all_ runners. This means it is impossible to only fetch runners that are owned by the instance, but no others.
This PR replaces `WithAvailable` with `WithVisible`. For repositories, users, and organizations, it has the same semantics as `WithAvailable`. For the instance scope, `WithVisible=true` equals today's default behaviour (i.e., return _all_ runners), whereas `WithVisible=false` is new and would only return the runners owned by the instance itself.
The advantage of `WithVisible` is that it has a consistent meaning across all scopes. This also lays the groundwork for the introduction of a `with-visible` (tentative name) flag in the HTTP API.
## Checklist
The [contributor guide](https://forgejo.org/docs/next/contributor/) contains information that will be helpful to first time contributors. There also are a few [conditions for merging Pull Requests in Forgejo repositories](https://codeberg.org/forgejo/governance/src/branch/main/PullRequestsAgreement.md). You are also welcome to join the [Forgejo development chatroom](https://matrix.to/#/#forgejo-development:matrix.org).
### Tests for Go changes
(can be removed for JavaScript changes)
- I added test coverage for Go changes...
- [x] in their respective `*_test.go` for unit tests.
- [x] in the `tests/integration` directory if it involves interactions with a live Forgejo server.
- I ran...
- [x] `make pr-go` before pushing
### Tests for JavaScript changes
(can be removed for Go changes)
- I added test coverage for JavaScript changes...
- [ ] in `web_src/js/*.test.js` if it can be unit tested.
- [ ] in `tests/e2e/*.test.e2e.js` if it requires interactions with a live Forgejo server (see also the [developer guide for JavaScript testing](https://codeberg.org/forgejo/forgejo/src/branch/forgejo/tests/e2e/README.md#end-to-end-tests)).
### Documentation
- [ ] I created a pull request [to the documentation](https://codeberg.org/forgejo/docs) to explain to Forgejo users how to use this change.
- [x] I did not document these changes and I do not expect someone else to do it.
### Release notes
- [ ] This change will be noticed by a Forgejo user or admin (feature, bug fix, performance, etc.). I suggest to include a release note for this change.
- [x] This change is not visible to a Forgejo user or admin (refactor, dependency upgrade, etc.). I think there is no need to add a release note for this change.
*The decision if the pull request will be shown in the release notes is up to the mergers / release team.*
The content of the `release-notes/<pull request number>.md` file will serve as the basis for the release notes. If the file does not exist, the title of the pull request will be used instead.
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/11657
Reviewed-by: Mathieu Fenniak <mfenniak@noreply.codeberg.org>
Co-authored-by: Andreas Ahlenstorf <andreas@ahlenstorf.ch>
Co-committed-by: Andreas Ahlenstorf <andreas@ahlenstorf.ch>
2026-03-13 01:43:32 +01:00
|
|
|
func TestRunner_GetVisibleRunnerByID(t *testing.T) {
|
|
|
|
|
defer unittest.OverrideFixtures("models/actions/TestRunner_GetVisibleRunnerByID")()
|
feat: add form-based runner management (#11516)
Forgejo Runner is deprecating the runner registration token. It is too powerful, requires tooling, and is unnecessary. As a consequence, users need new mechanisms for managing runners in Forgejo. https://codeberg.org/forgejo/forgejo/pulls/10677 added an HTTP API for runner registration. This PR adds the ability to manage runners using Forgejo's web interface.
Runners can be added, modified, and deleted. It is also possible to regenerate a runner's token. When a runner is added or a runner's token is regenerated, setup instructions are displayed. They explain how to alter Forgejo Runner's configuration file or how to launch `forgejo-runner daemon` (yet to be implemented). The existing details page has been overhauled and is now accessible to all users that are allowed to use a particular runner. The details page displays additional information that had to be removed from the list of runners due to space constraints. The task list is filtered. That means it only lists jobs of the respective repository, user, or organization.
The runner registration token has been marked as deprecated.
See https://code.forgejo.org/forgejo/forgejo-actions-feature-requests/issues/88 for context and design considerations.
## Checklist
The [contributor guide](https://forgejo.org/docs/next/contributor/) contains information that will be helpful to first time contributors. There also are a few [conditions for merging Pull Requests in Forgejo repositories](https://codeberg.org/forgejo/governance/src/branch/main/PullRequestsAgreement.md). You are also welcome to join the [Forgejo development chatroom](https://matrix.to/#/#forgejo-development:matrix.org).
### Tests for Go changes
(can be removed for JavaScript changes)
- I added test coverage for Go changes...
- [x] in their respective `*_test.go` for unit tests.
- [x] in the `tests/integration` directory if it involves interactions with a live Forgejo server.
- I ran...
- [x] `make pr-go` before pushing
### Tests for JavaScript changes
(can be removed for Go changes)
- I added test coverage for JavaScript changes...
- [ ] in `web_src/js/*.test.js` if it can be unit tested.
- [x] in `tests/e2e/*.test.e2e.js` if it requires interactions with a live Forgejo server (see also the [developer guide for JavaScript testing](https://codeberg.org/forgejo/forgejo/src/branch/forgejo/tests/e2e/README.md#end-to-end-tests)).
### Documentation
- [ ] I created a pull request [to the documentation](https://codeberg.org/forgejo/docs) to explain to Forgejo users how to use this change.
- [x] I did not document these changes and I do not expect someone else to do it.
### Release notes
- [x] This change will be noticed by a Forgejo user or admin (feature, bug fix, performance, etc.). I suggest to include a release note for this change.
- [ ] This change is not visible to a Forgejo user or admin (refactor, dependency upgrade, etc.). I think there is no need to add a release note for this change.
*The decision if the pull request will be shown in the release notes is up to the mergers / release team.*
The content of the `release-notes/<pull request number>.md` file will serve as the basis for the release notes. If the file does not exist, the title of the pull request will be used instead.
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/11516
Reviewed-by: Mathieu Fenniak <mfenniak@noreply.codeberg.org>
Co-authored-by: Andreas Ahlenstorf <andreas@ahlenstorf.ch>
Co-committed-by: Andreas Ahlenstorf <andreas@ahlenstorf.ch>
2026-03-12 02:14:45 +01:00
|
|
|
require.NoError(t, unittest.PrepareTestDatabase())
|
|
|
|
|
|
|
|
|
|
repository32 := unittest.AssertExistsAndLoadBean(t, &repo.Repository{ID: 32, OwnerID: 3})
|
|
|
|
|
repository1 := unittest.AssertExistsAndLoadBean(t, &repo.Repository{ID: 1, OwnerID: 2})
|
|
|
|
|
|
|
|
|
|
runner1 := unittest.AssertExistsAndLoadBean(t, &ActionRunner{ID: 719931, OwnerID: 3, RepoID: 0}) // Owned by org3
|
|
|
|
|
runner2 := unittest.AssertExistsAndLoadBean(t, &ActionRunner{ID: 719932, OwnerID: 2, RepoID: 0}) // Owned by user2
|
|
|
|
|
runner3 := unittest.AssertExistsAndLoadBean(t, &ActionRunner{ID: 719933, OwnerID: 0, RepoID: 0})
|
|
|
|
|
runner4 := unittest.AssertExistsAndLoadBean(t, &ActionRunner{ID: 719934, OwnerID: 0, RepoID: repository32.ID})
|
|
|
|
|
|
|
|
|
|
testCases := []struct {
|
|
|
|
|
name string
|
|
|
|
|
runner *ActionRunner
|
|
|
|
|
ownerID int64
|
|
|
|
|
repoID int64
|
|
|
|
|
expectedError string
|
|
|
|
|
}{
|
|
|
|
|
{
|
|
|
|
|
name: "Organization runner",
|
|
|
|
|
runner: runner1,
|
|
|
|
|
ownerID: 3,
|
|
|
|
|
repoID: 0,
|
|
|
|
|
expectedError: "",
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "Organization runner visible to admins",
|
|
|
|
|
runner: runner1,
|
|
|
|
|
ownerID: 0,
|
|
|
|
|
repoID: 0,
|
|
|
|
|
expectedError: "",
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "Organization runner invisible to different owner",
|
|
|
|
|
runner: runner1,
|
|
|
|
|
ownerID: 2,
|
|
|
|
|
repoID: 0,
|
|
|
|
|
expectedError: fmt.Sprintf("runner with ID %d: resource does not exist", runner1.ID),
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "Organization runner visible to its repositories",
|
|
|
|
|
runner: runner1,
|
|
|
|
|
ownerID: 0,
|
|
|
|
|
repoID: repository32.ID,
|
|
|
|
|
expectedError: "",
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "Organization runner invisible to repositories owned by somebody else",
|
|
|
|
|
runner: runner1,
|
|
|
|
|
ownerID: 0,
|
|
|
|
|
repoID: repository1.ID,
|
|
|
|
|
expectedError: fmt.Sprintf("runner with ID %d: resource does not exist", runner1.ID),
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "User runner",
|
|
|
|
|
runner: runner2,
|
|
|
|
|
ownerID: 2,
|
|
|
|
|
repoID: 0,
|
|
|
|
|
expectedError: "",
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "User runner invisible to different user",
|
|
|
|
|
runner: runner2,
|
|
|
|
|
ownerID: 1,
|
|
|
|
|
repoID: 0,
|
|
|
|
|
expectedError: fmt.Sprintf("runner with ID %d: resource does not exist", runner2.ID),
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "User runner visible to repository owned by user",
|
|
|
|
|
runner: runner2,
|
|
|
|
|
ownerID: 0,
|
|
|
|
|
repoID: repository1.ID,
|
|
|
|
|
expectedError: "",
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "User runner invisible to repository owned by different user",
|
|
|
|
|
runner: runner2,
|
|
|
|
|
ownerID: 0,
|
|
|
|
|
repoID: repository32.ID,
|
|
|
|
|
expectedError: fmt.Sprintf("runner with ID %d: resource does not exist", runner2.ID),
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "Global runner",
|
|
|
|
|
runner: runner3,
|
|
|
|
|
ownerID: 0,
|
|
|
|
|
repoID: 0,
|
|
|
|
|
expectedError: "",
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "Global runner is visible to any user",
|
|
|
|
|
runner: runner3,
|
|
|
|
|
ownerID: 2,
|
|
|
|
|
repoID: 0,
|
|
|
|
|
expectedError: "",
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "Global runner is visible to any repository",
|
|
|
|
|
runner: runner3,
|
|
|
|
|
ownerID: 0,
|
|
|
|
|
repoID: repository32.ID,
|
|
|
|
|
expectedError: "",
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "Repository runner",
|
|
|
|
|
runner: runner4,
|
|
|
|
|
ownerID: 0,
|
|
|
|
|
repoID: repository32.ID,
|
|
|
|
|
expectedError: "",
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "Repository runner is visible to admins",
|
|
|
|
|
runner: runner4,
|
|
|
|
|
ownerID: 0,
|
|
|
|
|
repoID: 0,
|
|
|
|
|
expectedError: "",
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "Repository runner is invisible to repository owner",
|
|
|
|
|
runner: runner4,
|
|
|
|
|
ownerID: repository32.OwnerID,
|
|
|
|
|
repoID: 0,
|
|
|
|
|
expectedError: fmt.Sprintf("runner with ID %d: resource does not exist", runner4.ID),
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for _, testCase := range testCases {
|
|
|
|
|
t.Run(testCase.name, func(t *testing.T) {
|
refactor: replace WithAvailable with WithVisible when fetching runners (#11657)
When fetching runners, the option `WithAvailable` can be enabled to fetch all runners that can be used by a repository, user, or organization, not only those that are owned by the respective repository, user, or organization. In the instance scope, `WithAvailable` has no meaning. You always get _all_ runners. This means it is impossible to only fetch runners that are owned by the instance, but no others.
This PR replaces `WithAvailable` with `WithVisible`. For repositories, users, and organizations, it has the same semantics as `WithAvailable`. For the instance scope, `WithVisible=true` equals today's default behaviour (i.e., return _all_ runners), whereas `WithVisible=false` is new and would only return the runners owned by the instance itself.
The advantage of `WithVisible` is that it has a consistent meaning across all scopes. This also lays the groundwork for the introduction of a `with-visible` (tentative name) flag in the HTTP API.
## Checklist
The [contributor guide](https://forgejo.org/docs/next/contributor/) contains information that will be helpful to first time contributors. There also are a few [conditions for merging Pull Requests in Forgejo repositories](https://codeberg.org/forgejo/governance/src/branch/main/PullRequestsAgreement.md). You are also welcome to join the [Forgejo development chatroom](https://matrix.to/#/#forgejo-development:matrix.org).
### Tests for Go changes
(can be removed for JavaScript changes)
- I added test coverage for Go changes...
- [x] in their respective `*_test.go` for unit tests.
- [x] in the `tests/integration` directory if it involves interactions with a live Forgejo server.
- I ran...
- [x] `make pr-go` before pushing
### Tests for JavaScript changes
(can be removed for Go changes)
- I added test coverage for JavaScript changes...
- [ ] in `web_src/js/*.test.js` if it can be unit tested.
- [ ] in `tests/e2e/*.test.e2e.js` if it requires interactions with a live Forgejo server (see also the [developer guide for JavaScript testing](https://codeberg.org/forgejo/forgejo/src/branch/forgejo/tests/e2e/README.md#end-to-end-tests)).
### Documentation
- [ ] I created a pull request [to the documentation](https://codeberg.org/forgejo/docs) to explain to Forgejo users how to use this change.
- [x] I did not document these changes and I do not expect someone else to do it.
### Release notes
- [ ] This change will be noticed by a Forgejo user or admin (feature, bug fix, performance, etc.). I suggest to include a release note for this change.
- [x] This change is not visible to a Forgejo user or admin (refactor, dependency upgrade, etc.). I think there is no need to add a release note for this change.
*The decision if the pull request will be shown in the release notes is up to the mergers / release team.*
The content of the `release-notes/<pull request number>.md` file will serve as the basis for the release notes. If the file does not exist, the title of the pull request will be used instead.
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/11657
Reviewed-by: Mathieu Fenniak <mfenniak@noreply.codeberg.org>
Co-authored-by: Andreas Ahlenstorf <andreas@ahlenstorf.ch>
Co-committed-by: Andreas Ahlenstorf <andreas@ahlenstorf.ch>
2026-03-13 01:43:32 +01:00
|
|
|
_, err := GetVisibleRunnerByID(t.Context(), testCase.runner.ID, testCase.ownerID, testCase.repoID)
|
feat: add form-based runner management (#11516)
Forgejo Runner is deprecating the runner registration token. It is too powerful, requires tooling, and is unnecessary. As a consequence, users need new mechanisms for managing runners in Forgejo. https://codeberg.org/forgejo/forgejo/pulls/10677 added an HTTP API for runner registration. This PR adds the ability to manage runners using Forgejo's web interface.
Runners can be added, modified, and deleted. It is also possible to regenerate a runner's token. When a runner is added or a runner's token is regenerated, setup instructions are displayed. They explain how to alter Forgejo Runner's configuration file or how to launch `forgejo-runner daemon` (yet to be implemented). The existing details page has been overhauled and is now accessible to all users that are allowed to use a particular runner. The details page displays additional information that had to be removed from the list of runners due to space constraints. The task list is filtered. That means it only lists jobs of the respective repository, user, or organization.
The runner registration token has been marked as deprecated.
See https://code.forgejo.org/forgejo/forgejo-actions-feature-requests/issues/88 for context and design considerations.
## Checklist
The [contributor guide](https://forgejo.org/docs/next/contributor/) contains information that will be helpful to first time contributors. There also are a few [conditions for merging Pull Requests in Forgejo repositories](https://codeberg.org/forgejo/governance/src/branch/main/PullRequestsAgreement.md). You are also welcome to join the [Forgejo development chatroom](https://matrix.to/#/#forgejo-development:matrix.org).
### Tests for Go changes
(can be removed for JavaScript changes)
- I added test coverage for Go changes...
- [x] in their respective `*_test.go` for unit tests.
- [x] in the `tests/integration` directory if it involves interactions with a live Forgejo server.
- I ran...
- [x] `make pr-go` before pushing
### Tests for JavaScript changes
(can be removed for Go changes)
- I added test coverage for JavaScript changes...
- [ ] in `web_src/js/*.test.js` if it can be unit tested.
- [x] in `tests/e2e/*.test.e2e.js` if it requires interactions with a live Forgejo server (see also the [developer guide for JavaScript testing](https://codeberg.org/forgejo/forgejo/src/branch/forgejo/tests/e2e/README.md#end-to-end-tests)).
### Documentation
- [ ] I created a pull request [to the documentation](https://codeberg.org/forgejo/docs) to explain to Forgejo users how to use this change.
- [x] I did not document these changes and I do not expect someone else to do it.
### Release notes
- [x] This change will be noticed by a Forgejo user or admin (feature, bug fix, performance, etc.). I suggest to include a release note for this change.
- [ ] This change is not visible to a Forgejo user or admin (refactor, dependency upgrade, etc.). I think there is no need to add a release note for this change.
*The decision if the pull request will be shown in the release notes is up to the mergers / release team.*
The content of the `release-notes/<pull request number>.md` file will serve as the basis for the release notes. If the file does not exist, the title of the pull request will be used instead.
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/11516
Reviewed-by: Mathieu Fenniak <mfenniak@noreply.codeberg.org>
Co-authored-by: Andreas Ahlenstorf <andreas@ahlenstorf.ch>
Co-committed-by: Andreas Ahlenstorf <andreas@ahlenstorf.ch>
2026-03-12 02:14:45 +01:00
|
|
|
if testCase.expectedError == "" {
|
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
} else {
|
|
|
|
|
assert.ErrorContains(t, err, testCase.expectedError)
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
}
|
refactor: replace WithAvailable with WithVisible when fetching runners (#11657)
When fetching runners, the option `WithAvailable` can be enabled to fetch all runners that can be used by a repository, user, or organization, not only those that are owned by the respective repository, user, or organization. In the instance scope, `WithAvailable` has no meaning. You always get _all_ runners. This means it is impossible to only fetch runners that are owned by the instance, but no others.
This PR replaces `WithAvailable` with `WithVisible`. For repositories, users, and organizations, it has the same semantics as `WithAvailable`. For the instance scope, `WithVisible=true` equals today's default behaviour (i.e., return _all_ runners), whereas `WithVisible=false` is new and would only return the runners owned by the instance itself.
The advantage of `WithVisible` is that it has a consistent meaning across all scopes. This also lays the groundwork for the introduction of a `with-visible` (tentative name) flag in the HTTP API.
## Checklist
The [contributor guide](https://forgejo.org/docs/next/contributor/) contains information that will be helpful to first time contributors. There also are a few [conditions for merging Pull Requests in Forgejo repositories](https://codeberg.org/forgejo/governance/src/branch/main/PullRequestsAgreement.md). You are also welcome to join the [Forgejo development chatroom](https://matrix.to/#/#forgejo-development:matrix.org).
### Tests for Go changes
(can be removed for JavaScript changes)
- I added test coverage for Go changes...
- [x] in their respective `*_test.go` for unit tests.
- [x] in the `tests/integration` directory if it involves interactions with a live Forgejo server.
- I ran...
- [x] `make pr-go` before pushing
### Tests for JavaScript changes
(can be removed for Go changes)
- I added test coverage for JavaScript changes...
- [ ] in `web_src/js/*.test.js` if it can be unit tested.
- [ ] in `tests/e2e/*.test.e2e.js` if it requires interactions with a live Forgejo server (see also the [developer guide for JavaScript testing](https://codeberg.org/forgejo/forgejo/src/branch/forgejo/tests/e2e/README.md#end-to-end-tests)).
### Documentation
- [ ] I created a pull request [to the documentation](https://codeberg.org/forgejo/docs) to explain to Forgejo users how to use this change.
- [x] I did not document these changes and I do not expect someone else to do it.
### Release notes
- [ ] This change will be noticed by a Forgejo user or admin (feature, bug fix, performance, etc.). I suggest to include a release note for this change.
- [x] This change is not visible to a Forgejo user or admin (refactor, dependency upgrade, etc.). I think there is no need to add a release note for this change.
*The decision if the pull request will be shown in the release notes is up to the mergers / release team.*
The content of the `release-notes/<pull request number>.md` file will serve as the basis for the release notes. If the file does not exist, the title of the pull request will be used instead.
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/11657
Reviewed-by: Mathieu Fenniak <mfenniak@noreply.codeberg.org>
Co-authored-by: Andreas Ahlenstorf <andreas@ahlenstorf.ch>
Co-committed-by: Andreas Ahlenstorf <andreas@ahlenstorf.ch>
2026-03-13 01:43:32 +01:00
|
|
|
|
|
|
|
|
func TestRunner_FindRunnerOptionsToConds(t *testing.T) {
|
|
|
|
|
defer unittest.OverrideFixtures("models/actions/TestRunner_FindRunnerOptionsToConds")()
|
|
|
|
|
require.NoError(t, unittest.PrepareTestDatabase())
|
|
|
|
|
|
|
|
|
|
runner1 := unittest.AssertExistsAndLoadBean(t, &ActionRunner{ID: 719931, OwnerID: 3, RepoID: 0}) // Owned by org3
|
|
|
|
|
runner2 := unittest.AssertExistsAndLoadBean(t, &ActionRunner{ID: 719932, OwnerID: 2, RepoID: 0}) // Owned by user2
|
|
|
|
|
runner3 := unittest.AssertExistsAndLoadBean(t, &ActionRunner{ID: 719933, OwnerID: 0, RepoID: 0})
|
|
|
|
|
runner4 := unittest.AssertExistsAndLoadBean(t, &ActionRunner{ID: 719934, OwnerID: 0, RepoID: 32})
|
|
|
|
|
runner5 := unittest.AssertExistsAndLoadBean(t, &ActionRunner{ID: 719935, OwnerID: 0, RepoID: 36})
|
|
|
|
|
|
|
|
|
|
testCases := []struct {
|
|
|
|
|
name string
|
|
|
|
|
opts FindRunnerOptions
|
|
|
|
|
expectedRunners RunnerList
|
|
|
|
|
unexpectedRunners RunnerList
|
|
|
|
|
}{
|
|
|
|
|
{
|
|
|
|
|
name: "Only runners owned by instance",
|
|
|
|
|
opts: FindRunnerOptions{OwnerID: 0, RepoID: 0, WithVisible: false},
|
|
|
|
|
expectedRunners: RunnerList{runner3},
|
|
|
|
|
unexpectedRunners: RunnerList{runner1, runner2, runner4, runner5},
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "All runners on instance",
|
|
|
|
|
opts: FindRunnerOptions{OwnerID: 0, RepoID: 0, WithVisible: true},
|
|
|
|
|
expectedRunners: RunnerList{runner1, runner2, runner3, runner4, runner5},
|
|
|
|
|
unexpectedRunners: RunnerList{},
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "Only runners owned by organization",
|
|
|
|
|
opts: FindRunnerOptions{OwnerID: 3, RepoID: 0, WithVisible: false},
|
|
|
|
|
expectedRunners: RunnerList{runner1},
|
|
|
|
|
unexpectedRunners: RunnerList{runner2, runner3, runner4, runner5},
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "Runners available to organization",
|
|
|
|
|
opts: FindRunnerOptions{OwnerID: 3, RepoID: 0, WithVisible: true},
|
|
|
|
|
expectedRunners: RunnerList{runner1, runner3},
|
|
|
|
|
unexpectedRunners: RunnerList{runner2, runner4, runner5},
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "Only runners owned by user",
|
|
|
|
|
opts: FindRunnerOptions{OwnerID: 2, RepoID: 0, WithVisible: false},
|
|
|
|
|
expectedRunners: RunnerList{runner2},
|
|
|
|
|
unexpectedRunners: RunnerList{runner1, runner3, runner4, runner5},
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "Runners available to user",
|
|
|
|
|
opts: FindRunnerOptions{OwnerID: 2, RepoID: 0, WithVisible: true},
|
|
|
|
|
expectedRunners: RunnerList{runner2, runner3},
|
|
|
|
|
unexpectedRunners: RunnerList{runner1, runner4, runner5},
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "Only runners owned by organization repository",
|
|
|
|
|
opts: FindRunnerOptions{OwnerID: 0, RepoID: 32, WithVisible: false},
|
|
|
|
|
expectedRunners: RunnerList{runner4},
|
|
|
|
|
unexpectedRunners: RunnerList{runner1, runner2, runner3, runner5},
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "Runners available to organization repository",
|
|
|
|
|
opts: FindRunnerOptions{OwnerID: 0, RepoID: 32, WithVisible: true},
|
|
|
|
|
expectedRunners: RunnerList{runner1, runner3, runner4},
|
|
|
|
|
unexpectedRunners: RunnerList{runner2, runner5},
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "Only runners owned by user repository",
|
|
|
|
|
opts: FindRunnerOptions{OwnerID: 0, RepoID: 36, WithVisible: false},
|
|
|
|
|
expectedRunners: RunnerList{runner5},
|
|
|
|
|
unexpectedRunners: RunnerList{runner1, runner2, runner3, runner4},
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "Runners available to user repository",
|
|
|
|
|
opts: FindRunnerOptions{OwnerID: 0, RepoID: 36, WithVisible: true},
|
|
|
|
|
expectedRunners: RunnerList{runner2, runner3, runner5},
|
|
|
|
|
unexpectedRunners: RunnerList{runner1, runner4},
|
|
|
|
|
},
|
feat: make it possible to search runners by UUID (#11671)
Forgejo Runner [identifies runners by their UUID](https://code.forgejo.org/forgejo/runner/pulls/1380), not by their name. That means users should be able to find a runner in Forgejo not only using its name, but also using its UUID. With this change, when a user enters a (partial) UUID into the search bar on top of the list of runners, all matching runners will be found.
## Checklist
The [contributor guide](https://forgejo.org/docs/next/contributor/) contains information that will be helpful to first time contributors. There also are a few [conditions for merging Pull Requests in Forgejo repositories](https://codeberg.org/forgejo/governance/src/branch/main/PullRequestsAgreement.md). You are also welcome to join the [Forgejo development chatroom](https://matrix.to/#/#forgejo-development:matrix.org).
### Tests for Go changes
(can be removed for JavaScript changes)
- I added test coverage for Go changes...
- [x] in their respective `*_test.go` for unit tests.
- [ ] in the `tests/integration` directory if it involves interactions with a live Forgejo server.
- I ran...
- [x] `make pr-go` before pushing
### Tests for JavaScript changes
(can be removed for Go changes)
- I added test coverage for JavaScript changes...
- [ ] in `web_src/js/*.test.js` if it can be unit tested.
- [ ] in `tests/e2e/*.test.e2e.js` if it requires interactions with a live Forgejo server (see also the [developer guide for JavaScript testing](https://codeberg.org/forgejo/forgejo/src/branch/forgejo/tests/e2e/README.md#end-to-end-tests)).
### Documentation
- [ ] I created a pull request [to the documentation](https://codeberg.org/forgejo/docs) to explain to Forgejo users how to use this change.
- [x] I did not document these changes and I do not expect someone else to do it.
### Release notes
- [x] This change will be noticed by a Forgejo user or admin (feature, bug fix, performance, etc.). I suggest to include a release note for this change.
- [ ] This change is not visible to a Forgejo user or admin (refactor, dependency upgrade, etc.). I think there is no need to add a release note for this change.
*The decision if the pull request will be shown in the release notes is up to the mergers / release team.*
The content of the `release-notes/<pull request number>.md` file will serve as the basis for the release notes. If the file does not exist, the title of the pull request will be used instead.
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/11671
Reviewed-by: Mathieu Fenniak <mfenniak@noreply.codeberg.org>
Co-authored-by: Andreas Ahlenstorf <andreas@ahlenstorf.ch>
Co-committed-by: Andreas Ahlenstorf <andreas@ahlenstorf.ch>
2026-03-14 04:12:00 +01:00
|
|
|
{
|
|
|
|
|
name: "Runners with partially matching name",
|
|
|
|
|
opts: FindRunnerOptions{Filter: "er-3"},
|
|
|
|
|
expectedRunners: RunnerList{runner3},
|
|
|
|
|
unexpectedRunners: RunnerList{runner1, runner2, runner4, runner5},
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "Runners with partially matching UUID",
|
|
|
|
|
opts: FindRunnerOptions{Filter: "21f75233798b"},
|
|
|
|
|
expectedRunners: RunnerList{runner4},
|
|
|
|
|
unexpectedRunners: RunnerList{runner1, runner2, runner3, runner5},
|
|
|
|
|
},
|
refactor: replace WithAvailable with WithVisible when fetching runners (#11657)
When fetching runners, the option `WithAvailable` can be enabled to fetch all runners that can be used by a repository, user, or organization, not only those that are owned by the respective repository, user, or organization. In the instance scope, `WithAvailable` has no meaning. You always get _all_ runners. This means it is impossible to only fetch runners that are owned by the instance, but no others.
This PR replaces `WithAvailable` with `WithVisible`. For repositories, users, and organizations, it has the same semantics as `WithAvailable`. For the instance scope, `WithVisible=true` equals today's default behaviour (i.e., return _all_ runners), whereas `WithVisible=false` is new and would only return the runners owned by the instance itself.
The advantage of `WithVisible` is that it has a consistent meaning across all scopes. This also lays the groundwork for the introduction of a `with-visible` (tentative name) flag in the HTTP API.
## Checklist
The [contributor guide](https://forgejo.org/docs/next/contributor/) contains information that will be helpful to first time contributors. There also are a few [conditions for merging Pull Requests in Forgejo repositories](https://codeberg.org/forgejo/governance/src/branch/main/PullRequestsAgreement.md). You are also welcome to join the [Forgejo development chatroom](https://matrix.to/#/#forgejo-development:matrix.org).
### Tests for Go changes
(can be removed for JavaScript changes)
- I added test coverage for Go changes...
- [x] in their respective `*_test.go` for unit tests.
- [x] in the `tests/integration` directory if it involves interactions with a live Forgejo server.
- I ran...
- [x] `make pr-go` before pushing
### Tests for JavaScript changes
(can be removed for Go changes)
- I added test coverage for JavaScript changes...
- [ ] in `web_src/js/*.test.js` if it can be unit tested.
- [ ] in `tests/e2e/*.test.e2e.js` if it requires interactions with a live Forgejo server (see also the [developer guide for JavaScript testing](https://codeberg.org/forgejo/forgejo/src/branch/forgejo/tests/e2e/README.md#end-to-end-tests)).
### Documentation
- [ ] I created a pull request [to the documentation](https://codeberg.org/forgejo/docs) to explain to Forgejo users how to use this change.
- [x] I did not document these changes and I do not expect someone else to do it.
### Release notes
- [ ] This change will be noticed by a Forgejo user or admin (feature, bug fix, performance, etc.). I suggest to include a release note for this change.
- [x] This change is not visible to a Forgejo user or admin (refactor, dependency upgrade, etc.). I think there is no need to add a release note for this change.
*The decision if the pull request will be shown in the release notes is up to the mergers / release team.*
The content of the `release-notes/<pull request number>.md` file will serve as the basis for the release notes. If the file does not exist, the title of the pull request will be used instead.
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/11657
Reviewed-by: Mathieu Fenniak <mfenniak@noreply.codeberg.org>
Co-authored-by: Andreas Ahlenstorf <andreas@ahlenstorf.ch>
Co-committed-by: Andreas Ahlenstorf <andreas@ahlenstorf.ch>
2026-03-13 01:43:32 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for _, testCase := range testCases {
|
|
|
|
|
t.Run(testCase.name, func(t *testing.T) {
|
|
|
|
|
runners, err := db.Find[ActionRunner](t.Context(), testCase.opts)
|
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
|
|
for _, expectedRunner := range testCase.expectedRunners {
|
|
|
|
|
assert.Contains(t, runners, expectedRunner)
|
|
|
|
|
}
|
|
|
|
|
for _, unexpectedRunner := range testCase.unexpectedRunners {
|
|
|
|
|
assert.NotContains(t, runners, unexpectedRunner)
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
}
|
2026-05-11 16:02:36 +02:00
|
|
|
|
|
|
|
|
func TestDeleteEphemeralRunner(t *testing.T) {
|
|
|
|
|
require.NoError(t, unittest.PrepareTestDatabase())
|
|
|
|
|
|
|
|
|
|
persistentRunnerOne := &ActionRunner{
|
|
|
|
|
ID: 606526,
|
|
|
|
|
UUID: "d53a1222-ae7a-4430-97f8-8fcb6efd04c9",
|
|
|
|
|
Name: "persistent-runner-one",
|
|
|
|
|
OwnerID: 2,
|
|
|
|
|
RepoID: 0,
|
|
|
|
|
Ephemeral: false,
|
|
|
|
|
TokenHash: "J9YDsQL",
|
|
|
|
|
}
|
|
|
|
|
persistentRunnerTwo := &ActionRunner{
|
|
|
|
|
ID: 606527,
|
|
|
|
|
UUID: "3dc23067-b2fd-4daf-b428-dddad80d7f37",
|
|
|
|
|
Name: "persistent-runner-two",
|
|
|
|
|
OwnerID: 2,
|
|
|
|
|
RepoID: 0,
|
|
|
|
|
Ephemeral: false,
|
|
|
|
|
TokenHash: "jvIylZtHsS",
|
|
|
|
|
}
|
|
|
|
|
ephemeralRunnerOne := &ActionRunner{
|
|
|
|
|
ID: 606528,
|
|
|
|
|
UUID: "2d9bc0a1-7019-4ed3-ba67-6415415ac2a9",
|
|
|
|
|
Name: "ephemeral-runner-one",
|
|
|
|
|
OwnerID: 2,
|
|
|
|
|
RepoID: 0,
|
|
|
|
|
Ephemeral: true,
|
|
|
|
|
TokenHash: "t9C8L0kM3W",
|
|
|
|
|
}
|
|
|
|
|
ephemeralRunnerTwo := &ActionRunner{
|
|
|
|
|
ID: 606529,
|
|
|
|
|
UUID: "da7a03f8-ab39-4c54-9ec9-2bd312fe3be1",
|
|
|
|
|
Name: "ephemeral-runner-two",
|
|
|
|
|
OwnerID: 2,
|
|
|
|
|
RepoID: 0,
|
|
|
|
|
Ephemeral: true,
|
|
|
|
|
TokenHash: "g9oTOFM",
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
require.NoError(t, CreateRunner(t.Context(), persistentRunnerOne))
|
|
|
|
|
require.NoError(t, CreateRunner(t.Context(), persistentRunnerTwo))
|
|
|
|
|
require.NoError(t, CreateRunner(t.Context(), ephemeralRunnerOne))
|
|
|
|
|
require.NoError(t, CreateRunner(t.Context(), ephemeralRunnerTwo))
|
|
|
|
|
|
|
|
|
|
unittest.AssertExistsAndLoadBean(t, &ActionRunner{ID: persistentRunnerOne.ID})
|
|
|
|
|
unittest.AssertExistsAndLoadBean(t, &ActionRunner{ID: persistentRunnerTwo.ID})
|
|
|
|
|
unittest.AssertExistsAndLoadBean(t, &ActionRunner{ID: ephemeralRunnerOne.ID})
|
|
|
|
|
unittest.AssertExistsAndLoadBean(t, &ActionRunner{ID: ephemeralRunnerTwo.ID})
|
|
|
|
|
|
|
|
|
|
require.NoError(t, DeleteEphemeralRunner(t.Context(), persistentRunnerOne.ID))
|
|
|
|
|
require.NoError(t, DeleteEphemeralRunner(t.Context(), ephemeralRunnerOne.ID))
|
|
|
|
|
|
|
|
|
|
unittest.AssertExistsAndLoadBean(t, &ActionRunner{ID: persistentRunnerOne.ID})
|
|
|
|
|
unittest.AssertExistsAndLoadBean(t, &ActionRunner{ID: persistentRunnerTwo.ID})
|
|
|
|
|
unittest.AssertNotExistsBean(t, &ActionRunner{ID: ephemeralRunnerOne.ID})
|
|
|
|
|
unittest.AssertExistsAndLoadBean(t, &ActionRunner{ID: ephemeralRunnerTwo.ID})
|
|
|
|
|
}
|