mirror of
https://github.com/go-gitea/gitea.git
synced 2026-08-10 05:24:18 +09:00
Pairs with https://gitea.com/gitea/runner/pulls/1143. Gitea depends on `gitea.com/gitea/runner` for exactly two packages: `act/model` and `act/exprparser`, the workflow model and the expression evaluator it needs to parse workflows and to build the task payload the runner consumes. Pulling the whole runner module in for that is heavy and puts shared code in the repository of one of the two consumers. Both packages now live in `gitea.dev/actionslib` (`pkg/model`, `pkg/exprparser`), the module Gitea and the runner already share for the runner API, so the dependency on the runner repository is dropped here. ### Changes - `gitea.com/gitea/runner/act/model` -> `gitea.dev/actionslib/pkg/model`, `.../act/exprparser` -> `gitea.dev/actionslib/pkg/exprparser` (22 files, import paths only). - `routers/api/actions/runner/interceptor.go` takes the `x-runner-uuid` / `x-runner-token` names from `gitea.dev/actionslib/pkg/protocol` instead of repeating the literals the runner also has. - `go.mod`: `gitea.com/gitea/runner` removed. --------- Signed-off-by: Lunny Xiao <xiaolunwen@gmail.com> Co-authored-by: silverwind <me@silverwind.io> Co-authored-by: Zettat123 <zettat123@gmail.com>
95 lines
2.8 KiB
Go
95 lines
2.8 KiB
Go
// Copyright 2022 The Gitea Authors. All rights reserved.
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
package runner
|
|
|
|
import (
|
|
"context"
|
|
"crypto/subtle"
|
|
"errors"
|
|
"strings"
|
|
"time"
|
|
|
|
"gitea.dev/actionslib/pkg/protocol"
|
|
actions_model "gitea.dev/models/actions"
|
|
auth_model "gitea.dev/models/auth"
|
|
"gitea.dev/modules/log"
|
|
"gitea.dev/modules/timeutil"
|
|
"gitea.dev/modules/util"
|
|
|
|
"connectrpc.com/connect"
|
|
"google.golang.org/grpc/codes"
|
|
"google.golang.org/grpc/status"
|
|
)
|
|
|
|
const (
|
|
uuidHeaderKey = protocol.UUIDHeader
|
|
tokenHeaderKey = protocol.TokenHeader
|
|
)
|
|
|
|
var withRunner = connect.WithInterceptors(connect.UnaryInterceptorFunc(func(unaryFunc connect.UnaryFunc) connect.UnaryFunc {
|
|
return func(ctx context.Context, request connect.AnyRequest) (connect.AnyResponse, error) {
|
|
methodName := getMethodName(request)
|
|
if methodName == "Register" {
|
|
return unaryFunc(ctx, request)
|
|
}
|
|
uuid := request.Header().Get(uuidHeaderKey)
|
|
token := request.Header().Get(tokenHeaderKey)
|
|
|
|
runner, err := actions_model.GetRunnerByUUID(ctx, uuid)
|
|
if err != nil {
|
|
if errors.Is(err, util.ErrNotExist) {
|
|
return nil, status.Error(codes.Unauthenticated, "unregistered runner")
|
|
}
|
|
return nil, status.Error(codes.Internal, err.Error())
|
|
}
|
|
if subtle.ConstantTimeCompare([]byte(runner.TokenHash), []byte(auth_model.HashToken(token, runner.TokenSalt))) != 1 {
|
|
return nil, status.Error(codes.Unauthenticated, "unregistered runner")
|
|
}
|
|
|
|
now := time.Now()
|
|
cols := make([]string, 0, 2)
|
|
// Debounce last_active too: while a runner streams logs, UpdateLog fires
|
|
// many times per second and writing on each is a major source of DB load.
|
|
// Persist only when stale enough to affect the active/idle status.
|
|
if (methodName == "UpdateTask" || methodName == "UpdateLog") &&
|
|
actions_model.ShouldPersistLastActive(runner.LastActive, now) {
|
|
runner.LastActive = timeutil.TimeStamp(now.Unix())
|
|
cols = append(cols, "last_active")
|
|
}
|
|
// Debounce last_online: writing on every poll is a major source of DB load
|
|
// with many runners. Persist only when stale enough to affect offline status.
|
|
if actions_model.ShouldPersistLastOnline(runner.LastOnline, now) {
|
|
runner.LastOnline = timeutil.TimeStamp(now.Unix())
|
|
cols = append(cols, "last_online")
|
|
}
|
|
if len(cols) > 0 {
|
|
if err := actions_model.UpdateRunner(ctx, runner, cols...); err != nil {
|
|
log.Error("can't update runner status: %v", err)
|
|
}
|
|
}
|
|
|
|
ctx = context.WithValue(ctx, runnerCtxKey{}, runner)
|
|
return unaryFunc(ctx, request)
|
|
}
|
|
}))
|
|
|
|
func getMethodName(req connect.AnyRequest) string {
|
|
splits := strings.Split(req.Spec().Procedure, "/")
|
|
if len(splits) > 0 {
|
|
return splits[len(splits)-1]
|
|
}
|
|
return ""
|
|
}
|
|
|
|
type runnerCtxKey struct{}
|
|
|
|
func GetRunner(ctx context.Context) *actions_model.ActionRunner {
|
|
if v := ctx.Value(runnerCtxKey{}); v != nil {
|
|
if r, ok := v.(*actions_model.ActionRunner); ok {
|
|
return r
|
|
}
|
|
}
|
|
return nil
|
|
}
|