0
0
mirror of https://github.com/thegeeklab/wp-docker-buildx.git synced 2024-11-22 00:00:40 +00:00

docs: hide system flags and refactor generator (#169)

This commit is contained in:
Robert Kaussow 2024-05-05 13:03:50 +02:00 committed by GitHub
parent 43c2e2074c
commit 77beefbc24
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
17 changed files with 483 additions and 498 deletions

View File

@ -19,7 +19,6 @@ GOLANGCI_LINT_PACKAGE ?= github.com/golangci/golangci-lint/cmd/golangci-lint@$(G
XGO_PACKAGE ?= src.techknowlogick.com/xgo@latest XGO_PACKAGE ?= src.techknowlogick.com/xgo@latest
GOTESTSUM_PACKAGE ?= gotest.tools/gotestsum@latest GOTESTSUM_PACKAGE ?= gotest.tools/gotestsum@latest
GENERATE ?=
XGO_VERSION := go-1.22.x XGO_VERSION := go-1.22.x
XGO_TARGETS ?= linux/amd64,linux/arm64 XGO_TARGETS ?= linux/amd64,linux/arm64
@ -65,11 +64,7 @@ lint: golangci-lint
.PHONY: generate .PHONY: generate
generate: generate:
$(GO) generate $(GENERATE) $(GO) generate $(PACKAGES)
.PHONY: generate-docs
generate-docs:
$(GO) generate ./cmd/$(EXECUTABLE)/flags.go
.PHONY: test .PHONY: test
test: test:

View File

@ -1,58 +0,0 @@
//go:build generate
// +build generate
package main
import (
"bytes"
"embed"
"fmt"
"os"
"text/template"
"github.com/thegeeklab/wp-docker-buildx/plugin"
"github.com/thegeeklab/wp-plugin-go/docs"
wp "github.com/thegeeklab/wp-plugin-go/plugin"
wp_template "github.com/thegeeklab/wp-plugin-go/template"
"github.com/urfave/cli/v2"
)
//go:embed templates/docs-data.yaml.tmpl
var yamlTemplate embed.FS
func main() {
settings := &plugin.Settings{}
app := &cli.App{
Flags: settingsFlags(settings, wp.FlagsPluginCategory),
}
out, err := toYAML(app)
if err != nil {
panic(err)
}
fi, err := os.Create("../../docs/data/data-raw.yaml")
if err != nil {
panic(err)
}
defer fi.Close()
if _, err := fi.WriteString(out); err != nil {
panic(err)
}
}
func toYAML(app *cli.App) (string, error) {
var w bytes.Buffer
yamlTmpl, err := template.New("docs").Funcs(wp_template.LoadFuncMap()).ParseFS(yamlTemplate, "templates/docs-data.yaml.tmpl")
if err != nil {
fmt.Println(yamlTmpl)
return "", err
}
if err := yamlTmpl.ExecuteTemplate(&w, "docs-data.yaml.tmpl", docs.GetTemplateData(app)); err != nil {
return "", err
}
return w.String(), nil
}

View File

@ -1,345 +0,0 @@
package main
import (
"github.com/thegeeklab/wp-docker-buildx/plugin"
"github.com/thegeeklab/wp-plugin-go/types"
"github.com/urfave/cli/v2"
)
// settingsFlags has the cli.Flags for the plugin.Settings.
//
//nolint:maintidx
//go:generate go run docs.go flags.go
func settingsFlags(settings *plugin.Settings, category string) []cli.Flag {
return []cli.Flag{
&cli.BoolFlag{
Name: "dry-run",
EnvVars: []string{"PLUGIN_DRY_RUN"},
Usage: "disable docker push",
Destination: &settings.Dryrun,
Category: category,
},
&cli.StringFlag{
Name: "daemon.mirror",
EnvVars: []string{"PLUGIN_MIRROR", "DOCKER_PLUGIN_MIRROR"},
Usage: "registry mirror to pull images",
Destination: &settings.Daemon.Mirror,
DefaultText: "$DOCKER_PLUGIN_MIRROR",
Category: category,
},
&cli.StringFlag{
Name: "daemon.storage-driver",
EnvVars: []string{"PLUGIN_STORAGE_DRIVER"},
Usage: "docker daemon storage driver",
Destination: &settings.Daemon.StorageDriver,
Category: category,
},
&cli.StringFlag{
Name: "daemon.storage-path",
EnvVars: []string{"PLUGIN_STORAGE_PATH"},
Usage: "docker daemon storage path",
Value: "/var/lib/docker",
Destination: &settings.Daemon.StoragePath,
Category: category,
},
&cli.StringFlag{
Name: "daemon.bip",
EnvVars: []string{"PLUGIN_BIP"},
Usage: "allow the docker daemon to bride IP address",
Destination: &settings.Daemon.Bip,
Category: category,
},
&cli.StringFlag{
Name: "daemon.mtu",
EnvVars: []string{"PLUGIN_MTU"},
Usage: "docker daemon custom MTU setting",
Destination: &settings.Daemon.MTU,
Category: category,
},
&cli.StringSliceFlag{
Name: "daemon.dns",
EnvVars: []string{"PLUGIN_CUSTOM_DNS"},
Usage: "custom docker daemon DNS server",
Destination: &settings.Daemon.DNS,
Category: category,
},
&cli.StringSliceFlag{
Name: "daemon.dns-search",
EnvVars: []string{"PLUGIN_CUSTOM_DNS_SEARCH"},
Usage: "custom docker daemon DNS search domain",
Destination: &settings.Daemon.DNSSearch,
Category: category,
},
&cli.BoolFlag{
Name: "daemon.insecure",
EnvVars: []string{"PLUGIN_INSECURE"},
Usage: "allow the docker daemon to use insecure registries",
Value: false,
Destination: &settings.Daemon.Insecure,
Category: category,
},
&cli.BoolFlag{
Name: "daemon.ipv6",
EnvVars: []string{"PLUGIN_IPV6"},
Usage: "enable docker daemon IPv6 support",
Value: false,
Destination: &settings.Daemon.IPv6,
Category: category,
},
&cli.BoolFlag{
Name: "daemon.experimental",
EnvVars: []string{"PLUGIN_EXPERIMENTAL"},
Usage: "enable docker daemon experimental mode",
Value: false,
Destination: &settings.Daemon.Experimental,
Category: category,
},
&cli.BoolFlag{
Name: "daemon.debug",
EnvVars: []string{"PLUGIN_DEBUG"},
Usage: "enable verbose debug mode for the docker daemon",
Value: false,
Destination: &settings.Daemon.Debug,
Category: category,
},
&cli.BoolFlag{
Name: "daemon.off",
EnvVars: []string{"PLUGIN_DAEMON_OFF"},
Usage: "disable the startup of the docker daemon",
Value: false,
Destination: &settings.Daemon.Disabled,
Category: category,
},
&cli.StringFlag{
Name: "daemon.buildkit-config",
EnvVars: []string{"PLUGIN_BUILDKIT_CONFIG"},
Usage: "content of the docker buildkit toml config",
Destination: &settings.Daemon.BuildkitConfig,
Category: category,
},
&cli.StringFlag{
Name: "daemon.max-concurrent-uploads",
EnvVars: []string{"PLUGIN_MAX_CONCURRENT_UPLOADS"},
Usage: "max concurrent uploads for each push",
Destination: &settings.Daemon.MaxConcurrentUploads,
Category: category,
},
&cli.StringFlag{
Name: "containerfile",
EnvVars: []string{"PLUGIN_CONTAINERFILE"},
Usage: "containerfile to use for the image build",
Value: "Containerfile",
Destination: &settings.Build.Containerfile,
Category: category,
},
&cli.StringFlag{
Name: "context",
EnvVars: []string{"PLUGIN_CONTEXT"},
Usage: "path of the build context",
Value: ".",
Destination: &settings.Build.Context,
Category: category,
},
&cli.StringSliceFlag{
Name: "named-context",
EnvVars: []string{"PLUGIN_NAMED_CONTEXT"},
Usage: "additional named build context",
Destination: &settings.Build.NamedContext,
Category: category,
},
&cli.StringSliceFlag{
Name: "tags",
EnvVars: []string{"PLUGIN_TAGS", "PLUGIN_TAG"},
Usage: "repository tags to use for the image",
FilePath: ".tags",
Destination: &settings.Build.Tags,
Category: category,
},
&cli.BoolFlag{
Name: "tags.auto",
EnvVars: []string{"PLUGIN_AUTO_TAG", "PLUGIN_DEFAULT_TAGS"},
Usage: "generate tag names automatically based on git branch and git tag",
Value: false,
Destination: &settings.Build.TagsAuto,
Category: category,
},
&cli.StringFlag{
Name: "tags.suffix",
EnvVars: []string{"PLUGIN_AUTO_TAG_SUFFIX", "PLUGIN_DEFAULT_SUFFIX"},
Usage: "generate tag names with the given suffix",
Destination: &settings.Build.TagsSuffix,
Category: category,
},
&cli.StringSliceFlag{
Name: "extra.tags",
EnvVars: []string{"PLUGIN_EXTRA_TAGS"},
Usage: "additional tags to use for the image including registry",
FilePath: ".extratags",
Destination: &settings.Build.ExtraTags,
Category: category,
},
&cli.StringSliceFlag{
Name: "args",
EnvVars: []string{"PLUGIN_BUILD_ARGS"},
Usage: "custom build arguments for the build",
Destination: &settings.Build.Args,
Category: category,
},
&cli.StringSliceFlag{
Name: "args-from-env",
EnvVars: []string{"PLUGIN_BUILD_ARGS_FROM_ENV"},
Usage: "forward environment variables as custom arguments to the build",
Destination: &settings.Build.ArgsEnv,
Category: category,
},
&cli.BoolFlag{
Name: "quiet",
EnvVars: []string{"PLUGIN_QUIET"},
Usage: "enable suppression of the build output",
Value: false,
Destination: &settings.Build.Quiet,
Category: category,
},
&cli.StringFlag{
Name: "output",
EnvVars: []string{"PLUGIN_OUTPUT"},
Usage: "export action for the build result",
Destination: &settings.Build.Output,
Category: category,
},
&cli.StringFlag{
Name: "target",
EnvVars: []string{"PLUGIN_TARGET"},
Usage: "build target to use",
Destination: &settings.Build.Target,
Category: category,
},
&cli.GenericFlag{
Name: "cache-from",
EnvVars: []string{"PLUGIN_CACHE_FROM"},
Usage: "images to consider as cache sources",
Value: &types.StringSliceFlag{},
Category: category,
},
&cli.StringFlag{
Name: "cache-to",
EnvVars: []string{"PLUGIN_CACHE_TO"},
Usage: "cache destination for the build cache",
Destination: &settings.Build.CacheTo,
Category: category,
},
&cli.BoolFlag{
Name: "pull-image",
EnvVars: []string{"PLUGIN_PULL_IMAGE"},
Usage: "enforce to pull base image at build time",
Value: true,
Destination: &settings.Build.Pull,
Category: category,
},
&cli.BoolFlag{
Name: "compress",
EnvVars: []string{"PLUGIN_COMPRESS"},
Usage: "enable compression of the build context using gzip",
Value: false,
Destination: &settings.Build.Compress,
Category: category,
},
&cli.StringFlag{
Name: "repo",
EnvVars: []string{"PLUGIN_REPO"},
Usage: "repository name for the image",
Destination: &settings.Build.Repo,
Category: category,
},
&cli.StringFlag{
Name: "docker.registry",
EnvVars: []string{"PLUGIN_REGISTRY", "DOCKER_REGISTRY"},
Usage: "docker registry to authenticate with",
Value: "https://index.docker.io/v1/",
Destination: &settings.Login.Registry,
Category: category,
},
&cli.StringFlag{
Name: "docker.username",
EnvVars: []string{"PLUGIN_USERNAME", "DOCKER_USERNAME"},
Usage: "username for registry authentication",
Destination: &settings.Login.Username,
DefaultText: "$DOCKER_USERNAME",
Category: category,
},
&cli.StringFlag{
Name: "docker.password",
EnvVars: []string{"PLUGIN_PASSWORD", "DOCKER_PASSWORD"},
Usage: "password for registry authentication",
Destination: &settings.Login.Password,
DefaultText: "$DOCKER_PASSWORD",
Category: category,
},
&cli.StringFlag{
Name: "docker.email",
EnvVars: []string{"PLUGIN_EMAIL", "DOCKER_EMAIL"},
Usage: "email address for registry authentication",
Destination: &settings.Login.Email,
DefaultText: "$DOCKER_EMAIL",
Category: category,
},
&cli.StringFlag{
Name: "docker.config",
EnvVars: []string{"PLUGIN_CONFIG", "DOCKER_PLUGIN_CONFIG"},
Usage: "content of the docker daemon json config",
Destination: &settings.Login.Config,
DefaultText: "$DOCKER_PLUGIN_CONFIG",
Category: category,
},
&cli.BoolFlag{
Name: "no-cache",
EnvVars: []string{"PLUGIN_NO_CACHE"},
Usage: "disable the usage of cached intermediate containers",
Value: false,
Destination: &settings.Build.NoCache,
Category: category,
},
&cli.StringSliceFlag{
Name: "add-host",
EnvVars: []string{"PLUGIN_ADD_HOST"},
Usage: "additional `host:ip` mapping",
Destination: &settings.Build.AddHost,
Category: category,
},
&cli.StringSliceFlag{
Name: "platforms",
EnvVars: []string{"PLUGIN_PLATFORMS"},
Usage: "target platform for build",
Destination: &settings.Build.Platforms,
Category: category,
},
&cli.StringSliceFlag{
Name: "labels",
EnvVars: []string{"PLUGIN_LABELS"},
Usage: "labels to add to image",
Destination: &settings.Build.Labels,
Category: category,
},
&cli.StringFlag{
Name: "provenance",
EnvVars: []string{"PLUGIN_PROVENANCE"},
Usage: "generates provenance attestation for the build",
Destination: &settings.Build.Provenance,
Category: category,
},
&cli.StringFlag{
Name: "sbom",
EnvVars: []string{"PLUGIN_SBOM"},
Usage: "generates SBOM attestation for the build",
Destination: &settings.Build.SBOM,
Category: category,
},
&cli.GenericFlag{
Name: "secrets",
EnvVars: []string{"PLUGIN_SECRETS"},
Usage: "exposes secrets to the build",
Value: &types.StringSliceFlag{},
Category: category,
},
}
}

View File

@ -1,11 +1,7 @@
package main package main
import ( import (
"fmt"
"github.com/thegeeklab/wp-docker-buildx/plugin" "github.com/thegeeklab/wp-docker-buildx/plugin"
wp "github.com/thegeeklab/wp-plugin-go/plugin"
) )
//nolint:gochecknoglobals //nolint:gochecknoglobals
@ -15,14 +11,5 @@ var (
) )
func main() { func main() {
settings := &plugin.Settings{} plugin.New(nil, BuildVersion, BuildDate).Run()
options := wp.Options{
Name: "wp-docker-buildx",
Description: "Build multiarch OCI images with buildx",
Version: BuildVersion,
VersionMetadata: fmt.Sprintf("date=%s", BuildDate),
Flags: settingsFlags(settings, wp.FlagsPluginCategory),
}
plugin.New(options, settings).Run()
} }

View File

@ -1,18 +0,0 @@
---
{{- if .GlobalArgs }}
properties:
{{- range $v := .GlobalArgs }}
- name: {{ $v.Name }}
{{- with $v.Description }}
description: |
{{ . | ToSentence }}
{{- end }}
{{- with $v.Type }}
type: {{ . }}
{{- end }}
{{- with $v.Default }}
defaultValue: {{ . }}
{{- end }}
required: {{ default false $v.Required }}
{{ end -}}
{{ end -}}

View File

@ -104,7 +104,7 @@ docker run --rm \
-e PLUGIN_TAG=latest \ -e PLUGIN_TAG=latest \
-e PLUGIN_REPO=octocat/hello-world \ -e PLUGIN_REPO=octocat/hello-world \
-e CI_COMMIT_SHA=00000000 \ -e CI_COMMIT_SHA=00000000 \
-v $(pwd):/build:z \ -v $(pwd)/testdata:/build:z \
-w /build \ -w /build \
--privileged \ --privileged \
thegeeklab/wp-docker-buildx --dry-run thegeeklab/wp-docker-buildx --dry-run

View File

@ -179,6 +179,13 @@ properties:
defaultValue: false defaultValue: false
required: false required: false
- name: insecure_skip_verify
description: |
Skip SSL verification.
type: bool
defaultValue: false
required: false
- name: ipv6 - name: ipv6
description: | description: |
Enable docker daemon IPv6 support. Enable docker daemon IPv6 support.
@ -192,6 +199,13 @@ properties:
type: list type: list
required: false required: false
- name: log_level
description: |
Plugin log level.
type: string
defaultValue: "info"
required: false
- name: max_concurrent_uploads - name: max_concurrent_uploads
description: | description: |
Max concurrent uploads for each push. Max concurrent uploads for each push.

2
go.mod
View File

@ -5,7 +5,7 @@ go 1.22
require ( require (
github.com/cenkalti/backoff/v4 v4.3.0 github.com/cenkalti/backoff/v4 v4.3.0
github.com/rs/zerolog v1.32.0 github.com/rs/zerolog v1.32.0
github.com/thegeeklab/wp-plugin-go v1.7.1 github.com/thegeeklab/wp-plugin-go/v2 v2.0.1
github.com/urfave/cli/v2 v2.27.2 github.com/urfave/cli/v2 v2.27.2
golang.org/x/sys v0.19.0 golang.org/x/sys v0.19.0
) )

4
go.sum
View File

@ -48,8 +48,8 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/thegeeklab/wp-plugin-go v1.7.1 h1:zfR/rfNPuyVhXJu1fsLfp4+Mz2pTf6WwW/mIqw9750I= github.com/thegeeklab/wp-plugin-go/v2 v2.0.1 h1:42kqe5U1x5Ysa9I8tDEhh+tyvfFkfXKvlb3UsigBmN4=
github.com/thegeeklab/wp-plugin-go v1.7.1/go.mod h1:Ixi5plt9tpFGTu6yc/Inm5DcDpp3xPTeohfr86gf2EU= github.com/thegeeklab/wp-plugin-go/v2 v2.0.1/go.mod h1:KRfDolkPSpO7Zx54Y0ofTFA7Cvd+7bHTHzYnYAo9WYg=
github.com/urfave/cli/v2 v2.27.2 h1:6e0H+AkS+zDckwPCUrZkKX38mRaau4nL2uipkJpbkcI= github.com/urfave/cli/v2 v2.27.2 h1:6e0H+AkS+zDckwPCUrZkKX38mRaau4nL2uipkJpbkcI=
github.com/urfave/cli/v2 v2.27.2/go.mod h1:g0+79LmHHATl7DAcHO99smiR/T7uGLw84w8Y42x+4eM= github.com/urfave/cli/v2 v2.27.2/go.mod h1:g0+79LmHHATl7DAcHO99smiR/T7uGLw84w8Y42x+4eM=
github.com/xrash/smetrics v0.0.0-20240312152122-5f08fbb34913 h1:+qGGcbkzsfDQNPPe9UDgpxAWQrhbbBXOYJFQDq/dtJw= github.com/xrash/smetrics v0.0.0-20240312152122-5f08fbb34913 h1:+qGGcbkzsfDQNPPe9UDgpxAWQrhbbBXOYJFQDq/dtJw=

42
internal/docs/main.go Normal file
View File

@ -0,0 +1,42 @@
//go:build generate
// +build generate
package main
import (
"context"
"flag"
"net/http"
"os"
"time"
"github.com/thegeeklab/wp-docker-buildx/plugin"
"github.com/thegeeklab/wp-plugin-go/v2/docs"
wp_template "github.com/thegeeklab/wp-plugin-go/v2/template"
)
func main() {
tmpl := "https://raw.githubusercontent.com/thegeeklab/woodpecker-plugins/main/templates/docs-data.yaml.tmpl"
client := http.Client{
Timeout: 30 * time.Second,
}
p := plugin.New(nil)
out, err := wp_template.Render(context.Background(), client, tmpl, docs.GetTemplateData(p.App))
if err != nil {
panic(err)
}
outputFile := flag.String("output", "", "Output file path")
flag.Parse()
if *outputFile == "" {
panic("no output file specified")
}
err = os.WriteFile(*outputFile, []byte(out), 0o644)
if err != nil {
panic(err)
}
}

View File

@ -6,7 +6,7 @@ import (
"os" "os"
"os/exec" "os/exec"
"github.com/thegeeklab/wp-plugin-go/trace" "github.com/thegeeklab/wp-plugin-go/v2/trace"
) )
func (p Plugin) startCoredns() { func (p Plugin) startCoredns() {

View File

@ -4,7 +4,7 @@ import (
"io" "io"
"os" "os"
"github.com/thegeeklab/wp-plugin-go/trace" "github.com/thegeeklab/wp-plugin-go/v2/trace"
) )
const ( const (
@ -25,7 +25,7 @@ func (p Plugin) startDaemon() {
} }
go func() { go func() {
trace.Cmd(cmd) trace.Cmd(cmd.Cmd)
_ = cmd.Run() _ = cmd.Run()
}() }()
} }

View File

@ -11,7 +11,7 @@ import (
) )
// helper function to create the docker login command. // helper function to create the docker login command.
func commandLogin(login Login) *execabs.Cmd { func commandLogin(login Login) *Cmd {
if login.Email != "" { if login.Email != "" {
return commandLoginEmail(login) return commandLoginEmail(login)
} }
@ -23,12 +23,12 @@ func commandLogin(login Login) *execabs.Cmd {
login.Registry, login.Registry,
} }
return execabs.Command( return &Cmd{
dockerBin, args..., Cmd: execabs.Command(dockerBin, args...),
) }
} }
func commandLoginEmail(login Login) *execabs.Cmd { func commandLoginEmail(login Login) *Cmd {
args := []string{ args := []string{
"login", "login",
"-u", login.Username, "-u", login.Username,
@ -37,22 +37,26 @@ func commandLoginEmail(login Login) *execabs.Cmd {
login.Registry, login.Registry,
} }
return execabs.Command( return &Cmd{
dockerBin, args..., Cmd: execabs.Command(dockerBin, args...),
) }
} }
// helper function to create the docker info command. // helper function to create the docker info command.
func commandVersion() *execabs.Cmd { func commandVersion() *Cmd {
return execabs.Command(dockerBin, "version") return &Cmd{
Cmd: execabs.Command(dockerBin, "version"),
}
} }
// helper function to create the docker info command. // helper function to create the docker info command.
func commandInfo() *execabs.Cmd { func commandInfo() *Cmd {
return execabs.Command(dockerBin, "info") return &Cmd{
Cmd: execabs.Command(dockerBin, "info"),
}
} }
func commandBuilder(daemon Daemon) *execabs.Cmd { func commandBuilder(daemon Daemon) *Cmd {
args := []string{ args := []string{
"buildx", "buildx",
"create", "create",
@ -63,15 +67,19 @@ func commandBuilder(daemon Daemon) *execabs.Cmd {
args = append(args, "--config", buildkitConfig) args = append(args, "--config", buildkitConfig)
} }
return execabs.Command(dockerBin, args...) return &Cmd{
Cmd: execabs.Command(dockerBin, args...),
}
} }
func commandBuildx() *execabs.Cmd { func commandBuildx() *Cmd {
return execabs.Command(dockerBin, "buildx", "ls") return &Cmd{
Cmd: execabs.Command(dockerBin, "buildx", "ls"),
}
} }
// helper function to create the docker build command. // helper function to create the docker build command.
func commandBuild(build Build, dryrun bool) *execabs.Cmd { func commandBuild(build Build, dryrun bool) *Cmd {
args := []string{ args := []string{
"buildx", "buildx",
"build", "build",
@ -164,7 +172,9 @@ func commandBuild(build Build, dryrun bool) *execabs.Cmd {
args = append(args, "--secret", secret) args = append(args, "--secret", secret)
} }
return execabs.Command(dockerBin, args...) return &Cmd{
Cmd: execabs.Command(dockerBin, args...),
}
} }
// helper function to add proxy values from the environment. // helper function to add proxy values from the environment.
@ -211,7 +221,7 @@ func hasProxyBuildArg(build *Build, key string) bool {
} }
// helper function to create the docker daemon command. // helper function to create the docker daemon command.
func commandDaemon(daemon Daemon) *execabs.Cmd { func commandDaemon(daemon Daemon) *Cmd {
args := []string{ args := []string{
"--data-root", daemon.StoragePath, "--data-root", daemon.StoragePath,
"--host=unix:///var/run/docker.sock", "--host=unix:///var/run/docker.sock",
@ -257,5 +267,7 @@ func commandDaemon(daemon Daemon) *execabs.Cmd {
args = append(args, "--max-concurrent-uploads", daemon.MaxConcurrentUploads) args = append(args, "--max-concurrent-uploads", daemon.MaxConcurrentUploads)
} }
return execabs.Command(dockerdBin, args...) return &Cmd{
Cmd: execabs.Command(dockerdBin, args...),
}
} }

View File

@ -10,11 +10,10 @@ import (
"github.com/cenkalti/backoff/v4" "github.com/cenkalti/backoff/v4"
"github.com/rs/zerolog/log" "github.com/rs/zerolog/log"
"github.com/thegeeklab/wp-plugin-go/tag" "github.com/thegeeklab/wp-plugin-go/v2/tag"
"github.com/thegeeklab/wp-plugin-go/trace" "github.com/thegeeklab/wp-plugin-go/v2/trace"
"github.com/thegeeklab/wp-plugin-go/types" "github.com/thegeeklab/wp-plugin-go/v2/types"
"github.com/urfave/cli/v2" "github.com/urfave/cli/v2"
"golang.org/x/sys/execabs"
) )
var ErrTypeAssertionFailed = errors.New("type assertion failed") var ErrTypeAssertionFailed = errors.New("type assertion failed")
@ -79,6 +78,8 @@ func (p *Plugin) Validate() error {
// //
//nolint:gocognit //nolint:gocognit
func (p *Plugin) Execute() error { func (p *Plugin) Execute() error {
batchCmd := make([]*Cmd, 0)
// start the Docker daemon server // start the Docker daemon server
//nolint: nestif //nolint: nestif
if !p.Settings.Daemon.Disabled { if !p.Settings.Daemon.Disabled {
@ -163,7 +164,7 @@ func (p *Plugin) Execute() error {
versionCmd.Stdout = os.Stdout versionCmd.Stdout = os.Stdout
versionCmd.Stderr = os.Stderr versionCmd.Stderr = os.Stderr
trace.Cmd(versionCmd) trace.Cmd(versionCmd.Cmd)
return versionCmd.Run() return versionCmd.Run()
} }
@ -175,19 +176,18 @@ func (p *Plugin) Execute() error {
return err return err
} }
var batchCmd []*execabs.Cmd
batchCmd = append(batchCmd, commandInfo()) // docker info batchCmd = append(batchCmd, commandInfo()) // docker info
batchCmd = append(batchCmd, commandBuilder(p.Settings.Daemon)) batchCmd = append(batchCmd, commandBuilder(p.Settings.Daemon))
batchCmd = append(batchCmd, commandBuildx()) batchCmd = append(batchCmd, commandBuildx())
batchCmd = append(batchCmd, commandBuild(p.Settings.Build, p.Settings.Dryrun)) // docker build batchCmd = append(batchCmd, commandBuild(p.Settings.Build, p.Settings.Dryrun)) // docker build
// execute all commands in batch mode. // execute all commands in batch mode.
for _, cmd := range batchCmd { for _, bc := range batchCmd {
cmd.Stdout = os.Stdout bc.Stdout = os.Stdout
cmd.Stderr = os.Stderr bc.Stderr = os.Stderr
trace.Cmd(cmd) trace.Cmd(bc.Cmd)
err := cmd.Run() err := bc.Run()
if err != nil { if err != nil {
return err return err
} }

View File

@ -1,10 +1,16 @@
package plugin package plugin
import ( import (
wp "github.com/thegeeklab/wp-plugin-go/plugin" "fmt"
wp "github.com/thegeeklab/wp-plugin-go/v2/plugin"
"github.com/thegeeklab/wp-plugin-go/v2/types"
"github.com/urfave/cli/v2" "github.com/urfave/cli/v2"
"golang.org/x/sys/execabs"
) )
//go:generate go run ../internal/docs/main.go -output=../docs/data/data-raw.yaml
// Plugin implements provide the plugin. // Plugin implements provide the plugin.
type Plugin struct { type Plugin struct {
*wp.Plugin *wp.Plugin
@ -77,15 +83,374 @@ type Build struct {
Secrets []string // Docker build secrets Secrets []string // Docker build secrets
} }
func New(options wp.Options, settings *Settings) *Plugin { type Cmd struct {
p := &Plugin{} *execabs.Cmd
Private bool
}
if options.Execute == nil { func New(e wp.ExecuteFunc, build ...string) *Plugin {
options.Execute = p.run p := &Plugin{
Settings: &Settings{},
}
options := wp.Options{
Name: "wp-docker-buildx",
Description: "Build multiarch OCI images with buildx",
Flags: Flags(p.Settings, wp.FlagsPluginCategory),
Execute: p.run,
HideWoodpeckerFlags: true,
}
if len(build) > 0 {
options.Version = build[0]
}
if len(build) > 1 {
options.VersionMetadata = fmt.Sprintf("date=%s", build[1])
}
if e != nil {
options.Execute = e
} }
p.Plugin = wp.New(options) p.Plugin = wp.New(options)
p.Settings = settings
return p return p
} }
// Flags returns a slice of CLI flags for the plugin.
//
//nolint:maintidx
func Flags(settings *Settings, category string) []cli.Flag {
return []cli.Flag{
&cli.BoolFlag{
Name: "dry-run",
EnvVars: []string{"PLUGIN_DRY_RUN"},
Usage: "disable docker push",
Destination: &settings.Dryrun,
Category: category,
},
&cli.StringFlag{
Name: "daemon.mirror",
EnvVars: []string{"PLUGIN_MIRROR", "DOCKER_PLUGIN_MIRROR"},
Usage: "registry mirror to pull images",
Destination: &settings.Daemon.Mirror,
DefaultText: "$DOCKER_PLUGIN_MIRROR",
Category: category,
},
&cli.StringFlag{
Name: "daemon.storage-driver",
EnvVars: []string{"PLUGIN_STORAGE_DRIVER"},
Usage: "docker daemon storage driver",
Destination: &settings.Daemon.StorageDriver,
Category: category,
},
&cli.StringFlag{
Name: "daemon.storage-path",
EnvVars: []string{"PLUGIN_STORAGE_PATH"},
Usage: "docker daemon storage path",
Value: "/var/lib/docker",
Destination: &settings.Daemon.StoragePath,
Category: category,
},
&cli.StringFlag{
Name: "daemon.bip",
EnvVars: []string{"PLUGIN_BIP"},
Usage: "allow the docker daemon to bride IP address",
Destination: &settings.Daemon.Bip,
Category: category,
},
&cli.StringFlag{
Name: "daemon.mtu",
EnvVars: []string{"PLUGIN_MTU"},
Usage: "docker daemon custom MTU setting",
Destination: &settings.Daemon.MTU,
Category: category,
},
&cli.StringSliceFlag{
Name: "daemon.dns",
EnvVars: []string{"PLUGIN_CUSTOM_DNS"},
Usage: "custom docker daemon DNS server",
Destination: &settings.Daemon.DNS,
Category: category,
},
&cli.StringSliceFlag{
Name: "daemon.dns-search",
EnvVars: []string{"PLUGIN_CUSTOM_DNS_SEARCH"},
Usage: "custom docker daemon DNS search domain",
Destination: &settings.Daemon.DNSSearch,
Category: category,
},
&cli.BoolFlag{
Name: "daemon.insecure",
EnvVars: []string{"PLUGIN_INSECURE"},
Usage: "allow the docker daemon to use insecure registries",
Value: false,
Destination: &settings.Daemon.Insecure,
Category: category,
},
&cli.BoolFlag{
Name: "daemon.ipv6",
EnvVars: []string{"PLUGIN_IPV6"},
Usage: "enable docker daemon IPv6 support",
Value: false,
Destination: &settings.Daemon.IPv6,
Category: category,
},
&cli.BoolFlag{
Name: "daemon.experimental",
EnvVars: []string{"PLUGIN_EXPERIMENTAL"},
Usage: "enable docker daemon experimental mode",
Value: false,
Destination: &settings.Daemon.Experimental,
Category: category,
},
&cli.BoolFlag{
Name: "daemon.debug",
EnvVars: []string{"PLUGIN_DEBUG"},
Usage: "enable verbose debug mode for the docker daemon",
Value: false,
Destination: &settings.Daemon.Debug,
Category: category,
},
&cli.BoolFlag{
Name: "daemon.off",
EnvVars: []string{"PLUGIN_DAEMON_OFF"},
Usage: "disable the startup of the docker daemon",
Value: false,
Destination: &settings.Daemon.Disabled,
Category: category,
},
&cli.StringFlag{
Name: "daemon.buildkit-config",
EnvVars: []string{"PLUGIN_BUILDKIT_CONFIG"},
Usage: "content of the docker buildkit toml config",
Destination: &settings.Daemon.BuildkitConfig,
Category: category,
},
&cli.StringFlag{
Name: "daemon.max-concurrent-uploads",
EnvVars: []string{"PLUGIN_MAX_CONCURRENT_UPLOADS"},
Usage: "max concurrent uploads for each push",
Destination: &settings.Daemon.MaxConcurrentUploads,
Category: category,
},
&cli.StringFlag{
Name: "containerfile",
EnvVars: []string{"PLUGIN_CONTAINERFILE"},
Usage: "containerfile to use for the image build",
Value: "Containerfile",
Destination: &settings.Build.Containerfile,
Category: category,
},
&cli.StringFlag{
Name: "context",
EnvVars: []string{"PLUGIN_CONTEXT"},
Usage: "path of the build context",
Value: ".",
Destination: &settings.Build.Context,
Category: category,
},
&cli.StringSliceFlag{
Name: "named-context",
EnvVars: []string{"PLUGIN_NAMED_CONTEXT"},
Usage: "additional named build context",
Destination: &settings.Build.NamedContext,
Category: category,
},
&cli.StringSliceFlag{
Name: "tags",
EnvVars: []string{"PLUGIN_TAGS", "PLUGIN_TAG"},
Usage: "repository tags to use for the image",
FilePath: ".tags",
Destination: &settings.Build.Tags,
Category: category,
},
&cli.BoolFlag{
Name: "tags.auto",
EnvVars: []string{"PLUGIN_AUTO_TAG", "PLUGIN_DEFAULT_TAGS"},
Usage: "generate tag names automatically based on git branch and git tag",
Value: false,
Destination: &settings.Build.TagsAuto,
Category: category,
},
&cli.StringFlag{
Name: "tags.suffix",
EnvVars: []string{"PLUGIN_AUTO_TAG_SUFFIX", "PLUGIN_DEFAULT_SUFFIX"},
Usage: "generate tag names with the given suffix",
Destination: &settings.Build.TagsSuffix,
Category: category,
},
&cli.StringSliceFlag{
Name: "extra.tags",
EnvVars: []string{"PLUGIN_EXTRA_TAGS"},
Usage: "additional tags to use for the image including registry",
FilePath: ".extratags",
Destination: &settings.Build.ExtraTags,
Category: category,
},
&cli.StringSliceFlag{
Name: "args",
EnvVars: []string{"PLUGIN_BUILD_ARGS"},
Usage: "custom build arguments for the build",
Destination: &settings.Build.Args,
Category: category,
},
&cli.StringSliceFlag{
Name: "args-from-env",
EnvVars: []string{"PLUGIN_BUILD_ARGS_FROM_ENV"},
Usage: "forward environment variables as custom arguments to the build",
Destination: &settings.Build.ArgsEnv,
Category: category,
},
&cli.BoolFlag{
Name: "quiet",
EnvVars: []string{"PLUGIN_QUIET"},
Usage: "enable suppression of the build output",
Value: false,
Destination: &settings.Build.Quiet,
Category: category,
},
&cli.StringFlag{
Name: "output",
EnvVars: []string{"PLUGIN_OUTPUT"},
Usage: "export action for the build result",
Destination: &settings.Build.Output,
Category: category,
},
&cli.StringFlag{
Name: "target",
EnvVars: []string{"PLUGIN_TARGET"},
Usage: "build target to use",
Destination: &settings.Build.Target,
Category: category,
},
&cli.GenericFlag{
Name: "cache-from",
EnvVars: []string{"PLUGIN_CACHE_FROM"},
Usage: "images to consider as cache sources",
Value: &types.StringSliceFlag{},
Category: category,
},
&cli.StringFlag{
Name: "cache-to",
EnvVars: []string{"PLUGIN_CACHE_TO"},
Usage: "cache destination for the build cache",
Destination: &settings.Build.CacheTo,
Category: category,
},
&cli.BoolFlag{
Name: "pull-image",
EnvVars: []string{"PLUGIN_PULL_IMAGE"},
Usage: "enforce to pull base image at build time",
Value: true,
Destination: &settings.Build.Pull,
Category: category,
},
&cli.BoolFlag{
Name: "compress",
EnvVars: []string{"PLUGIN_COMPRESS"},
Usage: "enable compression of the build context using gzip",
Value: false,
Destination: &settings.Build.Compress,
Category: category,
},
&cli.StringFlag{
Name: "repo",
EnvVars: []string{"PLUGIN_REPO"},
Usage: "repository name for the image",
Destination: &settings.Build.Repo,
Category: category,
},
&cli.StringFlag{
Name: "docker.registry",
EnvVars: []string{"PLUGIN_REGISTRY", "DOCKER_REGISTRY"},
Usage: "docker registry to authenticate with",
Value: "https://index.docker.io/v1/",
Destination: &settings.Login.Registry,
Category: category,
},
&cli.StringFlag{
Name: "docker.username",
EnvVars: []string{"PLUGIN_USERNAME", "DOCKER_USERNAME"},
Usage: "username for registry authentication",
Destination: &settings.Login.Username,
DefaultText: "$DOCKER_USERNAME",
Category: category,
},
&cli.StringFlag{
Name: "docker.password",
EnvVars: []string{"PLUGIN_PASSWORD", "DOCKER_PASSWORD"},
Usage: "password for registry authentication",
Destination: &settings.Login.Password,
DefaultText: "$DOCKER_PASSWORD",
Category: category,
},
&cli.StringFlag{
Name: "docker.email",
EnvVars: []string{"PLUGIN_EMAIL", "DOCKER_EMAIL"},
Usage: "email address for registry authentication",
Destination: &settings.Login.Email,
DefaultText: "$DOCKER_EMAIL",
Category: category,
},
&cli.StringFlag{
Name: "docker.config",
EnvVars: []string{"PLUGIN_CONFIG", "DOCKER_PLUGIN_CONFIG"},
Usage: "content of the docker daemon json config",
Destination: &settings.Login.Config,
DefaultText: "$DOCKER_PLUGIN_CONFIG",
Category: category,
},
&cli.BoolFlag{
Name: "no-cache",
EnvVars: []string{"PLUGIN_NO_CACHE"},
Usage: "disable the usage of cached intermediate containers",
Value: false,
Destination: &settings.Build.NoCache,
Category: category,
},
&cli.StringSliceFlag{
Name: "add-host",
EnvVars: []string{"PLUGIN_ADD_HOST"},
Usage: "additional `host:ip` mapping",
Destination: &settings.Build.AddHost,
Category: category,
},
&cli.StringSliceFlag{
Name: "platforms",
EnvVars: []string{"PLUGIN_PLATFORMS"},
Usage: "target platform for build",
Destination: &settings.Build.Platforms,
Category: category,
},
&cli.StringSliceFlag{
Name: "labels",
EnvVars: []string{"PLUGIN_LABELS"},
Usage: "labels to add to image",
Destination: &settings.Build.Labels,
Category: category,
},
&cli.StringFlag{
Name: "provenance",
EnvVars: []string{"PLUGIN_PROVENANCE"},
Usage: "generates provenance attestation for the build",
Destination: &settings.Build.Provenance,
Category: category,
},
&cli.StringFlag{
Name: "sbom",
EnvVars: []string{"PLUGIN_SBOM"},
Usage: "generates SBOM attestation for the build",
Destination: &settings.Build.SBOM,
Category: category,
},
&cli.GenericFlag{
Name: "secrets",
EnvVars: []string{"PLUGIN_SECRETS"},
Usage: "exposes secrets to the build",
Value: &types.StringSliceFlag{},
Category: category,
},
}
}

View File

@ -1,15 +1,12 @@
package main package plugin
import ( import (
"context" "context"
"reflect" "reflect"
"testing" "testing"
"github.com/thegeeklab/wp-docker-buildx/plugin"
wp "github.com/thegeeklab/wp-plugin-go/plugin"
) )
func Test_pluginOptions(t *testing.T) { func TestFlags(t *testing.T) {
tests := []struct { tests := []struct {
name string name string
envs map[string]string envs map[string]string
@ -32,14 +29,7 @@ func Test_pluginOptions(t *testing.T) {
t.Setenv(key, value) t.Setenv(key, value)
} }
settings := &plugin.Settings{} got := New(func(_ context.Context) error { return nil })
options := wp.Options{
Name: "wp-docker-buildx",
Flags: settingsFlags(settings, wp.FlagsPluginCategory),
Execute: func(_ context.Context) error { return nil },
}
got := plugin.New(options, settings)
_ = got.App.Run([]string{"wp-docker-buildx"}) _ = got.App.Run([]string{"wp-docker-buildx"})
_ = got.FlagsFromContext() _ = got.FlagsFromContext()

1
testdata/Containerfile vendored Normal file
View File

@ -0,0 +1 @@
FROM alpine:latest