Skip to content

Commit 0efa236

Browse files
committed
feature: velox v2
Signed-off-by: Valery Piashchynski <[email protected]>
1 parent 5b3990b commit 0efa236

33 files changed

+352
-2399
lines changed

builder/builder.go

Lines changed: 53 additions & 115 deletions
Original file line numberDiff line numberDiff line change
@@ -4,54 +4,49 @@ import (
44
"bytes"
55
"context"
66
"fmt"
7-
"math/rand"
87
"os"
98
"os/exec"
109
"path/filepath"
11-
"regexp"
1210
"strings"
1311
"time"
1412

1513
"github.com/hashicorp/go-version"
1614
"github.com/roadrunner-server/velox/v2025"
1715
"github.com/roadrunner-server/velox/v2025/builder/templates"
16+
"github.com/roadrunner-server/velox/v2025/plugin"
1817
"go.uber.org/zap"
1918
)
2019

2120
const (
2221
// path to the file which should be generated from the template
23-
pluginsPath string = "/container/plugins.go"
24-
letterBytes = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
25-
goModStr string = "go.mod"
26-
pluginStructureStr string = "Plugin{}"
27-
rrMainGo string = "cmd/rr/main.go"
28-
executableName string = "rr"
22+
pluginsPath string = "/container/plugins.go"
23+
goModStr string = "go.mod"
24+
rrMainGo string = "cmd/rr/main.go"
25+
executableName string = "rr"
26+
executableNameWindows string = "rr.exe"
2927
// cleanup pattern
3028
cleanupPattern string = "roadrunner-server*"
3129
ldflags string = "-X github.com/roadrunner-server/roadrunner/v2025/internal/meta.version=%s -X github.com/roadrunner-server/roadrunner/v2025/internal/meta.buildTime=%s"
3230
)
3331

34-
var replaceRegexp = regexp.MustCompile("(\t| )(.+) => (.+)")
35-
3632
type Builder struct {
3733
// rrTempPath - path, where RR was saved
3834
rrTempPath string
3935
// outputDir - output directory
4036
outputDir string
41-
modules []*velox.ModulesInfo
4237
log *zap.Logger
4338
sb *strings.Builder
39+
plugins []*plugin.Plugin
4440
debug bool
4541
rrVersion string
4642
goos string
4743
goarch string
4844
}
4945

5046
// NewBuilder creates a new Builder with the given required parameters and optional configuration
51-
func NewBuilder(rrTmpPath string, modules []*velox.ModulesInfo, opts ...Option) *Builder {
47+
func NewBuilder(rrTmpPath string, opts ...Option) *Builder {
5248
b := &Builder{
5349
rrTempPath: rrTmpPath,
54-
modules: modules,
5550
}
5651

5752
// Apply all options
@@ -63,64 +58,47 @@ func NewBuilder(rrTmpPath string, modules []*velox.ModulesInfo, opts ...Option)
6358
}
6459

6560
// Build builds a RR based on the provided modules info
66-
func (b *Builder) Build(rrModule string) error { //nolint:gocyclo
67-
t := new(templates.Template)
68-
69-
module, err := validateModule(rrModule)
70-
if err != nil {
71-
return err
61+
func (b *Builder) Build(rrRef string) (string, error) { //nolint:gocyclo
62+
if len(b.plugins) == 0 {
63+
return "", fmt.Errorf("please, use WithPlugins to add plugins to the RR build")
7264
}
7365

74-
t.ModuleVersion = module
75-
t.Entries = make([]*templates.Entry, len(b.modules))
76-
for i := range b.modules {
77-
t.Entries[i] = &templates.Entry{
78-
Module: b.modules[i].ModuleName,
79-
// we need to set prefix to avoid collisions
80-
Prefix: randStringBytes(5),
81-
StructureName: pluginStructureStr,
82-
PseudoVersion: b.modules[i].PseudoVersion,
83-
Replace: b.modules[i].Replace,
84-
}
66+
t := templates.NewTemplate(b.plugins)
67+
68+
module, err := validateModule(rrRef)
69+
if err != nil {
70+
return "", err
8571
}
8672

73+
t.RRModuleVersion = module
8774
buf := new(bytes.Buffer)
8875

8976
// compatibility with version 2
90-
switch t.ModuleVersion {
77+
switch t.RRModuleVersion {
9178
case velox.V2025:
9279
err = templates.CompileTemplateV2025(buf, t)
9380
if err != nil {
94-
return err
81+
return "", err
9582
}
9683
case velox.V2024:
9784
err = templates.CompileTemplateV2024(buf, t)
9885
if err != nil {
99-
return err
100-
}
101-
case velox.V2023:
102-
err = templates.CompileTemplateV2023(buf, t)
103-
if err != nil {
104-
return err
105-
}
106-
case velox.V2:
107-
err = templates.CompileTemplateV2(buf, t)
108-
if err != nil {
109-
return err
86+
return "", err
11087
}
11188
default:
112-
return fmt.Errorf("unknown module version: %s", t.ModuleVersion)
89+
return "", fmt.Errorf("unknown module version: %s", t.RRModuleVersion)
11390
}
11491

11592
b.log.Debug("template", zap.String("template", buf.String()))
11693

11794
f, err := os.Open(b.rrTempPath)
11895
if err != nil {
119-
return err
96+
return "", err
12097
}
12198
defer func() {
12299
_ = f.Close()
123-
files, errGl := filepath.Glob(filepath.Join(os.TempDir(), cleanupPattern))
100+
// clean output directory, remove everything except RR binary
101+
files, errGl := filepath.Glob(filepath.Join(b.outputDir, cleanupPattern))
124102
if errGl != nil {
125103
return
126104
}
@@ -134,77 +112,67 @@ func (b *Builder) Build(rrModule string) error { //nolint:gocyclo
134112
// remove old plugins.go
135113
err = os.Remove(filepath.Join(b.rrTempPath, pluginsPath))
136114
if err != nil {
137-
return err
115+
return "", err
138116
}
139117

140118
err = os.WriteFile(filepath.Join(b.rrTempPath, pluginsPath), buf.Bytes(), 0600)
141119
if err != nil {
142-
return err
120+
return "", err
143121
}
144122

145123
err = os.Remove(filepath.Join(b.rrTempPath, goModStr))
146124
if err != nil {
147-
return err
125+
return "", err
148126
}
149127

150128
goModFile, err := os.Create(filepath.Join(b.rrTempPath, goModStr))
151129
if err != nil {
152-
return err
130+
return "", err
153131
}
154132

155133
// reuse buffer
156134
buf.Reset()
157135

158136
// compatibility with version 2
159-
switch t.ModuleVersion {
137+
switch t.RRModuleVersion {
160138
case velox.V2025:
161139
err = templates.CompileGoModTemplate2025(buf, t)
162140
if err != nil {
163-
return err
141+
return "", err
164142
}
165143
case velox.V2024:
166144
err = templates.CompileGoModTemplate2024(buf, t)
167145
if err != nil {
168-
return err
169-
}
170-
case velox.V2023:
171-
err = templates.CompileGoModTemplate2023(buf, t)
172-
if err != nil {
173-
return err
174-
}
175-
case velox.V2:
176-
err = templates.CompileGoModTemplateV2(buf, t)
177-
if err != nil {
178-
return err
146+
return "", err
179147
}
180148
default:
181-
return fmt.Errorf("unknown module version: %s", t.ModuleVersion)
149+
return "", fmt.Errorf("unknown module version: %s", t.RRModuleVersion)
182150
}
183151

184152
b.log.Debug("template", zap.String("template", buf.String()))
185153

186154
_, err = goModFile.Write(buf.Bytes())
187155
if err != nil {
188-
return err
156+
return "", err
189157
}
190158

191159
// reuse buffer
192160
buf.Reset()
193161

194162
err = b.exec([]string{"go", "mod", "download"})
195163
if err != nil {
196-
return err
164+
return "", err
197165
}
198166

199167
err = b.exec([]string{"go", "mod", "tidy"})
200168
if err != nil {
201-
return err
169+
return "", err
202170
}
203171

204172
b.log.Info("creating output directory", zap.String("dir", b.outputDir))
205173
_, err = os.Stat(b.outputDir)
206174
if err != nil && !os.IsNotExist(err) {
207-
return fmt.Errorf("stat failed for output directory %s: %w", b.outputDir, err)
175+
return "", fmt.Errorf("stat failed for output directory %s: %w", b.outputDir, err)
208176
}
209177

210178
if os.IsExist(err) {
@@ -214,22 +182,24 @@ func (b *Builder) Build(rrModule string) error { //nolint:gocyclo
214182

215183
err = os.MkdirAll(b.outputDir, os.ModeDir|os.ModePerm)
216184
if err != nil {
217-
return err
185+
return "", err
218186
}
219187

220188
// INFO: we can get go envs via go env GOOS for example, but instead we will set them manually
221-
err = b.goBuildCmd(filepath.Join(b.rrTempPath, executableName))
189+
err = b.goBuildCmd(filepath.Join(b.rrTempPath, generateExecutableName(b.goos)))
222190
if err != nil {
223-
return err
191+
return "", err
224192
}
225193

226-
b.log.Info("moving binary", zap.String("file", filepath.Join(b.rrTempPath, executableName)), zap.String("to", filepath.Join(b.outputDir, executableName)))
227-
err = moveFile(filepath.Join(b.rrTempPath, executableName), filepath.Join(b.outputDir, executableName))
194+
// move the binary to the output directory
195+
binaryPath := filepath.Join(b.outputDir, generateExecutableName(b.goos))
196+
b.log.Info("moving binary", zap.String("file", filepath.Join(b.rrTempPath, generateExecutableName(b.goos))), zap.String("to", binaryPath))
197+
err = moveFile(filepath.Join(b.rrTempPath, generateExecutableName(b.goos)), binaryPath)
228198
if err != nil {
229-
return err
199+
return "", err
230200
}
231201

232-
return nil
202+
return binaryPath, nil
233203
}
234204

235205
func (b *Builder) Write(d []byte) (int, error) {
@@ -256,14 +226,6 @@ func validateModule(module string) (string, error) {
256226
return fmt.Sprintf("v%d", v.Segments()[0]), nil
257227
}
258228

259-
func randStringBytes(n int) string {
260-
b := make([]byte, n)
261-
for i := range b {
262-
b[i] = letterBytes[rand.Intn(len(letterBytes))] //nolint:gosec
263-
}
264-
return string(b)
265-
}
266-
267229
func (b *Builder) goBuildCmd(outputPath string) error {
268230
var cmd *exec.Cmd
269231

@@ -346,38 +308,6 @@ func (b *Builder) exec(cmd []string) error {
346308
return nil
347309
}
348310

349-
func (b *Builder) getDepsReplace(repl string) []*templates.Entry {
350-
b.log.Info("found replace, processing", zap.String("dependency", repl))
351-
modFile, err := os.ReadFile(filepath.Join(repl, goModStr))
352-
if err != nil {
353-
return nil
354-
}
355-
356-
var result []*templates.Entry //nolint:prealloc
357-
replaces := replaceRegexp.FindAllStringSubmatch(string(modFile), -1)
358-
for i := range replaces {
359-
split := strings.Split(strings.TrimSpace(replaces[i][0]), " => ")
360-
if len(split) != 2 {
361-
b.log.Error("not enough split args", zap.String("replace", replaces[i][0]))
362-
continue
363-
}
364-
365-
moduleName := split[0]
366-
moduleReplace := split[1]
367-
368-
if strings.HasPrefix(moduleReplace, ".") {
369-
moduleReplace = filepath.Join(repl, moduleReplace)
370-
}
371-
372-
result = append(result, &templates.Entry{
373-
Module: moduleName,
374-
Replace: moduleReplace,
375-
})
376-
}
377-
378-
return result
379-
}
380-
381311
func moveFile(from, to string) error {
382312
ffInfo, err := os.Stat(from)
383313
if err != nil {
@@ -406,3 +336,11 @@ func moveFile(from, to string) error {
406336

407337
return toFile.Close()
408338
}
339+
340+
// for Windows we should use .exe pattern
341+
func generateExecutableName(goos string) string {
342+
if strings.ToLower(goos) == "windows" {
343+
return executableNameWindows
344+
}
345+
return executableName
346+
}

0 commit comments

Comments
 (0)