Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

增加maven docker:build的支持 #7

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions java/build/maven_docker/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
FROM golang:1.10-alpine as builder

MAINTAINER [email protected]
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"}\
]\
}'
24 changes: 24 additions & 0 deletions java/build/maven_docker/README.md
Original file line number Diff line number Diff line change
@@ -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: <https://github.com/tencentyun/workflow-components/tree/master/java/build/maven>

### 构建:

`docker build -t hub.tencentyun.com/tencenthub/java_build_maven:latest .`
205 changes: 205 additions & 0 deletions java/build/maven_docker/builder.go
Original file line number Diff line number Diff line change
@@ -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
}
38 changes: 38 additions & 0 deletions java/build/maven_docker/main.go
Original file line number Diff line number Diff line change
@@ -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")
}
}