Skip to content

Commit c45a2ae

Browse files
authored
perf: add Dockerfile file to select build (#2372)
Signed-off-by: 张启航 <[email protected]>
1 parent 1ec6aa5 commit c45a2ae

File tree

10 files changed

+466
-30
lines changed

10 files changed

+466
-30
lines changed

api/handler/service_operation.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -398,6 +398,10 @@ func (o *OperationHandler) buildFromSourceCode(r *model.ComponentBuildReq, servi
398398
body["user"] = r.CodeInfo.User
399399
body["password"] = r.CodeInfo.Password
400400
}
401+
// 传递 dockerfile_path 到构建任务
402+
if r.CodeInfo.DockerfilePath != "" {
403+
body["dockerfile_path"] = r.CodeInfo.DockerfilePath
404+
}
401405
body["expire"] = 180
402406
body["configs"] = r.Configs
403407
return o.sendBuildTopic(service.ServiceID, "build_from_source_code", body, r.Arch)

api/model/model.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1729,6 +1729,10 @@ type BuildCodeInfo struct {
17291729
Password string `json:"password" validate:"password"`
17301730
//for .netcore source type, need cmd
17311731
Cmd string `json:"cmd"`
1732+
// Dockerfile路径,用于指定子目录中的Dockerfile
1733+
// in: body
1734+
// required: false
1735+
DockerfilePath string `json:"dockerfile_path"`
17321736
}
17331737

17341738
// BuildSlugInfo -

builder/build/dockerfile_build.go

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,13 @@ type dockerfileBuild struct {
4646
}
4747

4848
func (d *dockerfileBuild) Build(re *Request) (*Response, error) {
49-
filepath := path.Join(re.SourceDir, "Dockerfile")
50-
re.Logger.Info("Start parse Dockerfile", map[string]string{"step": "builder-exector"})
49+
// 如果指定了 dockerfile_path,使用它;否则使用默认的 Dockerfile
50+
dockerfilePath := "Dockerfile"
51+
if re.CodeSouceInfo.DockerfilePath != "" {
52+
dockerfilePath = re.CodeSouceInfo.DockerfilePath
53+
}
54+
filepath := path.Join(re.SourceDir, dockerfilePath)
55+
re.Logger.Info("Start parse Dockerfile", map[string]string{"step": "builder-exector", "dockerfile_path": dockerfilePath})
5156
_, err := sources.ParseFile(filepath)
5257
if err != nil {
5358
logrus.Error("parse dockerfile error.", err.Error())
@@ -88,6 +93,11 @@ func (d *dockerfileBuild) stopPreBuildJob(re *Request) error {
8893
func (d *dockerfileBuild) runBuildJob(re *Request, buildImageName string) error {
8994
name := fmt.Sprintf("%s-%s", re.ServiceID, re.DeployVersion)
9095
namespace := re.RbdNamespace
96+
// 获取 dockerfile 路径
97+
dockerfilePath := "Dockerfile"
98+
if re.CodeSouceInfo.DockerfilePath != "" {
99+
dockerfilePath = re.CodeSouceInfo.DockerfilePath
100+
}
91101
job := corev1.Pod{
92102
ObjectMeta: metav1.ObjectMeta{
93103
Name: name,
@@ -171,6 +181,10 @@ func (d *dockerfileBuild) runBuildJob(re *Request, buildImageName string) error
171181
Privileged: &privileged,
172182
},
173183
}
184+
// 如果指定了自定义的 dockerfile 路径,添加 filename 参数
185+
if dockerfilePath != "Dockerfile" {
186+
container.Args = append(container.Args, fmt.Sprintf("--opt=filename=%s", dockerfilePath))
187+
}
174188
if len(re.BuildKitArgs) > 0 {
175189
container.Args = append(container.Args, re.BuildKitArgs...)
176190
}

builder/exector/build_from_sourcecode_run.go

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -98,14 +98,15 @@ func NewSouceCodeBuildItem(in []byte) *SourceCodeBuildItem {
9898
eventID := gjson.GetBytes(in, "event_id").String()
9999
logger := event.GetManager().GetLogger(eventID)
100100
csi := sources.CodeSourceInfo{
101-
ServerType: strings.Replace(gjson.GetBytes(in, "server_type").String(), " ", "", -1),
102-
RepositoryURL: gjson.GetBytes(in, "repo_url").String(),
103-
Branch: gjson.GetBytes(in, "branch").String(),
104-
User: gjson.GetBytes(in, "user").String(),
105-
Password: gjson.GetBytes(in, "password").String(),
106-
TenantID: gjson.GetBytes(in, "tenant_id").String(),
107-
ServiceID: gjson.GetBytes(in, "service_id").String(),
108-
Configs: gjson.GetBytes(in, "configs").Map(),
101+
ServerType: strings.Replace(gjson.GetBytes(in, "server_type").String(), " ", "", -1),
102+
RepositoryURL: gjson.GetBytes(in, "repo_url").String(),
103+
Branch: gjson.GetBytes(in, "branch").String(),
104+
User: gjson.GetBytes(in, "user").String(),
105+
Password: gjson.GetBytes(in, "password").String(),
106+
TenantID: gjson.GetBytes(in, "tenant_id").String(),
107+
ServiceID: gjson.GetBytes(in, "service_id").String(),
108+
Configs: gjson.GetBytes(in, "configs").Map(),
109+
DockerfilePath: gjson.GetBytes(in, "dockerfile_path").String(),
109110
}
110111
envs := gjson.GetBytes(in, "envs").String()
111112
be := make(map[string]string)

builder/parser/code/lang.go

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,9 @@ package code
2020

2121
import (
2222
"fmt"
23+
"io/ioutil"
2324
"path"
25+
"path/filepath"
2426
"strings"
2527

2628
"github.com/goodrain/rainbond/util"
@@ -313,3 +315,82 @@ func netcore(homepath string) Lang {
313315
func scala(homepath string) Lang {
314316
return NO
315317
}
318+
319+
// FindDockerfiles 在指定目录中查找所有 Dockerfile 文件
320+
// 返回相对于 rootPath 的路径列表
321+
func FindDockerfiles(rootPath string, maxDepth int, maxFiles int) []string {
322+
var dockerfiles []string
323+
var ignoreDirs = map[string]bool{
324+
".git": true,
325+
"node_modules": true,
326+
"vendor": true,
327+
".svn": true,
328+
".hg": true,
329+
"__pycache__": true,
330+
".idea": true,
331+
".vscode": true,
332+
"target": true,
333+
"build": true,
334+
"dist": true,
335+
".gradle": true,
336+
".cache": true,
337+
}
338+
339+
var walk func(currentPath string, currentDepth int) bool
340+
walk = func(currentPath string, currentDepth int) bool {
341+
// 超过最大深度或已找到足够数量
342+
if currentDepth > maxDepth || len(dockerfiles) >= maxFiles {
343+
return len(dockerfiles) >= maxFiles
344+
}
345+
346+
files, err := ioutil.ReadDir(currentPath)
347+
if err != nil {
348+
return false
349+
}
350+
351+
// 先检查当前目录中的文件
352+
for _, file := range files {
353+
if file.IsDir() {
354+
continue
355+
}
356+
357+
fileName := file.Name()
358+
// 检查是否是 Dockerfile 或 Dockerfile.xxx
359+
if fileName == "Dockerfile" || strings.HasPrefix(fileName, "Dockerfile.") {
360+
relPath, err := filepath.Rel(rootPath, filepath.Join(currentPath, fileName))
361+
if err == nil {
362+
dockerfiles = append(dockerfiles, relPath)
363+
if len(dockerfiles) >= maxFiles {
364+
return true
365+
}
366+
}
367+
}
368+
}
369+
370+
// 递归遍历子目录
371+
for _, file := range files {
372+
if !file.IsDir() {
373+
continue
374+
}
375+
376+
dirName := file.Name()
377+
// 跳过隐藏目录和忽略目录
378+
if strings.HasPrefix(dirName, ".") && dirName != "." {
379+
continue
380+
}
381+
if ignoreDirs[dirName] {
382+
continue
383+
}
384+
385+
subPath := filepath.Join(currentPath, dirName)
386+
if walk(subPath, currentDepth+1) {
387+
return true
388+
}
389+
}
390+
391+
return false
392+
}
393+
394+
walk(rootPath, 0)
395+
return dockerfiles
396+
}

builder/parser/parser.go

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -196,10 +196,12 @@ type ServiceInfo struct {
196196
//For third party services
197197
Endpoints []*discovery.Endpoint `json:"endpoints,omitempty"`
198198
//os type,default linux
199-
OS string `json:"os"`
200-
Name string `json:"name,omitempty"` // module name
201-
Cname string `json:"cname,omitempty"` // service cname
199+
OS string `json:"os"`
200+
Name string `json:"name,omitempty"` // module name
201+
Cname string `json:"cname,omitempty"` // service cname
202202
Packaging string `json:"packaging,omitempty"`
203+
// Dockerfile 文件列表,相对于代码根目录的路径
204+
Dockerfiles []string `json:"dockerfiles,omitempty"`
203205
}
204206

205207
// GetServiceInfo GetServiceInfo

builder/parser/source_code.go

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -47,17 +47,18 @@ import (
4747

4848
// SourceCodeParse docker run 命令解析或直接镜像名解析
4949
type SourceCodeParse struct {
50-
ports map[int]*types.Port
51-
volumes map[string]*types.Volume
52-
envs map[string]*types.Env
53-
source string
54-
memory int
55-
image Image
56-
args []string
57-
branchs []string
58-
errors []ParseError
59-
logger event.Logger
60-
Lang code.Lang
50+
ports map[int]*types.Port
51+
volumes map[string]*types.Volume
52+
envs map[string]*types.Env
53+
source string
54+
memory int
55+
image Image
56+
args []string
57+
branchs []string
58+
errors []ParseError
59+
logger event.Logger
60+
Lang code.Lang
61+
dockerfiles []string // 所有找到的 Dockerfile 文件路径
6162

6263
Runtime bool `json:"runtime"`
6364
Dependencies bool `json:"dependencies"`
@@ -520,6 +521,14 @@ func (d *SourceCodeParse) Parse() ParseErrorList {
520521
d.args = strings.Split(rbdfileConfig.Cmd, " ")
521522
}
522523
}
524+
525+
// 扫描所有 Dockerfile 文件
526+
// 参数:最大深度 5 层,最多返回 20 个文件
527+
d.dockerfiles = code.FindDockerfiles(buildPath, 5, 20)
528+
if len(d.dockerfiles) > 0 {
529+
logrus.Infof("Found %d Dockerfile(s) in source code", len(d.dockerfiles))
530+
}
531+
523532
return d.errors
524533
}
525534

@@ -632,6 +641,7 @@ func (d *SourceCodeParse) GetServiceInfo() []ServiceInfo {
632641
Lang: d.GetLang(),
633642
ServiceType: model.ServiceTypeStatelessMultiple.String(),
634643
OS: runtime.GOOS,
644+
Dockerfiles: d.dockerfiles,
635645
}
636646
var res []ServiceInfo
637647
if d.isMulti && d.services != nil && len(d.services) > 0 {

0 commit comments

Comments
 (0)