From 54b0c1d9e0bfa537a2e068906d2689f7a3bcf88b Mon Sep 17 00:00:00 2001 From: Brad Rydzewski Date: Tue, 27 Oct 2015 17:53:51 -0700 Subject: [PATCH] enables multi-tag build and publish --- main.go | 69 +++++++++++++++++++++++++++++++++++--------------------- types.go | 45 ++++++++++++++++++++++++++++++++++++ 2 files changed, 88 insertions(+), 26 deletions(-) create mode 100644 types.go diff --git a/main.go b/main.go index d854ffc..d93f2ff 100644 --- a/main.go +++ b/main.go @@ -12,19 +12,18 @@ import ( ) type Docker struct { - Storage string `json:"storage_driver"` - Registry string `json:"registry"` - Insecure bool `json:"insecure"` - Username string `json:"username"` - Password string `json:"password"` - Email string `json:"email"` - Auth string `json:"auth"` - Repo string `json:"repo"` - Tag string `json:"tag"` - File string `json:"file"` - // see more here https://docs.docker.com/reference/commandline/build/ - Context string `json:"context"` - Dns []string `json:"dns"` + Storage string `json:"storage_driver"` + Registry string `json:"registry"` + Insecure bool `json:"insecure"` + Username string `json:"username"` + Password string `json:"password"` + Email string `json:"email"` + Auth string `json:"auth"` + Repo string `json:"repo"` + Tag StrSlice `json:"tag"` + File string `json:"file"` + Context string `json:"context"` + Dns []string `json:"dns"` } func main() { @@ -57,10 +56,9 @@ func main() { vargs.Context = "." } // Set the Tag value - if len(vargs.Tag) == 0 { - vargs.Tag = "latest" + if vargs.Tag.Len() == 0 { + vargs.Tag = StrSlice{[]string{"latest"}} } - vargs.Repo = fmt.Sprintf("%s:%s", vargs.Repo, vargs.Tag) go func() { args := []string{"-d"} @@ -128,7 +126,8 @@ func main() { cmd.Run() // Build the container - cmd = exec.Command("/usr/bin/docker", "build", "--pull=true", "--rm=true", "-f", vargs.File, "-t", vargs.Repo, vargs.Context) + name := fmt.Sprintf("%s:%s", vargs.Repo, vargs.Tag.Slice()[0]) + cmd = exec.Command("/usr/bin/docker", "build", "--pull=true", "--rm=true", "-f", vargs.File, "-t", name, vargs.Context) cmd.Dir = workspace.Path cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr @@ -138,16 +137,34 @@ func main() { os.Exit(1) } - // Push the container - cmd = exec.Command("/usr/bin/docker", "push", vargs.Repo) - cmd.Dir = workspace.Path - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr - trace(cmd) - err = cmd.Run() - if err != nil { - os.Exit(1) + // Creates image tags + for _, tag := range vargs.Tag.Slice()[1:] { + name_ := fmt.Sprintf("%s:%s", vargs.Repo, tag) + cmd = exec.Command("/usr/bin/docker", "tag", name, name_) + cmd.Dir = workspace.Path + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + trace(cmd) + err = cmd.Run() + if err != nil { + os.Exit(1) + } } + + // Push the image and tags to the registry + for _, tag := range vargs.Tag.Slice() { + name_ := fmt.Sprintf("%s:%s", vargs.Repo, tag) + cmd = exec.Command("/usr/bin/docker", "push", name_) + cmd.Dir = workspace.Path + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + trace(cmd) + err = cmd.Run() + if err != nil { + os.Exit(1) + } + } + } // Trace writes each command to standard error (preceded by a ‘$ ’) before it diff --git a/types.go b/types.go new file mode 100644 index 0000000..7831e0c --- /dev/null +++ b/types.go @@ -0,0 +1,45 @@ +package main + +import "encoding/json" + +// StrSlice representes a string or an array of strings. +// We need to override the json decoder to accept both options. +type StrSlice struct { + parts []string +} + +// UnmarshalJSON decodes the byte slice whether it's a string or an array of strings. +// This method is needed to implement json.Unmarshaler. +func (e *StrSlice) UnmarshalJSON(b []byte) error { + if len(b) == 0 { + return nil + } + + p := make([]string, 0, 1) + if err := json.Unmarshal(b, &p); err != nil { + var s string + if err := json.Unmarshal(b, &s); err != nil { + return err + } + p = append(p, s) + } + + e.parts = p + return nil +} + +// Len returns the number of parts of the StrSlice. +func (e *StrSlice) Len() int { + if e == nil { + return 0 + } + return len(e.parts) +} + +// Slice gets the parts of the StrSlice as a Slice of string. +func (e *StrSlice) Slice() []string { + if e == nil { + return nil + } + return e.parts +}