diff --git a/java/build/maven_docker/Dockerfile b/java/build/maven_docker/Dockerfile new file mode 100644 index 0000000..8963526 --- /dev/null +++ b/java/build/maven_docker/Dockerfile @@ -0,0 +1,35 @@ +FROM golang:1.10-alpine as builder + +MAINTAINER julywind@126.com +WORKDIR /go/src/component-maven + +COPY ./ /go/src/component-maven + +RUN set -ex && \ +go build -v -o /go/bin/component-maven \ +-gcflags '-N -l' \ +./*.go + + +FROM maven:3.5-jdk-8 +RUN mkdir -p /root/src +WORKDIR /root/src + +RUN apt-get update && apt-get install -y docker \ + && rm -rf /var/lib/apt/lists/* + +COPY --from=builder /go/bin/component-maven /usr/bin/ +CMD ["component-maven"] + +LABEL TencentHubComponent='{\ + "description": "TencentHub官方组件(Java Build Maven Docker), 使用maven进行java项目构建,并且可执行docker相关的命令.",\ + "input": [\ + {"name": "GIT_CLONE_URL", "desc": "必填,源代码地址,如为私有仓库需要授权; 如需使用系统关联的git仓库, 可以从系统提供的全局环境变量中获取: ${_WORKFLOW_GIT_CLONE_URL}"},\ + {"name": "GIT_REF", "desc": "非必填,源代码目标提交号或者分支名, 默认为master"},\ + {"name": "M2_SETTINGS_XML", "desc": "非必填,$user/.m2/setting.xml配置文件内容,默认使用maven的全局配置"},\ + {"name": "GOALS", "desc": "非必填,maven 构建目标, 默认是package"},\ + {"name": "POM_PATH", "desc": "非必填,pom 文件相对路径, 默认`./pom.xml`"},\ + {"name": "EXT_COMMAND", "desc": "非必填,GOALS之外的命令, 默认不执行"},\ + {"name": "_WORKFLOW_FLAG_HUB_TOKEN", "default": "true", "desc": "非必填, 若为真, 工作流将根据用户名和密码自动填充HUB_USER和HUB_TOKEN"}\ + ]\ +}' diff --git a/java/build/maven_docker/README.md b/java/build/maven_docker/README.md new file mode 100644 index 0000000..9bcb3fa --- /dev/null +++ b/java/build/maven_docker/README.md @@ -0,0 +1,24 @@ +## 组件名称:Java Build Maven + +使用 maven 进行 java 项目构建, 可选地将构建产物上传到指定的二进制仓库. + +### 组件参数 +#### 入参 +- `GIT_CLONE_URL` 必填,源代码地址,如为私有仓库需要授权; 如需使用系统关联的git仓库, 可以从系统提供的全局环境变量中获取: `${_WORKFLOW_GIT_CLONE_URL}` +- `GIT_REF` 非必填,源代码目标提交号或者分支名, 默认为master +- `M2_SETTINGS_XML` 非必填,`$user/.m2/setting.xml`配置文件内容,默认使用maven的全局配置 +- `GOALS` 非必填,maven 构建目标, 默认是`package` +- `POM_PATH` 非必填,pom 文件相对路径, 默认`./pom.xml` +- `EXT_COMMAND` 非必填,GOALS之外的命令, 默认不执行 + +### Tag列表及其Dockerfile链接 + +* 3.5-jdk-8, latest: [Dockerfile](https://github.com/tencentyun/workflow-components/blob/c2d0c1ceb447694a092599858203d29dd877e6bb/java/build/maven/Dockerfile) + +### 源码地址 + +Java Maven Build: + +### 构建: + +`docker build -t hub.tencentyun.com/tencenthub/java_build_maven:latest .` diff --git a/java/build/maven_docker/builder.go b/java/build/maven_docker/builder.go new file mode 100644 index 0000000..6cb6aaf --- /dev/null +++ b/java/build/maven_docker/builder.go @@ -0,0 +1,205 @@ +package main + +import ( + "fmt" + "os" + "os/exec" + "path/filepath" + "strings" + "bytes" +) + +const baseSpace = "/root/src" + +type Builder struct { + // 用户提供参数, 通过环境变量传入 + GitCloneURL string + GitRef string + Goals string + PomPath string + + HubRepo string + HubUser string + HubToken string + M2SettingXML string + ExtCommand string + projectName string +} + +// NewBuilder is +func NewBuilder(envs map[string]string) (*Builder, error) { + b := &Builder{} + if envs["GIT_CLONE_URL"] != "" { + b.ExtCommand = envs["EXT_COMMAND"] + } + if envs["GIT_CLONE_URL"] != "" { + b.GitCloneURL = envs["GIT_CLONE_URL"] + b.GitRef = envs["GIT_REF"] + } else if envs["_WORKFLOW_GIT_CLONE_URL"] != "" { + b.GitCloneURL = envs["_WORKFLOW_GIT_CLONE_URL"] + b.GitRef = envs["_WORKFLOW_GIT_REF"] + } else { + return nil, fmt.Errorf("envionment variable GIT_CLONE_URL is required") + } + + if b.GitRef == "" { + b.GitRef = "master" + } + + s := strings.TrimSuffix(strings.TrimSuffix(b.GitCloneURL, "/"), ".git") + b.projectName = s[strings.LastIndex(s, "/")+1:] + + if b.GitRef = envs["GIT_REF"]; b.GitRef == "" { + b.GitRef = "master" + } + + b.Goals = strings.TrimSpace(strings.TrimPrefix(strings.TrimSpace(envs["GOALS"]), "mvn ")) + + if b.PomPath = envs["POM_PATH"]; b.PomPath == "" { + b.PomPath = "./pom.xml" + } + + b.M2SettingXML = envs["M2_SETTINGS_XML"] + + return b, nil +} + +func (b *Builder) run() error { + if err := os.Chdir(baseSpace); err != nil { + return fmt.Errorf("Chdir to baseSpace(%s) failed:%v", baseSpace, err) + } + + if err := b.gitPull(); err != nil { + return err + } + + if err := b.gitReset(); err != nil { + return err + } + + if err := b.setM2SettingXML(); err != nil { + return err + } + + if err := b.build(); err != nil { + return err + } + + // if err := b.handleArtifacts(); err != nil { + // return err + // } + + // err = b.doPush(b.Image) + // if err != nil { + // return + // } + return nil +} + +func (b *Builder) setM2SettingXML() error { + var command = []string{"cp", "/usr/share/maven/conf/settings.xml", "/root/.m2/settings.xml"} + if _, err := (CMD{Command: command}).Run(); err != nil { + fmt.Println("copy settings.xml failed:", err) + return err + } + if b.M2SettingXML != "" { + command = []string{"echo", b.M2SettingXML, ">", "/root/.m2/setting.xml"} + if _, err := (CMD{Command: command}).Run(); err != nil { + fmt.Println("write setting to .m2/settings.xml failed:", err) + return err + } + } + return nil +} + +func (b *Builder) build() error { + var command = strings.Fields(b.Goals) + + if len(command) == 0 { + command = append(command, "mvn", "package") + } + + if command[0] != "mvn" { + command = append([]string{"mvn"}, command...) + } + + command = append(command, "-f", b.PomPath) + + cwd, _ := os.Getwd() + if _, err := (CMD{Command: command, WorkDir: filepath.Join(cwd, b.projectName)}).Run(); err != nil { + fmt.Println("Run mvn goals failed:", err) + return err + } + fmt.Println("Run mvn goals succeed.") + + if _, err := (CMD{command, filepath.Join(cwd, b.projectName),b.ExtCommand}).ExecCommand(); err != nil { + fmt.Println("Run extCommand failed:", err) + return err + } + fmt.Println("Run extCommand succeed.") + return nil +} + +func (b *Builder) gitPull() error { + var command = []string{"git", "clone", "--recurse-submodules", b.GitCloneURL, b.projectName} + if _, err := (CMD{Command: command}).Run(); err != nil { + fmt.Println("Clone project failed:", err) + return err + } + fmt.Println("Clone project", b.GitCloneURL, "succeed.") + return nil +} + +func (b *Builder) gitReset() error { + cwd, _ := os.Getwd() + var command = []string{"git", "checkout", b.GitRef, "--"} + if _, err := (CMD{Command: command, WorkDir: filepath.Join(cwd, b.projectName)}).Run(); err != nil { + fmt.Println("Switch to commit", b.GitRef, "failed:", err) + return err + } + fmt.Println("Switch to", b.GitRef, "succeed.") + return nil +} + +type CMD struct { + Command []string // cmd with args + WorkDir string + ExtCommand string +} + +func (c CMD) ExecCommand() (string, error){ + if(c.ExtCommand == ""){ + return "",nil + } + fmt.Printf("exec:", c.ExtCommand) + cmd := exec.Command("/bin/bash", "-c", c.ExtCommand) + if c.WorkDir != "" { + cmd.Dir = c.WorkDir + } + var out bytes.Buffer + + cmd.Stdout = &out + err := cmd.Run() + if err != nil { + fmt.Println("exec:", c.ExtCommand, "\nFailed:", err) + } + fmt.Printf(out.String()) + return out.String(),err +} + +func (c CMD) Run() (string, error) { + fmt.Println("Run CMD: ", strings.Join(c.Command, " ")) + + cmd := exec.Command(c.Command[0], c.Command[1:]...) + if c.WorkDir != "" { + cmd.Dir = c.WorkDir + } + + data, err := cmd.CombinedOutput() + result := string(data) + if len(result) > 0 { + fmt.Println(result) + } + + return result, err +} \ No newline at end of file diff --git a/java/build/maven_docker/main.go b/java/build/maven_docker/main.go new file mode 100644 index 0000000..267551e --- /dev/null +++ b/java/build/maven_docker/main.go @@ -0,0 +1,38 @@ +package main + +import ( + "fmt" + "os" +) + +var envList = []string{ + "GIT_CLONE_URL", + "GIT_REF", + "_WORKFLOW_GIT_CLONE_URL", + "_WORKFLOW_GIT_REF", + + "GOALS", + "POM_PATH", + "EXT_COMMAND", + "M2_SETTINGS_XML", +} + +func main() { + envs := make(map[string]string) + for _, envName := range envList { + envs[envName] = os.Getenv(envName) + } + + builder, err := NewBuilder(envs) + if err != nil { + fmt.Println("BUILDER FAILED: ", err) + os.Exit(1) + } + + if err := builder.run(); err != nil { + fmt.Println("BUILD FAILED", err) + os.Exit(1) + } else { + fmt.Println("BUILD SUCCEED") + } +}