Skip to content

Commit 6d3bb62

Browse files
committed
fix
1 parent 35c86af commit 6d3bb62

File tree

4 files changed

+137
-12
lines changed

4 files changed

+137
-12
lines changed

models/actions/runner_token.go

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"code.gitea.io/gitea/models/db"
1111
repo_model "code.gitea.io/gitea/models/repo"
1212
user_model "code.gitea.io/gitea/models/user"
13+
"code.gitea.io/gitea/modules/base"
1314
"code.gitea.io/gitea/modules/timeutil"
1415
"code.gitea.io/gitea/modules/util"
1516
)
@@ -51,7 +52,7 @@ func GetRunnerToken(ctx context.Context, token string) (*ActionRunnerToken, erro
5152
if err != nil {
5253
return nil, err
5354
} else if !has {
54-
return nil, fmt.Errorf("runner token %q: %w", token, util.ErrNotExist)
55+
return nil, fmt.Errorf(`runner token "%s...": %w`, base.TruncateString(token, 3), util.ErrNotExist)
5556
}
5657
return &runnerToken, nil
5758
}
@@ -68,19 +69,15 @@ func UpdateRunnerToken(ctx context.Context, r *ActionRunnerToken, cols ...string
6869
return err
6970
}
7071

71-
// NewRunnerToken creates a new active runner token and invalidate all old tokens
72+
// NewRunnerTokenWithValue creates a new active runner token and invalidate all old tokens
7273
// ownerID will be ignored and treated as 0 if repoID is non-zero.
73-
func NewRunnerToken(ctx context.Context, ownerID, repoID int64) (*ActionRunnerToken, error) {
74+
func NewRunnerTokenWithValue(ctx context.Context, ownerID, repoID int64, token string) (*ActionRunnerToken, error) {
7475
if ownerID != 0 && repoID != 0 {
7576
// It's trying to create a runner token that belongs to a repository, but OwnerID has been set accidentally.
7677
// Remove OwnerID to avoid confusion; it's not worth returning an error here.
7778
ownerID = 0
7879
}
7980

80-
token, err := util.CryptoRandomString(40)
81-
if err != nil {
82-
return nil, err
83-
}
8481
runnerToken := &ActionRunnerToken{
8582
OwnerID: ownerID,
8683
RepoID: repoID,
@@ -95,11 +92,19 @@ func NewRunnerToken(ctx context.Context, ownerID, repoID int64) (*ActionRunnerTo
9592
return err
9693
}
9794

98-
_, err = db.GetEngine(ctx).Insert(runnerToken)
95+
_, err := db.GetEngine(ctx).Insert(runnerToken)
9996
return err
10097
})
10198
}
10299

100+
func NewRunnerToken(ctx context.Context, ownerID, repoID int64) (*ActionRunnerToken, error) {
101+
token, err := util.CryptoRandomString(40)
102+
if err != nil {
103+
return nil, err
104+
}
105+
return NewRunnerTokenWithValue(ctx, ownerID, repoID, token)
106+
}
107+
103108
// GetLatestRunnerToken returns the latest runner token
104109
func GetLatestRunnerToken(ctx context.Context, ownerID, repoID int64) (*ActionRunnerToken, error) {
105110
if ownerID != 0 && repoID != 0 {

routers/init.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ func InitWebInstalled(ctx context.Context) {
171171
auth.Init()
172172
mustInit(svg.Init)
173173

174-
actions_service.Init()
174+
mustInitCtx(ctx, actions_service.Init)
175175

176176
mustInit(repo_service.InitLicenseClassifier)
177177

services/actions/init.go

Lines changed: 46 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,23 +4,66 @@
44
package actions
55

66
import (
7+
"context"
8+
"errors"
9+
"fmt"
10+
"os"
11+
"strings"
12+
13+
actions_model "code.gitea.io/gitea/models/actions"
714
"code.gitea.io/gitea/modules/graceful"
815
"code.gitea.io/gitea/modules/log"
916
"code.gitea.io/gitea/modules/queue"
1017
"code.gitea.io/gitea/modules/setting"
18+
"code.gitea.io/gitea/modules/util"
1119
notify_service "code.gitea.io/gitea/services/notify"
1220
)
1321

14-
func Init() {
22+
func initGlobalRunnerToken(ctx context.Context) error {
23+
// use the same env name as the runner, for consistency
24+
token := os.Getenv("GITEA_RUNNER_REGISTRATION_TOKEN")
25+
tokenFile := os.Getenv("GITEA_RUNNER_REGISTRATION_TOKEN_FILE")
26+
if token != "" && tokenFile != "" {
27+
return errors.New("both GITEA_RUNNER_REGISTRATION_TOKEN and GITEA_RUNNER_REGISTRATION_TOKEN_FILE are set, only one can be used")
28+
}
29+
if tokenFile != "" {
30+
file, err := os.ReadFile(tokenFile)
31+
if err != nil {
32+
return fmt.Errorf("unable to read GITEA_RUNNER_REGISTRATION_TOKEN_FILE: %w", err)
33+
}
34+
token = strings.TrimSpace(string(file))
35+
}
36+
if token == "" {
37+
return nil
38+
}
39+
40+
if len(token) < 32 {
41+
return errors.New("GITEA_RUNNER_REGISTRATION_TOKEN must be at least 32 random characters")
42+
}
43+
44+
existing, err := actions_model.GetRunnerToken(ctx, token)
45+
if err != nil && !errors.Is(err, util.ErrNotExist) {
46+
return fmt.Errorf("unable to check existing token: %w", err)
47+
}
48+
if existing != nil && !existing.IsActive {
49+
log.Warn("The token defined by GITEA_RUNNER_REGISTRATION_TOKEN is already invalidated, please use the latest one from web UI")
50+
return nil
51+
}
52+
_, err = actions_model.NewRunnerTokenWithValue(ctx, 0, 0, token)
53+
return err
54+
}
55+
56+
func Init(ctx context.Context) error {
1557
if !setting.Actions.Enabled {
16-
return
58+
return nil
1759
}
1860

1961
jobEmitterQueue = queue.CreateUniqueQueue(graceful.GetManager().ShutdownContext(), "actions_ready_job", jobEmitterQueueHandler)
2062
if jobEmitterQueue == nil {
21-
log.Fatal("Unable to create actions_ready_job queue")
63+
return errors.New("unable to create actions_ready_job queue")
2264
}
2365
go graceful.GetManager().RunWithCancel(jobEmitterQueue)
2466

2567
notify_service.RegisterNotifier(NewNotifier())
68+
return initGlobalRunnerToken(ctx)
2669
}

services/actions/init_test.go

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
// Copyright 2024 The Gitea Authors. All rights reserved.
2+
// SPDX-License-Identifier: MIT
3+
4+
package actions
5+
6+
import (
7+
"os"
8+
"testing"
9+
10+
actions_model "code.gitea.io/gitea/models/actions"
11+
"code.gitea.io/gitea/models/db"
12+
"code.gitea.io/gitea/models/unittest"
13+
"code.gitea.io/gitea/modules/util"
14+
15+
"github.com/stretchr/testify/assert"
16+
"github.com/stretchr/testify/require"
17+
)
18+
19+
func TestMain(m *testing.M) {
20+
unittest.MainTest(m, &unittest.TestOptions{
21+
FixtureFiles: []string{"action_runner_token.yml"},
22+
})
23+
os.Exit(m.Run())
24+
}
25+
26+
func TestInitToken(t *testing.T) {
27+
assert.NoError(t, unittest.PrepareTestDatabase())
28+
29+
t.Run("NoToken", func(t *testing.T) {
30+
t.Setenv("GITEA_RUNNER_REGISTRATION_TOKEN", "")
31+
t.Setenv("GITEA_RUNNER_REGISTRATION_TOKEN_FILE", "")
32+
err := initGlobalRunnerToken(db.DefaultContext)
33+
require.NoError(t, err)
34+
empty, err := db.IsTableNotEmpty(&actions_model.ActionRunnerToken{})
35+
require.NoError(t, err)
36+
assert.True(t, empty)
37+
})
38+
39+
t.Run("EnvToken", func(t *testing.T) {
40+
tokenValue, _ := util.CryptoRandomString(32)
41+
t.Setenv("GITEA_RUNNER_REGISTRATION_TOKEN", tokenValue)
42+
t.Setenv("GITEA_RUNNER_REGISTRATION_TOKEN_FILE", "")
43+
err := initGlobalRunnerToken(db.DefaultContext)
44+
require.NoError(t, err)
45+
token := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionRunnerToken{Token: tokenValue})
46+
assert.True(t, token.IsActive)
47+
})
48+
49+
t.Run("EnvFileToken", func(t *testing.T) {
50+
tokenValue, _ := util.CryptoRandomString(32)
51+
f := t.TempDir() + "/token"
52+
_ = os.WriteFile(f, []byte(tokenValue), 0o644)
53+
t.Setenv("GITEA_RUNNER_REGISTRATION_TOKEN", "")
54+
t.Setenv("GITEA_RUNNER_REGISTRATION_TOKEN_FILE", f)
55+
err := initGlobalRunnerToken(db.DefaultContext)
56+
require.NoError(t, err)
57+
token := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionRunnerToken{Token: tokenValue})
58+
assert.True(t, token.IsActive)
59+
60+
_, err = actions_model.NewRunnerToken(db.DefaultContext, 0, 0)
61+
require.NoError(t, err)
62+
token = unittest.AssertExistsAndLoadBean(t, &actions_model.ActionRunnerToken{Token: tokenValue})
63+
assert.False(t, token.IsActive)
64+
})
65+
66+
t.Run("InvalidToken", func(t *testing.T) {
67+
t.Setenv("GITEA_RUNNER_REGISTRATION_TOKEN", "abc")
68+
err := initGlobalRunnerToken(db.DefaultContext)
69+
assert.ErrorContains(t, err, "must be at least")
70+
})
71+
72+
t.Run("InactiveToken", func(t *testing.T) {
73+
t.Setenv("GITEA_RUNNER_REGISTRATION_TOKEN", "abc")
74+
err := initGlobalRunnerToken(db.DefaultContext)
75+
assert.ErrorContains(t, err, "must be at least")
76+
})
77+
}

0 commit comments

Comments
 (0)