Skip to content

Commit

Permalink
Merge pull request #10 from crazy-max/fix-persistent-flags
Browse files Browse the repository at this point in the history
fix persistent flags
  • Loading branch information
thaJeztah authored Nov 4, 2021
2 parents bb36108 + 669397c commit cc5eaf0
Show file tree
Hide file tree
Showing 13 changed files with 128 additions and 61 deletions.
24 changes: 5 additions & 19 deletions clidocstool.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@ import (
"github.com/spf13/cobra"
)

const (
// AnnotationExternalUrl specifies an external link annotation
AnnotationExternalUrl = "docs.external.url"
)

// Options defines options for cli-docs-tool
type Options struct {
Root *cobra.Command
Expand Down Expand Up @@ -75,25 +80,6 @@ func (c *Client) GenAllTree() error {
return nil
}

// DisableFlagsInUseLine sets the DisableFlagsInUseLine flag on all
// commands within the tree rooted at cmd.
func (c *Client) DisableFlagsInUseLine() {
visitAll(c.root, func(ccmd *cobra.Command) {
// do not add a `[flags]` to the end of the usage line.
ccmd.DisableFlagsInUseLine = true
})
}

// visitAll traverses all commands from the root.
// This is different from the VisitAll of cobra.Command where only parents
// are checked.
func visitAll(root *cobra.Command, fn func(*cobra.Command)) {
for _, cmd := range root.Commands() {
visitAll(cmd, fn)
}
fn(root)
}

func fileExists(f string) bool {
info, err := os.Stat(f)
if os.IsNotExist(err) {
Expand Down
10 changes: 6 additions & 4 deletions clidocstool_md.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ func (c *Client) GenMarkdownTree(cmd *cobra.Command) error {
}
}

// always disable the addition of [flags] to the usage
cmd.DisableFlagsInUseLine = true

// Skip the root command altogether, to prevent generating a useless
// md file for plugins.
if c.plugin && !cmd.HasParent() {
Expand Down Expand Up @@ -117,7 +120,7 @@ func mdFilename(cmd *cobra.Command) string {

func mdMakeLink(txt, link string, f *pflag.Flag, isAnchor bool) string {
link = "#" + link
annotations, ok := f.Annotations["docs.external.url"]
annotations, ok := f.Annotations[AnnotationExternalUrl]
if ok && len(annotations) > 0 {
link = annotations[0]
} else {
Expand Down Expand Up @@ -158,11 +161,10 @@ func mdCmdOutput(cmd *cobra.Command, old string) (string, error) {
fmt.Fprint(b, "\n\n")
}

hasFlags := cmd.Flags().HasAvailableFlags()

// add inherited flags before checking for flags availability
cmd.Flags().AddFlagSet(cmd.InheritedFlags())

if hasFlags {
if cmd.Flags().HasAvailableFlags() {
fmt.Fprint(b, "### Options\n\n")
fmt.Fprint(b, "| Name | Description |\n")
fmt.Fprint(b, "| --- | --- |\n")
Expand Down
2 changes: 1 addition & 1 deletion clidocstool_md_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ func TestGenMarkdownTree(t *testing.T) {
require.NoError(t, err)
require.NoError(t, c.GenMarkdownTree(buildxCmd))

for _, tt := range []string{"buildx.md", "buildx_build.md"} {
for _, tt := range []string{"buildx.md", "buildx_build.md", "buildx_stop.md"} {
tt := tt
t.Run(tt, func(t *testing.T) {
fres := filepath.Join(tmpdir, tt)
Expand Down
76 changes: 43 additions & 33 deletions clidocstool_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ var (
dockerCmd *cobra.Command
buildxCmd *cobra.Command
buildxBuildCmd *cobra.Command
buildxStopCmd *cobra.Command
)

//nolint:errcheck
Expand All @@ -54,43 +55,52 @@ func init() {
Short: "Start a build",
Run: func(cmd *cobra.Command, args []string) {},
}
buildxStopCmd = &cobra.Command{
Use: "stop [NAME]",
Short: "Stop builder instance",
Run: func(cmd *cobra.Command, args []string) {},
}

buildxPFlags := buildxCmd.PersistentFlags()
buildxPFlags.String("builder", os.Getenv("BUILDX_BUILDER"), "Override the configured builder instance")

flags := buildxBuildCmd.Flags()
flags.Bool("push", false, "Shorthand for --output=type=registry")
flags.Bool("load", false, "Shorthand for --output=type=docker")
flags.StringArrayP("tag", "t", []string{}, "Name and optionally a tag in the 'name:tag' format")
flags.SetAnnotation("tag", "docs.external.url", []string{"https://docs.docker.com/engine/reference/commandline/build/#tag-an-image--t"})
flags.StringArray("build-arg", []string{}, "Set build-time variables")
flags.SetAnnotation("build-arg", "docs.external.url", []string{"https://docs.docker.com/engine/reference/commandline/build/#set-build-time-variables---build-arg"})
flags.StringP("file", "f", "", "Name of the Dockerfile (Default is 'PATH/Dockerfile')")
flags.SetAnnotation("file", "docs.external.url", []string{"https://docs.docker.com/engine/reference/commandline/build/#specify-a-dockerfile--f"})
flags.StringArray("label", []string{}, "Set metadata for an image")
flags.StringArray("cache-from", []string{}, "External cache sources (eg. user/app:cache, type=local,src=path/to/dir)")
flags.StringArray("cache-to", []string{}, "Cache export destinations (eg. user/app:cache, type=local,dest=path/to/dir)")
flags.String("target", "", "Set the target build stage to build.")
flags.SetAnnotation("target", "docs.external.url", []string{"https://docs.docker.com/engine/reference/commandline/build/#specifying-target-build-stage---target"})
flags.StringSlice("allow", []string{}, "Allow extra privileged entitlement, e.g. network.host, security.insecure")
flags.StringArray("platform", []string{}, "Set target platform for build")
flags.StringArray("secret", []string{}, "Secret file to expose to the build: id=mysecret,src=/local/secret")
flags.StringArray("ssh", []string{}, "SSH agent socket or keys to expose to the build (format: `default|<id>[=<socket>|<key>[,<key>]]`)")
flags.StringArrayP("output", "o", []string{}, "Output destination (format: type=local,dest=path)")
buildxBuildFlags := buildxBuildCmd.Flags()
buildxBuildFlags.Bool("push", false, "Shorthand for --output=type=registry")
buildxBuildFlags.Bool("load", false, "Shorthand for --output=type=docker")
buildxBuildFlags.StringArrayP("tag", "t", []string{}, "Name and optionally a tag in the 'name:tag' format")
buildxBuildFlags.SetAnnotation("tag", AnnotationExternalUrl, []string{"https://docs.docker.com/engine/reference/commandline/build/#tag-an-image--t"})
buildxBuildFlags.StringArray("build-arg", []string{}, "Set build-time variables")
buildxBuildFlags.SetAnnotation("build-arg", AnnotationExternalUrl, []string{"https://docs.docker.com/engine/reference/commandline/build/#set-build-time-variables---build-arg"})
buildxBuildFlags.StringP("file", "f", "", "Name of the Dockerfile (Default is 'PATH/Dockerfile')")
buildxBuildFlags.SetAnnotation("file", AnnotationExternalUrl, []string{"https://docs.docker.com/engine/reference/commandline/build/#specify-a-dockerfile--f"})
buildxBuildFlags.StringArray("label", []string{}, "Set metadata for an image")
buildxBuildFlags.StringArray("cache-from", []string{}, "External cache sources (eg. user/app:cache, type=local,src=path/to/dir)")
buildxBuildFlags.StringArray("cache-to", []string{}, "Cache export destinations (eg. user/app:cache, type=local,dest=path/to/dir)")
buildxBuildFlags.String("target", "", "Set the target build stage to build.")
buildxBuildFlags.SetAnnotation("target", AnnotationExternalUrl, []string{"https://docs.docker.com/engine/reference/commandline/build/#specifying-target-build-stage---target"})
buildxBuildFlags.StringSlice("allow", []string{}, "Allow extra privileged entitlement, e.g. network.host, security.insecure")
buildxBuildFlags.StringArray("platform", []string{}, "Set target platform for build")
buildxBuildFlags.StringArray("secret", []string{}, "Secret file to expose to the build: id=mysecret,src=/local/secret")
buildxBuildFlags.StringArray("ssh", []string{}, "SSH agent socket or keys to expose to the build (format: `default|<id>[=<socket>|<key>[,<key>]]`)")
buildxBuildFlags.StringArrayP("output", "o", []string{}, "Output destination (format: type=local,dest=path)")
// not implemented
flags.String("network", "default", "Set the networking mode for the RUN instructions during build")
flags.StringSlice("add-host", []string{}, "Add a custom host-to-IP mapping (host:ip)")
flags.SetAnnotation("add-host", "docs.external.url", []string{"https://docs.docker.com/engine/reference/commandline/build/#add-entries-to-container-hosts-file---add-host"})
flags.String("iidfile", "", "Write the image ID to the file")
buildxBuildFlags.String("network", "default", "Set the networking mode for the RUN instructions during build")
buildxBuildFlags.StringSlice("add-host", []string{}, "Add a custom host-to-IP mapping (host:ip)")
buildxBuildFlags.SetAnnotation("add-host", AnnotationExternalUrl, []string{"https://docs.docker.com/engine/reference/commandline/build/#add-entries-to-container-hosts-file---add-host"})
buildxBuildFlags.String("iidfile", "", "Write the image ID to the file")
// hidden flags
flags.BoolP("quiet", "q", false, "Suppress the build output and print image ID on success")
flags.MarkHidden("quiet")
flags.Bool("squash", false, "Squash newly built layers into a single new layer")
flags.MarkHidden("squash")
flags.String("ulimit", "", "Ulimit options")
flags.MarkHidden("ulimit")
flags.StringSlice("security-opt", []string{}, "Security options")
flags.MarkHidden("security-opt")
flags.Bool("compress", false, "Compress the build context using gzip")
buildxBuildFlags.BoolP("quiet", "q", false, "Suppress the build output and print image ID on success")
buildxBuildFlags.MarkHidden("quiet")
buildxBuildFlags.Bool("squash", false, "Squash newly built layers into a single new layer")
buildxBuildFlags.MarkHidden("squash")
buildxBuildFlags.String("ulimit", "", "Ulimit options")
buildxBuildFlags.MarkHidden("ulimit")
buildxBuildFlags.StringSlice("security-opt", []string{}, "Security options")
buildxBuildFlags.MarkHidden("security-opt")
buildxBuildFlags.Bool("compress", false, "Compress the build context using gzip")

buildxCmd.AddCommand(buildxBuildCmd)
buildxCmd.AddCommand(buildxStopCmd)
dockerCmd.AddCommand(buildxCmd)
}

Expand All @@ -108,7 +118,7 @@ func TestGenAllTree(t *testing.T) {
require.NoError(t, err)
require.NoError(t, c.GenAllTree())

for _, tt := range []string{"buildx.md", "buildx_build.md", "docker_buildx.yaml", "docker_buildx_build.yaml"} {
for _, tt := range []string{"buildx.md", "buildx_build.md", "buildx_stop.md", "docker_buildx.yaml", "docker_buildx_build.yaml", "docker_buildx_stop.yaml"} {
tt := tt
t.Run(tt, func(t *testing.T) {
fres := filepath.Join(tmpdir, tt)
Expand Down
9 changes: 8 additions & 1 deletion clidocstool_yaml.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,9 @@ func (c *Client) genYamlTreeCustom(cmd *cobra.Command, filePrepender func(string
}
}

// always disable the addition of [flags] to the usage
cmd.DisableFlagsInUseLine = true

// The "root" command used in the generator is just a "stub", and only has a
// list of subcommands, but not (e.g.) global options/flags. We should fix
// that, so that the YAML file for the docker "root" command contains the
Expand Down Expand Up @@ -140,6 +143,10 @@ func (c *Client) genYamlCustom(cmd *cobra.Command, w io.Writer) error {
longMaxWidth = 74
)

// necessary to add inherited flags otherwise some
// fields are not properly declared like usage
cmd.Flags().AddFlagSet(cmd.InheritedFlags())

cliDoc := cmdDoc{
Name: cmd.CommandPath(),
Aliases: strings.Join(cmd.Aliases, ", "),
Expand Down Expand Up @@ -259,7 +266,7 @@ func genFlagResult(flags *pflag.FlagSet, anchors map[string]struct{}) []cmdOptio
Deprecated: len(flag.Deprecated) > 0,
}

if v, ok := flag.Annotations["docs.external.url"]; ok && len(v) > 0 {
if v, ok := flag.Annotations[AnnotationExternalUrl]; ok && len(v) > 0 {
opt.DetailsURL = strings.TrimPrefix(v[0], "https://docs.docker.com")
} else if _, ok = anchors[flag.Name]; ok {
opt.DetailsURL = "#" + flag.Name
Expand Down
2 changes: 1 addition & 1 deletion clidocstool_yaml_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ func TestGenYamlTree(t *testing.T) {
require.NoError(t, err)
require.NoError(t, c.GenYamlTree(buildxCmd))

for _, tt := range []string{"docker_buildx.yaml", "docker_buildx_build.yaml"} {
for _, tt := range []string{"docker_buildx.yaml", "docker_buildx_build.yaml", "docker_buildx_stop.yaml"} {
tt := tt
t.Run(tt, func(t *testing.T) {
fres := filepath.Join(tmpdir, tt)
Expand Down
1 change: 0 additions & 1 deletion example/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,6 @@ func gen(opts *options) error {
if err != nil {
return err
}
c.DisableFlagsInUseLine()

// generate all supported docs formats
return c.GenAllTree()
Expand Down
7 changes: 7 additions & 0 deletions fixtures/buildx.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,15 @@ Build with BuildKit
| Name | Description |
| --- | --- |
| [`build`](buildx_build.md) | Start a build |
| [`stop`](buildx_stop.md) | Stop builder instance |


### Options

| Name | Description |
| --- | --- |
| `--builder string` | Override the configured builder instance |


<!---MARKER_GEN_END-->

1 change: 1 addition & 0 deletions fixtures/buildx_build.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ Start a build
| [`--add-host stringSlice`](https://docs.docker.com/engine/reference/commandline/build/#add-entries-to-container-hosts-file---add-host) | Add a custom host-to-IP mapping (host:ip) |
| `--allow stringSlice` | Allow extra privileged entitlement, e.g. network.host, security.insecure |
| [`--build-arg stringArray`](https://docs.docker.com/engine/reference/commandline/build/#set-build-time-variables---build-arg) | Set build-time variables |
| `--builder string` | Override the configured builder instance |
| `--cache-from stringArray` | External cache sources (eg. user/app:cache, type=local,src=path/to/dir) |
| `--cache-to stringArray` | Cache export destinations (eg. user/app:cache, type=local,dest=path/to/dir) |
| `--compress` | Compress the build context using gzip |
Expand Down
14 changes: 14 additions & 0 deletions fixtures/buildx_stop.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# docker buildx stop

<!---MARKER_GEN_START-->
Stop builder instance

### Options

| Name | Description |
| --- | --- |
| `--builder string` | Override the configured builder instance |


<!---MARKER_GEN_END-->

11 changes: 11 additions & 0 deletions fixtures/docker_buildx.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,19 @@ pname: docker
plink: docker.yaml
cname:
- docker buildx build
- docker buildx stop
clink:
- docker_buildx_build.yaml
- docker_buildx_stop.yaml
options:
- option: builder
value_type: string
description: Override the configured builder instance
deprecated: false
experimental: false
experimentalcli: false
kubernetes: false
swarm: false
deprecated: false
experimental: false
experimentalcli: false
Expand Down
11 changes: 10 additions & 1 deletion fixtures/docker_buildx_build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ command: docker buildx build
aliases: b
short: Start a build
long: Start a build
usage: docker buildx build [OPTIONS] PATH | URL | - [flags]
usage: docker buildx build [OPTIONS] PATH | URL | -
pname: docker buildx
plink: docker_buildx.yaml
options:
Expand Down Expand Up @@ -213,6 +213,15 @@ options:
experimentalcli: false
kubernetes: false
swarm: false
inherited_options:
- option: builder
value_type: string
description: Override the configured builder instance
deprecated: false
experimental: false
experimentalcli: false
kubernetes: false
swarm: false
deprecated: false
experimental: false
experimentalcli: false
Expand Down
21 changes: 21 additions & 0 deletions fixtures/docker_buildx_stop.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
command: docker buildx stop
short: Stop builder instance
long: Stop builder instance
usage: docker buildx stop [NAME]
pname: docker buildx
plink: docker_buildx.yaml
inherited_options:
- option: builder
value_type: string
description: Override the configured builder instance
deprecated: false
experimental: false
experimentalcli: false
kubernetes: false
swarm: false
deprecated: false
experimental: false
experimentalcli: false
kubernetes: false
swarm: false

0 comments on commit cc5eaf0

Please sign in to comment.