mirror of
				https://github.com/go-gitea/gitea
				synced 2025-10-31 19:38:23 +00:00 
			
		
		
		
	add CLI command to register runner tokens (#23762)
This is a CLI command to generate new tokens for the runners to register with Fix https://github.com/go-gitea/gitea/issues/23643 --------- Co-authored-by: delvh <dev.lh@web.de>
This commit is contained in:
		
							
								
								
									
										56
									
								
								cmd/actions.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										56
									
								
								cmd/actions.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,56 @@ | ||||
| // Copyright 2023 The Gitea Authors. All rights reserved. | ||||
| // SPDX-License-Identifier: MIT | ||||
|  | ||||
| package cmd | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
|  | ||||
| 	"code.gitea.io/gitea/modules/private" | ||||
| 	"code.gitea.io/gitea/modules/setting" | ||||
|  | ||||
| 	"github.com/urfave/cli" | ||||
| ) | ||||
|  | ||||
| var ( | ||||
| 	// CmdActions represents the available actions sub-commands. | ||||
| 	CmdActions = cli.Command{ | ||||
| 		Name:        "actions", | ||||
| 		Usage:       "", | ||||
| 		Description: "Commands for managing Gitea Actions", | ||||
| 		Subcommands: []cli.Command{ | ||||
| 			subcmdActionsGenRunnerToken, | ||||
| 		}, | ||||
| 	} | ||||
|  | ||||
| 	subcmdActionsGenRunnerToken = cli.Command{ | ||||
| 		Name:    "generate-runner-token", | ||||
| 		Usage:   "Generate a new token for a runner to use to register with the server", | ||||
| 		Action:  runGenerateActionsRunnerToken, | ||||
| 		Aliases: []string{"grt"}, | ||||
| 		Flags: []cli.Flag{ | ||||
| 			cli.StringFlag{ | ||||
| 				Name:  "scope, s", | ||||
| 				Value: "", | ||||
| 				Usage: "{owner}[/{repo}] - leave empty for a global runner", | ||||
| 			}, | ||||
| 		}, | ||||
| 	} | ||||
| ) | ||||
|  | ||||
| func runGenerateActionsRunnerToken(c *cli.Context) error { | ||||
| 	ctx, cancel := installSignals() | ||||
| 	defer cancel() | ||||
|  | ||||
| 	setting.InitProviderFromExistingFile() | ||||
| 	setting.LoadCommonSettings() | ||||
|  | ||||
| 	scope := c.String("scope") | ||||
|  | ||||
| 	respText, extra := private.GenerateActionsRunnerToken(ctx, scope) | ||||
| 	if extra.HasError() { | ||||
| 		return handleCliResponseExtra(extra) | ||||
| 	} | ||||
| 	_, _ = fmt.Printf("%s\n", respText) | ||||
| 	return nil | ||||
| } | ||||
| @@ -551,3 +551,28 @@ Restore-repo restore repository data from disk dir: | ||||
|   - `--owner_name lunny`: Restore destination owner name | ||||
|   - `--repo_name tango`: Restore destination repository name | ||||
|   - `--units <units>`: Which items will be restored, one or more units should be separated as comma. wiki, issues, labels, releases, release_assets, milestones, pull_requests, comments are allowed. Empty means all units. | ||||
|  | ||||
| ### actions generate-runner-token | ||||
|  | ||||
| Generate a new token for a runner to use to register with the server | ||||
|  | ||||
| - Options: | ||||
|   - `--scope {owner}[/{repo}]`, `-s {owner}[/{repo}]`: To limit the scope of the runner, no scope means the runner can be used for all repos, but you can also limit it to a specific repo or owner | ||||
|  | ||||
| To register a global runner: | ||||
|  | ||||
| ``` | ||||
| gitea actions generate-runner-token | ||||
| ``` | ||||
|  | ||||
| To register a runner for a specific organization, in this case `org`: | ||||
|  | ||||
| ``` | ||||
| gitea actions generate-runner-token -s org | ||||
| ``` | ||||
|  | ||||
| To register a runner for a specific repo, in this case `username/test-repo`: | ||||
|  | ||||
| ``` | ||||
| gitea actions generate-runner-token -s username/test-repo | ||||
| ``` | ||||
|   | ||||
							
								
								
									
										1
									
								
								main.go
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								main.go
									
									
									
									
									
								
							| @@ -75,6 +75,7 @@ arguments - which can alternatively be run by running the subcommand web.` | ||||
| 		cmd.CmdDocs, | ||||
| 		cmd.CmdDumpRepository, | ||||
| 		cmd.CmdRestoreRepository, | ||||
| 		cmd.CmdActions, | ||||
| 	} | ||||
| 	// Now adjust these commands to add our global configuration options | ||||
|  | ||||
|   | ||||
							
								
								
									
										27
									
								
								modules/private/actions.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								modules/private/actions.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,27 @@ | ||||
| // Copyright 2023 The Gitea Authors. All rights reserved. | ||||
| // SPDX-License-Identifier: MIT | ||||
|  | ||||
| package private | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
|  | ||||
| 	"code.gitea.io/gitea/modules/setting" | ||||
| ) | ||||
|  | ||||
| // Email structure holds a data for sending general emails | ||||
| type GenerateTokenRequest struct { | ||||
| 	Scope string | ||||
| } | ||||
|  | ||||
| // GenerateActionsRunnerToken calls the internal GenerateActionsRunnerToken function | ||||
| func GenerateActionsRunnerToken(ctx context.Context, scope string) (string, ResponseExtra) { | ||||
| 	reqURL := setting.LocalURL + "api/internal/actions/generate_actions_runner_token" | ||||
|  | ||||
| 	req := newInternalRequest(ctx, reqURL, "POST", GenerateTokenRequest{ | ||||
| 		Scope: scope, | ||||
| 	}) | ||||
|  | ||||
| 	resp, extra := requestJSONResp(req, &responseText{}) | ||||
| 	return resp.Text, extra | ||||
| } | ||||
							
								
								
									
										91
									
								
								routers/private/actions.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										91
									
								
								routers/private/actions.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,91 @@ | ||||
| // Copyright 2023 The Gitea Authors. All rights reserved. | ||||
| // SPDX-License-Identifier: MIT | ||||
|  | ||||
| package private | ||||
|  | ||||
| import ( | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"net/http" | ||||
| 	"strings" | ||||
|  | ||||
| 	actions_model "code.gitea.io/gitea/models/actions" | ||||
| 	repo_model "code.gitea.io/gitea/models/repo" | ||||
| 	user_model "code.gitea.io/gitea/models/user" | ||||
| 	"code.gitea.io/gitea/modules/context" | ||||
| 	"code.gitea.io/gitea/modules/json" | ||||
| 	"code.gitea.io/gitea/modules/log" | ||||
| 	"code.gitea.io/gitea/modules/private" | ||||
| 	"code.gitea.io/gitea/modules/util" | ||||
| ) | ||||
|  | ||||
| // GenerateActionsRunnerToken generates a new runner token for a given scope | ||||
| func GenerateActionsRunnerToken(ctx *context.PrivateContext) { | ||||
| 	var genRequest private.GenerateTokenRequest | ||||
| 	rd := ctx.Req.Body | ||||
| 	defer rd.Close() | ||||
|  | ||||
| 	if err := json.NewDecoder(rd).Decode(&genRequest); err != nil { | ||||
| 		log.Error("%v", err) | ||||
| 		ctx.JSON(http.StatusInternalServerError, private.Response{ | ||||
| 			Err: err.Error(), | ||||
| 		}) | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	owner, repo, err := parseScope(ctx, genRequest.Scope) | ||||
| 	if err != nil { | ||||
| 		log.Error("%v", err) | ||||
| 		ctx.JSON(http.StatusInternalServerError, private.Response{ | ||||
| 			Err: err.Error(), | ||||
| 		}) | ||||
| 	} | ||||
|  | ||||
| 	token, err := actions_model.GetUnactivatedRunnerToken(ctx, owner, repo) | ||||
| 	if errors.Is(err, util.ErrNotExist) { | ||||
| 		token, err = actions_model.NewRunnerToken(ctx, owner, repo) | ||||
| 		if err != nil { | ||||
| 			err := fmt.Sprintf("error while creating runner token: %v", err) | ||||
| 			log.Error("%v", err) | ||||
| 			ctx.JSON(http.StatusInternalServerError, private.Response{ | ||||
| 				Err: err, | ||||
| 			}) | ||||
| 			return | ||||
| 		} | ||||
| 	} else if err != nil { | ||||
| 		err := fmt.Sprintf("could not get unactivated runner token: %v", err) | ||||
| 		log.Error("%v", err) | ||||
| 		ctx.JSON(http.StatusInternalServerError, private.Response{ | ||||
| 			Err: err, | ||||
| 		}) | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	ctx.PlainText(http.StatusOK, token.Token) | ||||
| } | ||||
|  | ||||
| func parseScope(ctx *context.PrivateContext, scope string) (ownerID, repoID int64, err error) { | ||||
| 	ownerID = 0 | ||||
| 	repoID = 0 | ||||
| 	if scope == "" { | ||||
| 		return ownerID, repoID, nil | ||||
| 	} | ||||
|  | ||||
| 	ownerName, repoName, found := strings.Cut(scope, "/") | ||||
|  | ||||
| 	u, err := user_model.GetUserByName(ctx, ownerName) | ||||
| 	if err != nil { | ||||
| 		return ownerID, repoID, err | ||||
| 	} | ||||
|  | ||||
| 	if !found { | ||||
| 		return u.ID, repoID, nil | ||||
| 	} | ||||
|  | ||||
| 	r, err := repo_model.GetRepositoryByName(u.ID, repoName) | ||||
| 	if err != nil { | ||||
| 		return ownerID, repoID, err | ||||
| 	} | ||||
| 	repoID = r.ID | ||||
| 	return ownerID, repoID, nil | ||||
| } | ||||
| @@ -77,6 +77,7 @@ func Routes() *web.Route { | ||||
| 	r.Get("/manager/processes", Processes) | ||||
| 	r.Post("/mail/send", SendEmail) | ||||
| 	r.Post("/restore_repo", RestoreRepo) | ||||
| 	r.Post("/actions/generate_actions_runner_token", GenerateActionsRunnerToken) | ||||
|  | ||||
| 	return r | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user