GitRoot
craft your forge, build your project, grow your community freely
1// SPDX-FileCopyrightText: 2025 Romain Maneschi <romain@gitroot.dev>
2//
3// SPDX-License-Identifier: EUPL-1.2
4
5package exec
6
7import (
8 "context"
9 "fmt"
10 "os"
11 "path/filepath"
12 "time"
13
14 pluginLib "gitroot.dev/libs/golang/plugin/model"
15 "gitroot.dev/server/configuration"
16 "gitroot.dev/server/logger"
17 "gitroot.dev/server/repository"
18 "gitroot.dev/server/user"
19)
20
21const APP_DIR = "app"
22
23type executor interface {
24 name() string
25 exec(dir string, exec pluginLib.Exec) (*pluginLib.ExecStatus, error)
26}
27
28type manager struct {
29 logger *logger.Logger
30 ctx context.Context
31 conf needConf
32 executor executor
33}
34
35type needConf interface {
36 GetExecConf() configuration.ExecConf
37}
38
39type needUser interface {
40 RootCommiter() *user.Commiter
41}
42
43func NewManager(ctx context.Context, conf needConf, userManager needUser) *manager {
44 log := logger.NewLoggerCtx(logger.EXEC, ctx)
45 var exe executor = NewNone(log)
46 c := conf.GetExecConf()
47 if c.BareMetal.Enabled {
48 exe = NewBareMetal(log)
49 } else if c.Bwrap.Enabled {
50 exe = NewBwrap(log, conf.GetExecConf().Bwrap)
51 } else if c.Container.Enabled {
52 exe = NewContainer(log, conf.GetExecConf().Container)
53 } else if c.Ssh.Enabled {
54 exe = NewSsh(log, conf.GetExecConf().Ssh, userManager)
55 } else {
56 log.Warn("executor not found will use none")
57 }
58 m := &manager{
59 logger: log,
60 ctx: ctx,
61 conf: conf,
62 executor: exe,
63 }
64 return m
65}
66
67func (m *manager) prepareExec(project *repository.GitRootRepository, branch string, callback func(dir string) (*pluginLib.ExecStatus, error)) (*pluginLib.ExecStatus, error) {
68 dir := os.TempDir()
69 tempDir := filepath.Join(dir, "pipelines-gitroot", fmt.Sprintf("%s-%s-%d", project.Name(), branch, time.Now().Nanosecond()))
70
71 err := os.MkdirAll(tempDir, os.ModePerm)
72 if err != nil {
73 return nil, err
74 }
75
76 err = project.Worktree(filepath.Join(tempDir, APP_DIR))
77 if err != nil {
78 return nil, err
79 }
80 return callback(tempDir)
81}
82
83func (m *manager) Exec(project *repository.GitRootRepository, branch string, exec pluginLib.Exec) (*pluginLib.ExecStatus, error) {
84 m.logger.Info("will exec", logger.NewLoggerPair("executor", m.executor.name()), logger.NewLoggerPair("project", project.Name()), logger.NewLoggerPair("branch", branch))
85 return m.prepareExec(project, branch, func(dir string) (*pluginLib.ExecStatus, error) {
86 return m.executor.exec(dir, exec)
87 })
88}