mirror of
				https://gitee.com/gitea/gitea
				synced 2025-11-04 08:30:25 +08:00 
			
		
		
		
	Support changing labels of Actions runner without re-registration (#24806)
close #24540 related: - Protocol: https://gitea.com/gitea/actions-proto-def/pulls/9 - Runner side: https://gitea.com/gitea/act_runner/pulls/201 changes: - Add column of `labels` to table `action_runner`, and combine the value of `agent_labels` and `custom_labels` column to `labels` column. - Store `labels` when registering `act_runner`. - Update `labels` when `act_runner` starting and calling `Declare`. - Users cannot modify the `custom labels` in edit page any more. other changes: - Store `version` when registering `act_runner`. - If runner is latest version, parse version from `Declare`. But older version runner still parse version from request header.
This commit is contained in:
		@@ -21,11 +21,10 @@ import (
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	uuidHeaderKey    = "x-runner-uuid"
 | 
			
		||||
	tokenHeaderKey   = "x-runner-token"
 | 
			
		||||
	uuidHeaderKey  = "x-runner-uuid"
 | 
			
		||||
	tokenHeaderKey = "x-runner-token"
 | 
			
		||||
	// Deprecated: will be removed after Gitea 1.20 released.
 | 
			
		||||
	versionHeaderKey = "x-runner-version"
 | 
			
		||||
 | 
			
		||||
	versionUnknown = "Unknown"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var withRunner = connect.WithInterceptors(connect.UnaryInterceptorFunc(func(unaryFunc connect.UnaryFunc) connect.UnaryFunc {
 | 
			
		||||
@@ -36,11 +35,9 @@ var withRunner = connect.WithInterceptors(connect.UnaryInterceptorFunc(func(unar
 | 
			
		||||
		}
 | 
			
		||||
		uuid := request.Header().Get(uuidHeaderKey)
 | 
			
		||||
		token := request.Header().Get(tokenHeaderKey)
 | 
			
		||||
		// TODO: version will be removed from request header after Gitea 1.20 released.
 | 
			
		||||
		// And Gitea will not try to read version from reuqest header
 | 
			
		||||
		version := request.Header().Get(versionHeaderKey)
 | 
			
		||||
		if util.IsEmptyString(version) {
 | 
			
		||||
			version = versionUnknown
 | 
			
		||||
		}
 | 
			
		||||
		version, _ = util.SplitStringAtByteN(version, 64)
 | 
			
		||||
 | 
			
		||||
		runner, err := actions_model.GetRunnerByUUID(ctx, uuid)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
@@ -54,7 +51,11 @@ var withRunner = connect.WithInterceptors(connect.UnaryInterceptorFunc(func(unar
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		cols := []string{"last_online"}
 | 
			
		||||
		if runner.Version != version {
 | 
			
		||||
 | 
			
		||||
		// TODO: version will be removed from request header after Gitea 1.20 released.
 | 
			
		||||
		// And Gitea will not try to read version from reuqest header
 | 
			
		||||
		version, _ = util.SplitStringAtByteN(version, 64)
 | 
			
		||||
		if !util.IsEmptyString(version) && runner.Version != version {
 | 
			
		||||
			runner.Version = version
 | 
			
		||||
			cols = append(cols, "version")
 | 
			
		||||
		}
 | 
			
		||||
 
 | 
			
		||||
@@ -54,15 +54,23 @@ func (s *Service) Register(
 | 
			
		||||
		return nil, errors.New("runner token has already been activated")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	labels := req.Msg.Labels
 | 
			
		||||
	// TODO: agent_labels should be removed from pb after Gitea 1.20 released.
 | 
			
		||||
	// Old version runner's agent_labels slice is not empty and labels slice is empty.
 | 
			
		||||
	// And due to compatibility with older versions, it is temporarily marked as Deprecated in pb, so use `//nolint` here.
 | 
			
		||||
	if len(req.Msg.AgentLabels) > 0 && len(req.Msg.Labels) == 0 { //nolint:staticcheck
 | 
			
		||||
		labels = req.Msg.AgentLabels //nolint:staticcheck
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// create new runner
 | 
			
		||||
	name, _ := util.SplitStringAtByteN(req.Msg.Name, 255)
 | 
			
		||||
	runner := &actions_model.ActionRunner{
 | 
			
		||||
		UUID:         gouuid.New().String(),
 | 
			
		||||
		Name:         name,
 | 
			
		||||
		OwnerID:      runnerToken.OwnerID,
 | 
			
		||||
		RepoID:       runnerToken.RepoID,
 | 
			
		||||
		AgentLabels:  req.Msg.AgentLabels,
 | 
			
		||||
		CustomLabels: req.Msg.CustomLabels,
 | 
			
		||||
		UUID:        gouuid.New().String(),
 | 
			
		||||
		Name:        name,
 | 
			
		||||
		OwnerID:     runnerToken.OwnerID,
 | 
			
		||||
		RepoID:      runnerToken.RepoID,
 | 
			
		||||
		Version:     req.Msg.Version,
 | 
			
		||||
		AgentLabels: labels,
 | 
			
		||||
	}
 | 
			
		||||
	if err := runner.GenerateToken(); err != nil {
 | 
			
		||||
		return nil, errors.New("can't generate token")
 | 
			
		||||
@@ -81,18 +89,41 @@ func (s *Service) Register(
 | 
			
		||||
 | 
			
		||||
	res := connect.NewResponse(&runnerv1.RegisterResponse{
 | 
			
		||||
		Runner: &runnerv1.Runner{
 | 
			
		||||
			Id:           runner.ID,
 | 
			
		||||
			Uuid:         runner.UUID,
 | 
			
		||||
			Token:        runner.Token,
 | 
			
		||||
			Name:         runner.Name,
 | 
			
		||||
			AgentLabels:  runner.AgentLabels,
 | 
			
		||||
			CustomLabels: runner.CustomLabels,
 | 
			
		||||
			Id:      runner.ID,
 | 
			
		||||
			Uuid:    runner.UUID,
 | 
			
		||||
			Token:   runner.Token,
 | 
			
		||||
			Name:    runner.Name,
 | 
			
		||||
			Version: runner.Version,
 | 
			
		||||
			Labels:  runner.AgentLabels,
 | 
			
		||||
		},
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	return res, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *Service) Declare(
 | 
			
		||||
	ctx context.Context,
 | 
			
		||||
	req *connect.Request[runnerv1.DeclareRequest],
 | 
			
		||||
) (*connect.Response[runnerv1.DeclareResponse], error) {
 | 
			
		||||
	runner := GetRunner(ctx)
 | 
			
		||||
	runner.AgentLabels = req.Msg.Labels
 | 
			
		||||
	runner.Version = req.Msg.Version
 | 
			
		||||
	if err := actions_model.UpdateRunner(ctx, runner, "agent_labels", "version"); err != nil {
 | 
			
		||||
		return nil, status.Errorf(codes.Internal, "update runner: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return connect.NewResponse(&runnerv1.DeclareResponse{
 | 
			
		||||
		Runner: &runnerv1.Runner{
 | 
			
		||||
			Id:      runner.ID,
 | 
			
		||||
			Uuid:    runner.UUID,
 | 
			
		||||
			Token:   runner.Token,
 | 
			
		||||
			Name:    runner.Name,
 | 
			
		||||
			Version: runner.Version,
 | 
			
		||||
			Labels:  runner.AgentLabels,
 | 
			
		||||
		},
 | 
			
		||||
	}), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// FetchTask assigns a task to the runner
 | 
			
		||||
func (s *Service) FetchTask(
 | 
			
		||||
	ctx context.Context,
 | 
			
		||||
 
 | 
			
		||||
@@ -84,7 +84,6 @@ func List(ctx *context.Context) {
 | 
			
		||||
		allRunnerLabels := make(container.Set[string])
 | 
			
		||||
		for _, r := range runners {
 | 
			
		||||
			allRunnerLabels.AddMultiple(r.AgentLabels...)
 | 
			
		||||
			allRunnerLabels.AddMultiple(r.CustomLabels...)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		workflows = make([]Workflow, 0, len(entries))
 | 
			
		||||
 
 | 
			
		||||
@@ -6,7 +6,6 @@ package actions
 | 
			
		||||
import (
 | 
			
		||||
	"errors"
 | 
			
		||||
	"net/http"
 | 
			
		||||
	"strings"
 | 
			
		||||
 | 
			
		||||
	actions_model "code.gitea.io/gitea/models/actions"
 | 
			
		||||
	"code.gitea.io/gitea/models/db"
 | 
			
		||||
@@ -126,9 +125,8 @@ func RunnerDetailsEditPost(ctx *context.Context, runnerID, ownerID, repoID int64
 | 
			
		||||
 | 
			
		||||
	form := web.GetForm(ctx).(*forms.EditRunnerForm)
 | 
			
		||||
	runner.Description = form.Description
 | 
			
		||||
	runner.CustomLabels = splitLabels(form.CustomLabels)
 | 
			
		||||
 | 
			
		||||
	err = actions_model.UpdateRunner(ctx, runner, "description", "custom_labels")
 | 
			
		||||
	err = actions_model.UpdateRunner(ctx, runner, "description")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		log.Warn("RunnerDetailsEditPost.UpdateRunner failed: %v, url: %s", err, ctx.Req.URL)
 | 
			
		||||
		ctx.Flash.Warning(ctx.Tr("actions.runners.update_runner_failed"))
 | 
			
		||||
@@ -176,11 +174,3 @@ func RunnerDeletePost(ctx *context.Context, runnerID int64,
 | 
			
		||||
		"redirect": successRedirectTo,
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func splitLabels(s string) []string {
 | 
			
		||||
	labels := strings.Split(s, ",")
 | 
			
		||||
	for i, v := range labels {
 | 
			
		||||
		labels[i] = strings.TrimSpace(v)
 | 
			
		||||
	}
 | 
			
		||||
	return labels
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user