Skip to content
This repository was archived by the owner on Oct 6, 2025. It is now read-only.

Commit e98b48d

Browse files
committed
generate reference docs with cli-docs-tool
Signed-off-by: CrazyMax <1951866+crazy-max@users.noreply.github.com>
1 parent 0efa602 commit e98b48d

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

76 files changed

+12230
-3
lines changed

.github/workflows/validate.yml

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
name: validate
2+
3+
permissions:
4+
contents: read
5+
6+
concurrency:
7+
group: ${{ github.workflow }}-${{ github.ref }}
8+
cancel-in-progress: true
9+
10+
on:
11+
workflow_dispatch:
12+
push:
13+
branches:
14+
- 'main'
15+
- 'v[0-9]*'
16+
tags:
17+
- 'v*'
18+
19+
jobs:
20+
prepare:
21+
runs-on: ubuntu-24.04
22+
outputs:
23+
targets: ${{ steps.generate.outputs.targets }}
24+
steps:
25+
-
26+
name: Checkout
27+
uses: actions/checkout@v4
28+
-
29+
name: List targets
30+
id: generate
31+
uses: docker/bake-action/subaction/list-targets@v6
32+
with:
33+
target: validate
34+
35+
validate:
36+
runs-on: ubuntu-24.04
37+
needs:
38+
- prepare
39+
strategy:
40+
fail-fast: false
41+
matrix:
42+
target: ${{ fromJson(needs.prepare.outputs.targets) }}
43+
steps:
44+
-
45+
name: Set up Docker Buildx
46+
uses: docker/setup-buildx-action@v3
47+
with:
48+
buildkitd-flags: --debug
49+
-
50+
name: Validate
51+
uses: docker/bake-action@v6
52+
with:
53+
targets: ${{ matrix.target }}

Dockerfile

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
# syntax=docker/dockerfile:1
2+
3+
ARG GO_VERSION=1.24
4+
ARG ALPINE_VERSION=3.21
5+
6+
ARG DOCS_FORMATS="md,yaml"
7+
8+
FROM --platform=${BUILDPLATFORM} golang:${GO_VERSION}-alpine${ALPINE_VERSION} AS base
9+
RUN apk add --no-cache rsync git
10+
ENV GOFLAGS=-mod=vendor
11+
ENV CGO_ENABLED=0
12+
WORKDIR /src
13+
14+
FROM base AS docs-gen
15+
WORKDIR /src
16+
RUN --mount=target=. \
17+
--mount=target=/root/.cache,type=cache \
18+
go build -mod=vendor -o /out/docsgen ./docs/generate.go
19+
20+
FROM base AS docs-build
21+
WORKDIR /src
22+
COPY --from=docs-gen /out/docsgen /usr/bin
23+
ARG DOCS_FORMATS
24+
RUN --mount=target=/context \
25+
--mount=target=.,type=tmpfs <<EOT
26+
set -e
27+
rsync -a /context/. .
28+
docsgen --formats "$DOCS_FORMATS" --source "docs/reference"
29+
mkdir /out
30+
cp -r docs/reference/* /out/
31+
EOT
32+
33+
FROM scratch AS docs-update
34+
COPY --from=docs-build /out /
35+
36+
FROM docs-build AS docs-validate
37+
RUN --mount=target=/context \
38+
--mount=target=.,type=tmpfs <<EOT
39+
set -e
40+
rsync -a /context/. .
41+
git add -A
42+
rm -rf docs/reference/*
43+
cp -rf /out/* ./docs/reference/
44+
if [ -n "$(git status --porcelain -- docs/reference)" ]; then
45+
echo >&2 'ERROR: Docs result differs. Please update with "make docs"'
46+
git status --porcelain -- docs/reference
47+
exit 1
48+
fi
49+
EOT

Makefile

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
.PHONY: all build clean link mock unit-tests
1+
.PHONY: all build clean link mock unit-tests docs
22

33
BINARY_NAME=model-cli
44

@@ -67,3 +67,10 @@ clean:
6767
@echo "Cleaning up..."
6868
@rm -f $(BINARY_NAME)
6969
@echo "Cleaned!"
70+
71+
docs:
72+
$(eval $@_TMP_OUT := $(shell mktemp -d -t model-cli-output.XXXXXXXXXX))
73+
docker buildx bake --set "*.output=type=local,dest=$($@_TMP_OUT)" update-docs
74+
rm -rf ./docs/reference/*
75+
cp -R "$($@_TMP_OUT)"/* ./docs/reference/
76+
rm -rf "$($@_TMP_OUT)"/*

docker-bake.hcl

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
variable "GO_VERSION" {
2+
default = null
3+
}
4+
variable "DOCS_FORMATS" {
5+
default = "md,yaml"
6+
}
7+
8+
target "_common" {
9+
args = {
10+
GO_VERSION = GO_VERSION
11+
BUILDKIT_CONTEXT_KEEP_GIT_DIR = 1
12+
}
13+
}
14+
15+
group "default" {
16+
targets = ["validate"]
17+
}
18+
19+
group "validate" {
20+
targets = ["validate-docs"]
21+
}
22+
23+
target "validate-docs" {
24+
inherits = ["_common"]
25+
args = {
26+
DOCS_FORMATS = DOCS_FORMATS
27+
}
28+
target = "docs-validate"
29+
output = ["type=cacheonly"]
30+
}
31+
32+
target "update-docs" {
33+
inherits = ["_common"]
34+
args = {
35+
DOCS_FORMATS = DOCS_FORMATS
36+
}
37+
target = "docs-update"
38+
output = ["./docs/reference"]
39+
}

docs/generate.go

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
package main
2+
3+
import (
4+
"log"
5+
"os"
6+
"strings"
7+
8+
clidocstool "github.com/docker/cli-docs-tool"
9+
"github.com/docker/cli/cli/command"
10+
"github.com/docker/model-cli/commands"
11+
"github.com/pkg/errors"
12+
"github.com/spf13/cobra"
13+
"github.com/spf13/pflag"
14+
)
15+
16+
const defaultSourcePath = "docs/reference/"
17+
18+
type options struct {
19+
source string
20+
formats []string
21+
}
22+
23+
func gen(opts *options) error {
24+
log.SetFlags(0)
25+
26+
dockerCLI, err := command.NewDockerCli()
27+
if err != nil {
28+
return err
29+
}
30+
cmd := &cobra.Command{
31+
Use: "docker [OPTIONS] COMMAND [ARG...]",
32+
Short: "The base command for the Docker CLI.",
33+
DisableAutoGenTag: true,
34+
}
35+
36+
cmd.AddCommand(commands.NewRootCmd(dockerCLI))
37+
38+
c, err := clidocstool.New(clidocstool.Options{
39+
Root: cmd,
40+
SourceDir: opts.source,
41+
Plugin: true,
42+
})
43+
if err != nil {
44+
return err
45+
}
46+
47+
for _, format := range opts.formats {
48+
switch format {
49+
case "md":
50+
if err = c.GenMarkdownTree(cmd); err != nil {
51+
return err
52+
}
53+
case "yaml":
54+
fixUpExperimentalCLI(cmd)
55+
if err = c.GenYamlTree(cmd); err != nil {
56+
return err
57+
}
58+
default:
59+
return errors.Errorf("unknown format %q", format)
60+
}
61+
}
62+
63+
return nil
64+
}
65+
66+
func run() error {
67+
opts := &options{}
68+
flags := pflag.NewFlagSet(os.Args[0], pflag.ContinueOnError)
69+
flags.StringVar(&opts.source, "source", defaultSourcePath, "Docs source folder")
70+
flags.StringSliceVar(&opts.formats, "formats", []string{}, "Format (md, yaml)")
71+
if err := flags.Parse(os.Args[1:]); err != nil {
72+
return err
73+
}
74+
if len(opts.formats) == 0 {
75+
return errors.New("Docs format required")
76+
}
77+
return gen(opts)
78+
}
79+
80+
func main() {
81+
if err := run(); err != nil {
82+
log.Printf("ERROR: %+v", err)
83+
os.Exit(1)
84+
}
85+
}
86+
87+
// fixUpExperimentalCLI trims the " (EXPERIMENTAL)" suffix from the CLI output,
88+
// as docs.docker.com already displays "experimental (CLI)",
89+
//
90+
// https://github.com/docker/buildx/pull/2188#issuecomment-1889487022
91+
func fixUpExperimentalCLI(cmd *cobra.Command) {
92+
const (
93+
annotationExperimentalCLI = "experimentalCLI"
94+
suffixExperimental = " (EXPERIMENTAL)"
95+
)
96+
if _, ok := cmd.Annotations[annotationExperimentalCLI]; ok {
97+
cmd.Short = strings.TrimSuffix(cmd.Short, suffixExperimental)
98+
}
99+
cmd.Flags().VisitAll(func(f *pflag.Flag) {
100+
if _, ok := f.Annotations[annotationExperimentalCLI]; ok {
101+
f.Usage = strings.TrimSuffix(f.Usage, suffixExperimental)
102+
}
103+
})
104+
for _, c := range cmd.Commands() {
105+
fixUpExperimentalCLI(c)
106+
}
107+
}

0 commit comments

Comments
 (0)