mirror of
https://code.forgejo.org/forgejo/runner.git
synced 2025-07-02 16:38:35 +00:00
[FORGEJO] add the create-runner-file
This commit is contained in:
parent
b876fa3fab
commit
4c78fbc7b1
7 changed files with 328 additions and 10 deletions
164
internal/app/cmd/create-runner-file.go
Normal file
164
internal/app/cmd/create-runner-file.go
Normal file
|
@ -0,0 +1,164 @@
|
|||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
pingv1 "code.gitea.io/actions-proto-go/ping/v1"
|
||||
"github.com/bufbuild/connect-go"
|
||||
gouuid "github.com/google/uuid"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"gitea.com/gitea/act_runner/internal/app/run"
|
||||
"gitea.com/gitea/act_runner/internal/pkg/client"
|
||||
"gitea.com/gitea/act_runner/internal/pkg/config"
|
||||
"gitea.com/gitea/act_runner/internal/pkg/ver"
|
||||
)
|
||||
|
||||
type createRunnerFileArgs struct {
|
||||
Connect bool
|
||||
InstanceAddr string
|
||||
Secret string
|
||||
Name string
|
||||
}
|
||||
|
||||
func createRunnerFileCmd(ctx context.Context, configFile *string) *cobra.Command {
|
||||
var argsVar createRunnerFileArgs
|
||||
cmd := &cobra.Command{
|
||||
Use: "create-runner-file",
|
||||
Short: "Create a runner file using a shared secret used to pre-register the runner on the Forgejo instance",
|
||||
Args: cobra.MaximumNArgs(0),
|
||||
RunE: runCreateRunnerFile(ctx, &argsVar, configFile),
|
||||
}
|
||||
cmd.Flags().BoolVar(&argsVar.Connect, "connect", false, "tries to connect to the instance using the secret (Forgejo v1.21 instance or greater)")
|
||||
cmd.Flags().StringVar(&argsVar.InstanceAddr, "instance", "", "Forgejo instance address")
|
||||
cmd.MarkFlagRequired("instance")
|
||||
cmd.Flags().StringVar(&argsVar.Secret, "secret", "", "secret shared with the Frogejo instance via forgejo-cli actions register")
|
||||
cmd.MarkFlagRequired("secret")
|
||||
cmd.Flags().StringVar(&argsVar.Name, "name", "", "Runner name")
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
// must be exactly the same as fogejo/models/actions/forgejo.go
|
||||
func uuidFromSecret(secret string) (string, error) {
|
||||
uuid, err := gouuid.FromBytes([]byte(secret[:16]))
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("gouuid.FromBytes %v", err)
|
||||
}
|
||||
return uuid.String(), nil
|
||||
}
|
||||
|
||||
// should be exactly the same as forgejo/cmd/forgejo/actions.go
|
||||
func validateSecret(secret string) error {
|
||||
secretLen := len(secret)
|
||||
if secretLen != 40 {
|
||||
return fmt.Errorf("the secret must be exactly 40 characters long, not %d", secretLen)
|
||||
}
|
||||
if _, err := hex.DecodeString(secret); err != nil {
|
||||
return fmt.Errorf("the secret must be an hexadecimal string: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func ping(cfg *config.Config, reg *config.Registration) error {
|
||||
// initial http client
|
||||
cli := client.New(
|
||||
reg.Address,
|
||||
cfg.Runner.Insecure,
|
||||
"",
|
||||
"",
|
||||
ver.Version(),
|
||||
)
|
||||
|
||||
_, err := cli.Ping(context.Background(), connect.NewRequest(&pingv1.PingRequest{
|
||||
Data: reg.UUID,
|
||||
}))
|
||||
if err != nil {
|
||||
return fmt.Errorf("ping %s failed %w", reg.Address, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func runCreateRunnerFile(ctx context.Context, args *createRunnerFileArgs, configFile *string) func(cmd *cobra.Command, args []string) error {
|
||||
return func(*cobra.Command, []string) error {
|
||||
log.SetLevel(log.DebugLevel)
|
||||
log.Info("Creating runner file")
|
||||
|
||||
//
|
||||
// Prepare the registration data
|
||||
//
|
||||
cfg, err := config.LoadDefault(*configFile)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid configuration: %w", err)
|
||||
}
|
||||
|
||||
if err := validateSecret(args.Secret); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
uuid, err := uuidFromSecret(args.Secret)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
name := args.Name
|
||||
if name == "" {
|
||||
name, _ = os.Hostname()
|
||||
log.Infof("Runner name is empty, use hostname '%s'.", name)
|
||||
}
|
||||
|
||||
reg := &config.Registration{
|
||||
Name: name,
|
||||
UUID: uuid,
|
||||
Token: args.Secret,
|
||||
Address: args.InstanceAddr,
|
||||
}
|
||||
|
||||
//
|
||||
// Verify the Forgejo instance is reachable
|
||||
//
|
||||
if err := ping(cfg, reg); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
//
|
||||
// Save the registration file
|
||||
//
|
||||
if err := config.SaveRegistration(cfg.Runner.File, reg); err != nil {
|
||||
return fmt.Errorf("failed to save runner config to %s: %w", cfg.Runner.File, err)
|
||||
}
|
||||
|
||||
//
|
||||
// Verify the secret works
|
||||
//
|
||||
if args.Connect {
|
||||
cli := client.New(
|
||||
reg.Address,
|
||||
cfg.Runner.Insecure,
|
||||
reg.UUID,
|
||||
reg.Token,
|
||||
ver.Version(),
|
||||
)
|
||||
|
||||
runner := run.NewRunner(cfg, reg, cli)
|
||||
resp, err := runner.Declare(ctx, cfg.Runner.Labels)
|
||||
|
||||
if err != nil && connect.CodeOf(err) == connect.CodeUnimplemented {
|
||||
log.Warn("Cannot verify the connection because the Forgejo instance is lower than v1.21")
|
||||
} else if err != nil {
|
||||
log.WithError(err).Error("fail to invoke Declare")
|
||||
return err
|
||||
} else {
|
||||
log.Infof("connection successful: %s, with version: %s, with labels: %v",
|
||||
resp.Msg.Runner.Name, resp.Msg.Runner.Version, resp.Msg.Runner.Labels)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue