Files
devstar/services/runner/runner.go
2025-08-11 11:29:50 +08:00

145 lines
3.5 KiB
Go

package runner
import (
"context"
"fmt"
"net"
"strings"
"time"
actions_module "code.gitea.io/gitea/models/actions"
docker_module "code.gitea.io/gitea/modules/docker"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
)
func RegistGlobalRunner(ctx context.Context) error {
log.Info("获取全局RunnerToken...")
actionRunnerToken, err := actions_module.NewRunnerToken(ctx, 0, 0)
if err != nil {
return fmt.Errorf("获取全局RunnerToken失败:%v", err)
}
runnerCount := setting.Runner.Count
for i := 0; i < runnerCount; i++ {
err := RegistRunner(ctx, actionRunnerToken.Token)
if err != nil {
return fmt.Errorf("注册Runner失败:%v", err)
}
}
return nil
}
func RegistRunner(ctx context.Context, token string) error {
log.Info("开始注册Runner...")
cli, err := docker_module.CreateDockerClient(&ctx)
if err != nil {
return fmt.Errorf("Docker client创建失败:%v", err)
}
log.Info("[RegistRunner]Docker client创建成功")
defer cli.Close()
//拉取act_runner镜像
dockerHost, err := docker_module.GetDockerSocketPath()
if err != nil {
return fmt.Errorf("获取docker socket路径失败:%v", err)
}
// 拉取镜像
err = docker_module.PullImageSync(cli, dockerHost, setting.Runner.Image)
if err != nil {
return fmt.Errorf("拉取act_runner镜像失败:%v", err)
}
//获取本机IP
ips, err := getLocalIP()
if err != nil {
return fmt.Errorf("获取本机IP失败:%v", err)
}
//获取InstanceUrl
conntype := strings.Split(setting.AppURL, "://")[0]
port := setting.HTTPPort
instanceURL := conntype + "://" + ips[0] + ":" + port
timestamp := time.Now().Format("20060102150405")
//Runner配置
env := []string{
"GITEA_INSTANCE_URL=" + instanceURL,
"GITEA_RUNNER_REGISTRATION_TOKEN=" + token,
"GITEA_RUNNER_NAME=runner-" + timestamp,
}
binds := []string{
"/var/run/docker.sock:/var/run/docker.sock",
}
containerName := "runner-" + timestamp
//创建并启动Runner容器
opts := &docker_module.CreateDevcontainerOptions{
Name: containerName,
Image: setting.Runner.Image,
Binds: binds,
ContainerEnv: env,
}
err = docker_module.CreateAndStartContainer(cli, opts)
if err != nil {
return fmt.Errorf("创建并注册Runner失败:%v", err)
}
return nil
}
func DeleteRunnerByName(ctx context.Context, runnerName string) error {
log.Info("开始停止并删除容器: %s", runnerName)
// 创建Docker客户端
cli, err := docker_module.CreateDockerClient(&ctx)
if err != nil {
return fmt.Errorf("Docker client创建失败:%v", err)
}
log.Info("[StopAndRemoveContainer]Docker client创建成功")
defer cli.Close()
err = docker_module.DeleteContainer(cli, runnerName)
if err != nil {
return fmt.Errorf("Runner创建失败:%v", err)
}
return nil
}
func getLocalIP() ([]string, error) {
var ips []string
interfaces, err := net.Interfaces()
if err != nil {
return nil, err
}
for _, iface := range interfaces {
if iface.Flags&net.FlagUp == 0 ||
iface.Flags&net.FlagLoopback != 0 {
continue
}
addrs, err := iface.Addrs()
if err != nil {
continue
}
// 遍历地址列表
for _, addr := range addrs {
var ip net.IP
switch v := addr.(type) {
case *net.IPNet:
ip = v.IP
case *net.IPAddr:
ip = v.IP
}
if ip == nil || ip.IsLoopback() {
continue
}
ip = ip.To4()
if ip == nil {
continue // 非IPv4地址
}
ips = append(ips, ip.String())
}
}
if len(ips) == 0 {
return nil, fmt.Errorf("no valid IP address found")
}
return ips, nil
}