mirror of
https://github.com/go-gitea/gitea.git
synced 2025-08-19 23:24:14 +09:00
168 lines
4.3 KiB
Go
168 lines
4.3 KiB
Go
// Copyright 2022 The Gitea Authors. All rights reserved.
|
|
// Use of this source code is governed by a MIT-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
package runner
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"net/url"
|
|
"strings"
|
|
|
|
"code.gitea.io/gitea/core"
|
|
bots_model "code.gitea.io/gitea/models/bots"
|
|
"code.gitea.io/gitea/models/repo"
|
|
"code.gitea.io/gitea/models/user"
|
|
"code.gitea.io/gitea/modules/log"
|
|
runnerv1 "gitea.com/gitea/proto-go/runner/v1"
|
|
"gitea.com/gitea/proto-go/runner/v1/runnerv1connect"
|
|
|
|
"github.com/bufbuild/connect-go"
|
|
gouuid "github.com/google/uuid"
|
|
)
|
|
|
|
var _ runnerv1connect.RunnerServiceClient = (*Service)(nil)
|
|
|
|
type Service struct {
|
|
Scheduler core.Scheduler
|
|
|
|
runnerv1connect.UnimplementedRunnerServiceHandler
|
|
}
|
|
|
|
// Register for new runner.
|
|
func (s *Service) Register(
|
|
ctx context.Context,
|
|
req *connect.Request[runnerv1.RegisterRequest],
|
|
) (*connect.Response[runnerv1.RegisterResponse], error) {
|
|
if req.Msg.Token == "" || req.Msg.Name == "" || req.Msg.Url == "" {
|
|
return nil, errors.New("missing runner token, name or URL")
|
|
}
|
|
|
|
runnerToken, err := bots_model.GetRunnerToken(req.Msg.Token)
|
|
if err != nil {
|
|
return nil, errors.New("runner token not found")
|
|
}
|
|
|
|
if runnerToken.IsActive {
|
|
return nil, errors.New("runner token has already activated")
|
|
}
|
|
|
|
// valiate user data
|
|
u, err := url.Parse(req.Msg.Url)
|
|
if err != nil {
|
|
return nil, errors.New("can't parse url: " + req.Msg.Url)
|
|
}
|
|
|
|
urls := strings.Split(u.Path, "/")
|
|
if runnerToken.OwnerID != 0 {
|
|
if len(urls) < 2 {
|
|
return nil, errors.New("can't parse owner name")
|
|
}
|
|
owner, err := user.GetUserByID(runnerToken.OwnerID)
|
|
if err != nil {
|
|
return nil, errors.New("can't get owner name")
|
|
}
|
|
if owner.LowerName != strings.ToLower(urls[1]) {
|
|
return nil, errors.New("wrong owner name")
|
|
}
|
|
}
|
|
|
|
if runnerToken.RepoID != 0 {
|
|
if len(urls) < 3 {
|
|
return nil, errors.New("can't parse repo name")
|
|
}
|
|
|
|
r, err := repo.GetRepositoryByIDCtx(ctx, runnerToken.RepoID)
|
|
if err != nil {
|
|
return nil, errors.New("can't get repo name")
|
|
}
|
|
|
|
if r.LowerName != strings.ToLower(urls[2]) {
|
|
return nil, errors.New("wrong repo name")
|
|
}
|
|
}
|
|
|
|
// create new runner
|
|
runner := &bots_model.Runner{
|
|
UUID: gouuid.New().String(),
|
|
Name: req.Msg.Name,
|
|
OwnerID: runnerToken.OwnerID,
|
|
RepoID: runnerToken.RepoID,
|
|
Token: req.Msg.Token,
|
|
Status: core.StatusOffline,
|
|
AgentLabels: req.Msg.AgentLabels,
|
|
CustomLabels: req.Msg.CustomLabels,
|
|
}
|
|
|
|
// create new runner
|
|
if err := bots_model.NewRunner(ctx, runner); err != nil {
|
|
return nil, errors.New("can't create new runner")
|
|
}
|
|
|
|
// update token status
|
|
runnerToken.IsActive = true
|
|
if err := bots_model.UpdateRunnerToken(ctx, runnerToken, "is_active"); err != nil {
|
|
return nil, errors.New("can't update runner token status")
|
|
}
|
|
|
|
res := connect.NewResponse(&runnerv1.RegisterResponse{
|
|
Runner: &runnerv1.Runner{
|
|
Uuid: runner.UUID,
|
|
Token: runner.Token,
|
|
Name: runner.Name,
|
|
AgentLabels: runner.AgentLabels,
|
|
CustomLabels: runner.CustomLabels,
|
|
},
|
|
})
|
|
|
|
return res, nil
|
|
}
|
|
|
|
// Request requests the next available build stage for execution.
|
|
func (s *Service) FetchTask(
|
|
ctx context.Context,
|
|
req *connect.Request[runnerv1.FetchTaskRequest],
|
|
) (*connect.Response[runnerv1.FetchTaskResponse], error) {
|
|
log.Debug("manager: request queue item")
|
|
|
|
task, err := s.Scheduler.Request(ctx, core.Filter{
|
|
OS: req.Msg.Os,
|
|
Arch: req.Msg.Arch,
|
|
})
|
|
if err != nil && ctx.Err() != nil {
|
|
log.Debug("manager: context canceled")
|
|
return nil, err
|
|
}
|
|
if err != nil {
|
|
log.Warn("manager: request queue item error")
|
|
return nil, err
|
|
}
|
|
|
|
// TODO: update task and check data lock
|
|
task.Machine = req.Msg.Os
|
|
|
|
res := connect.NewResponse(&runnerv1.FetchTaskResponse{
|
|
Task: task,
|
|
})
|
|
return res, nil
|
|
}
|
|
|
|
// UpdateTask updates the task status.
|
|
func (s *Service) UpdateTask(
|
|
ctx context.Context,
|
|
req *connect.Request[runnerv1.UpdateTaskRequest],
|
|
) (*connect.Response[runnerv1.UpdateTaskResponse], error) {
|
|
res := connect.NewResponse(&runnerv1.UpdateTaskResponse{})
|
|
return res, nil
|
|
}
|
|
|
|
// UpdateLog uploads log of the task.
|
|
func (s *Service) UpdateLog(
|
|
ctx context.Context,
|
|
req *connect.Request[runnerv1.UpdateLogRequest],
|
|
) (*connect.Response[runnerv1.UpdateLogResponse], error) {
|
|
res := connect.NewResponse(&runnerv1.UpdateLogResponse{})
|
|
return res, nil
|
|
}
|