mirror of
https://github.com/thegeeklab/wp-docker-buildx.git
synced 2024-11-22 00:00:40 +00:00
Robert Kaussow
a2bc0869af
BREAKING CHANGE: The type of the `build_args` property was changed from `list` to `map` to support the use of secrets for certain build arguments. During this refactoring, the `build_args_from_env` behavior was also changed to achieve the intended behavior. Environment variable names passed to this list will be used as build arguments if the environment variable is set.
250 lines
6.0 KiB
Go
250 lines
6.0 KiB
Go
package docker
|
|
|
|
import (
|
|
"fmt"
|
|
"maps"
|
|
"os"
|
|
"strings"
|
|
"time"
|
|
|
|
plugin_exec "github.com/thegeeklab/wp-plugin-go/v3/exec"
|
|
"github.com/urfave/cli/v2"
|
|
)
|
|
|
|
const dockerBin = "/usr/local/bin/docker"
|
|
|
|
// Login defines Docker login parameters.
|
|
type Registry struct {
|
|
Address string // Docker registry address
|
|
Username string // Docker registry username
|
|
Password string // Docker registry password
|
|
Email string // Docker registry email
|
|
Config string // Docker Auth Config
|
|
}
|
|
|
|
// Build defines Docker build parameters.
|
|
type Build struct {
|
|
Ref string // Git commit ref
|
|
Branch string // Git repository branch
|
|
Containerfile string // Docker build Containerfile
|
|
Context string // Docker build context
|
|
TagsAuto bool // Docker build auto tag
|
|
TagsSuffix string // Docker build tags with suffix
|
|
Tags cli.StringSlice // Docker build tags
|
|
ExtraTags cli.StringSlice // Docker build tags including registry
|
|
Platforms cli.StringSlice // Docker build target platforms
|
|
Args map[string]string // Docker build args
|
|
ArgsEnv cli.StringSlice // Docker build args from env
|
|
Target string // Docker build target
|
|
Pull bool // Docker build pull
|
|
CacheFrom []string // Docker build cache-from
|
|
CacheTo string // Docker build cache-to
|
|
Compress bool // Docker build compress
|
|
Repo string // Docker build repository
|
|
NoCache bool // Docker build no-cache
|
|
AddHost cli.StringSlice // Docker build add-host
|
|
Quiet bool // Docker build quiet
|
|
Output string // Docker build output folder
|
|
NamedContext cli.StringSlice // Docker build named context
|
|
Labels cli.StringSlice // Docker build labels
|
|
Provenance string // Docker build provenance attestation
|
|
SBOM string // Docker build sbom attestation
|
|
Secrets []string // Docker build secrets
|
|
Dryrun bool // Docker build dryrun
|
|
}
|
|
|
|
// helper function to create the docker login command.
|
|
func (r *Registry) Login() *plugin_exec.Cmd {
|
|
args := []string{
|
|
"login",
|
|
"-u", r.Username,
|
|
"-p", r.Password,
|
|
}
|
|
|
|
if r.Email != "" {
|
|
args = append(args, "-e", r.Email)
|
|
}
|
|
|
|
args = append(args, r.Address)
|
|
|
|
cmd := plugin_exec.Command(dockerBin, args...)
|
|
cmd.Stdout = os.Stdout
|
|
cmd.Stderr = os.Stderr
|
|
|
|
return cmd
|
|
}
|
|
|
|
// helper function to create the docker info command.
|
|
func Version() *plugin_exec.Cmd {
|
|
cmd := plugin_exec.Command(dockerBin, "version")
|
|
cmd.Stdout = os.Stdout
|
|
cmd.Stderr = os.Stderr
|
|
|
|
return cmd
|
|
}
|
|
|
|
// helper function to create the docker info command.
|
|
func Info() *plugin_exec.Cmd {
|
|
cmd := plugin_exec.Command(dockerBin, "info")
|
|
cmd.Stdout = os.Stdout
|
|
cmd.Stderr = os.Stderr
|
|
|
|
return cmd
|
|
}
|
|
|
|
// helper function to create the docker build command.
|
|
func (b *Build) Run() *plugin_exec.Cmd {
|
|
args := []string{
|
|
"buildx",
|
|
"build",
|
|
"--rm=true",
|
|
"-f", b.Containerfile,
|
|
}
|
|
|
|
defaultBuildArgs := map[string]string{
|
|
"DOCKER_IMAGE_CREATED": time.Now().Format(time.RFC3339),
|
|
}
|
|
|
|
maps.Copy(b.Args, defaultBuildArgs)
|
|
|
|
args = append(args, b.Context)
|
|
if !b.Dryrun && b.Output == "" && len(b.Tags.Value()) > 0 {
|
|
args = append(args, "--push")
|
|
}
|
|
|
|
if b.Compress {
|
|
args = append(args, "--compress")
|
|
}
|
|
|
|
if b.Pull {
|
|
args = append(args, "--pull=true")
|
|
}
|
|
|
|
if b.NoCache {
|
|
args = append(args, "--no-cache")
|
|
}
|
|
|
|
for _, arg := range b.CacheFrom {
|
|
args = append(args, "--cache-from", arg)
|
|
}
|
|
|
|
if b.CacheTo != "" {
|
|
args = append(args, "--cache-to", b.CacheTo)
|
|
}
|
|
|
|
for _, arg := range b.ArgsEnv.Value() {
|
|
b.addArgFromEnv(arg)
|
|
}
|
|
|
|
for key, value := range b.Args {
|
|
args = append(args, "--build-arg", fmt.Sprintf("%s=%s", key, value))
|
|
}
|
|
|
|
for _, host := range b.AddHost.Value() {
|
|
args = append(args, "--add-host", host)
|
|
}
|
|
|
|
if b.Target != "" {
|
|
args = append(args, "--target", b.Target)
|
|
}
|
|
|
|
if b.Quiet {
|
|
args = append(args, "--quiet")
|
|
}
|
|
|
|
if b.Output != "" {
|
|
args = append(args, "--output", b.Output)
|
|
}
|
|
|
|
for _, arg := range b.NamedContext.Value() {
|
|
args = append(args, "--build-context", arg)
|
|
}
|
|
|
|
if len(b.Platforms.Value()) > 0 {
|
|
args = append(args, "--platform", strings.Join(b.Platforms.Value(), ","))
|
|
}
|
|
|
|
for _, arg := range b.Tags.Value() {
|
|
args = append(args, "-t", fmt.Sprintf("%s:%s", b.Repo, arg))
|
|
}
|
|
|
|
for _, arg := range b.ExtraTags.Value() {
|
|
args = append(args, "-t", arg)
|
|
}
|
|
|
|
for _, arg := range b.Labels.Value() {
|
|
args = append(args, "--label", arg)
|
|
}
|
|
|
|
if b.Provenance != "" {
|
|
args = append(args, "--provenance", b.Provenance)
|
|
}
|
|
|
|
if b.SBOM != "" {
|
|
args = append(args, "--sbom", b.SBOM)
|
|
}
|
|
|
|
for _, secret := range b.Secrets {
|
|
args = append(args, "--secret", secret)
|
|
}
|
|
|
|
cmd := plugin_exec.Command(dockerBin, args...)
|
|
cmd.Stdout = os.Stdout
|
|
cmd.Stderr = os.Stderr
|
|
|
|
return cmd
|
|
}
|
|
|
|
// helper function to add proxy values from the environment.
|
|
func (b *Build) AddProxyBuildArgs() {
|
|
b.addProxyValue("http_proxy")
|
|
b.addProxyValue("https_proxy")
|
|
b.addProxyValue("no_proxy")
|
|
}
|
|
|
|
// helper function to add the upper and lower case version of a proxy value.
|
|
func (b *Build) addProxyValue(key string) {
|
|
value := b.getProxyValue(key)
|
|
|
|
if value != "" && !b.hasProxyBuildArg(key) {
|
|
b.Args[key] = value
|
|
b.Args[strings.ToUpper(key)] = value
|
|
}
|
|
}
|
|
|
|
func (b *Build) addArgFromEnv(key string) {
|
|
if value, ok := b.Args[key]; ok && value != "" {
|
|
return
|
|
}
|
|
|
|
if value, ok := os.LookupEnv(key); ok && value != "" {
|
|
b.Args[key] = value
|
|
}
|
|
}
|
|
|
|
// helper function to get a proxy value from the environment.
|
|
//
|
|
// assumes that the upper and lower case versions of are the same.
|
|
func (b *Build) getProxyValue(key string) string {
|
|
value := os.Getenv(key)
|
|
|
|
if value != "" {
|
|
return value
|
|
}
|
|
|
|
return os.Getenv(strings.ToUpper(key))
|
|
}
|
|
|
|
// helper function that looks to see if a proxy value was set in the build args.
|
|
func (b *Build) hasProxyBuildArg(key string) bool {
|
|
if _, ok := b.Args[key]; ok {
|
|
return true
|
|
}
|
|
|
|
if _, ok := b.Args[strings.ToUpper(key)]; ok {
|
|
return true
|
|
}
|
|
|
|
return false
|
|
}
|