From 4e24d83c7adc1054bc5c58454c1f36fa7812f417 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julian=20T=C3=B6lle?= Date: Sat, 2 Nov 2024 21:57:53 +0100 Subject: [PATCH] docs: add generated CLI help output to repo (#46) Generate the help pages using `cobras` builtin functionality and commit them to the repository. This gives users to ability to review the options of `hcloud-upload-image` without having to install it first. --- .github/workflows/ci.yaml | 22 +++++++++++-- README.md | 2 +- cmd/cleanup.go | 7 ++-- cmd/root.go | 20 ++++++------ cmd/upload.go | 6 ++-- docs/cli/hcloud-upload-image.md | 20 ++++++++++++ docs/cli/hcloud-upload-image_cleanup.md | 38 ++++++++++++++++++++++ docs/cli/hcloud-upload-image_upload.md | 43 +++++++++++++++++++++++++ go.mod | 3 ++ go.sum | 10 ++++++ scripts/cli-help-pages.go | 35 ++++++++++++++++++++ 11 files changed, 188 insertions(+), 18 deletions(-) create mode 100644 docs/cli/hcloud-upload-image.md create mode 100644 docs/cli/hcloud-upload-image_cleanup.md create mode 100644 docs/cli/hcloud-upload-image_upload.md create mode 100644 scripts/cli-help-pages.go diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 8af6e11..2be498c 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -30,7 +30,6 @@ jobs: args: --timeout 5m working-directory: hcloudimages - test: runs-on: ubuntu-latest steps: @@ -45,7 +44,6 @@ jobs: - name: Run tests run: go test -v -race -coverpkg=./...,./hcloudimages/... ./... ./hcloudimages/... - go-mod-tidy: runs-on: ubuntu-latest steps: @@ -65,3 +63,23 @@ jobs: - if: failure() run: echo "::error::Check failed, please run 'go mod tidy' and commit the changes." + + cli-help-pages: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Set up Go + uses: actions/setup-go@v5 + with: + go-version-file: go.mod + + - name: Generate CLI help pages + run: go run ./scripts/cli-help-pages.go + + - name: Check uncommitted changes + run: git diff --exit-code + + - if: failure() + run: echo "::error::Check failed, please run 'go run ./scripts/cli-help-pages.go' and commit the changes." diff --git a/README.md b/README.md index 55ca110..ced52ee 100644 --- a/README.md +++ b/README.md @@ -63,7 +63,7 @@ hcloud-upload-image upload \ --compression bz2 ``` -To learn more, you can use the embedded help output: +To learn more, you can use the embedded help output or check out the [CLI help pages in this repository](docs/cli/hcloud-upload-image.md).: ```shell hcloud-upload-image --help diff --git a/cmd/cleanup.go b/cmd/cleanup.go index 78486b7..a41e2e1 100644 --- a/cmd/cleanup.go +++ b/cmd/cleanup.go @@ -18,11 +18,12 @@ that match the label "apricote.de/created-by=hcloud-upload-image". If you want to see a preview of what would be removed, you can use the official hcloud CLI and run: -$ hcloud server list -l apricote.de/created-by=hcloud-upload-image -$ hcloud ssh-key list -l apricote.de/created-by=hcloud-upload-image + $ hcloud server list -l apricote.de/created-by=hcloud-upload-image + $ hcloud ssh-key list -l apricote.de/created-by=hcloud-upload-image This command does not handle any parallel executions of hcloud-upload-image and will remove in-use resources if called at the same time.`, + DisableAutoGenTag: true, GroupID: "primary", @@ -44,5 +45,5 @@ and will remove in-use resources if called at the same time.`, } func init() { - rootCmd.AddCommand(cleanupCmd) + RootCmd.AddCommand(cleanupCmd) } diff --git a/cmd/root.go b/cmd/root.go index 1d735d4..3e28667 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -28,11 +28,13 @@ var ( // The pre-authenticated client. Set in the root command PersistentPreRun var client *hcloudimages.Client -// rootCmd represents the base command when called without any subcommands -var rootCmd = &cobra.Command{ - Use: "hcloud-upload-image", - Long: `Manage custom OS images on Hetzner Cloud.`, - SilenceUsage: true, +// RootCmd represents the base command when called without any subcommands +var RootCmd = &cobra.Command{ + Use: "hcloud-upload-image", + Short: `Manage custom OS images on Hetzner Cloud.`, + Long: `Manage custom OS images on Hetzner Cloud.`, + SilenceUsage: true, + DisableAutoGenTag: true, Version: version.Version, @@ -98,18 +100,18 @@ func initClient(cmd *cobra.Command, _ []string) { } func Execute() { - err := rootCmd.Execute() + err := RootCmd.Execute() if err != nil { os.Exit(1) } } func init() { - rootCmd.SetErrPrefix("\033[1;31mError:") + RootCmd.SetErrPrefix("\033[1;31mError:") - rootCmd.PersistentFlags().CountVarP(&verbose, flagVerbose, "v", "verbose debug output, can be specified up to 2 times") + RootCmd.PersistentFlags().CountVarP(&verbose, flagVerbose, "v", "verbose debug output, can be specified up to 2 times") - rootCmd.AddGroup(&cobra.Group{ + RootCmd.AddGroup(&cobra.Group{ ID: "primary", Title: "Primary Commands:", }) diff --git a/cmd/upload.go b/cmd/upload.go index 0c06177..9196900 100644 --- a/cmd/upload.go +++ b/cmd/upload.go @@ -29,8 +29,8 @@ var uploadCmd = &cobra.Command{ Long: `This command implements a fake "upload", by going through a real server and snapshots. This does cost a bit of money for the server.`, Example: ` hcloud-upload-image upload --image-path /home/you/images/custom-linux-image-x86.bz2 --architecture x86 --compression bz2 --description "My super duper custom linux" - hcloud-upload-image upload --image-url https://examples.com/image-arm.raw --architecture arm --labels foo=bar,version=latest -`, + hcloud-upload-image upload --image-url https://examples.com/image-arm.raw --architecture arm --labels foo=bar,version=latest`, + DisableAutoGenTag: true, GroupID: "primary", @@ -88,7 +88,7 @@ This does cost a bit of money for the server.`, } func init() { - rootCmd.AddCommand(uploadCmd) + RootCmd.AddCommand(uploadCmd) uploadCmd.Flags().String(uploadFlagImageURL, "", "Remote URL of the disk image that should be uploaded") uploadCmd.Flags().String(uploadFlagImagePath, "", "Local path to the disk image that should be uploaded") diff --git a/docs/cli/hcloud-upload-image.md b/docs/cli/hcloud-upload-image.md new file mode 100644 index 0000000..1e01ef0 --- /dev/null +++ b/docs/cli/hcloud-upload-image.md @@ -0,0 +1,20 @@ +## hcloud-upload-image + +Manage custom OS images on Hetzner Cloud. + +### Synopsis + +Manage custom OS images on Hetzner Cloud. + +### Options + +``` + -h, --help help for hcloud-upload-image + -v, --verbose count verbose debug output, can be specified up to 2 times +``` + +### SEE ALSO + +* [hcloud-upload-image cleanup](hcloud-upload-image_cleanup.md) - Remove any temporary resources that were left over +* [hcloud-upload-image upload](hcloud-upload-image_upload.md) - Upload the specified disk image into your Hetzner Cloud project. + diff --git a/docs/cli/hcloud-upload-image_cleanup.md b/docs/cli/hcloud-upload-image_cleanup.md new file mode 100644 index 0000000..5e848a4 --- /dev/null +++ b/docs/cli/hcloud-upload-image_cleanup.md @@ -0,0 +1,38 @@ +## hcloud-upload-image cleanup + +Remove any temporary resources that were left over + +### Synopsis + +If the upload fails at any point, there might still exist a server or +ssh key in your Hetzner Cloud project. This command cleans up any resources +that match the label "apricote.de/created-by=hcloud-upload-image". + +If you want to see a preview of what would be removed, you can use the official hcloud CLI and run: + + $ hcloud server list -l apricote.de/created-by=hcloud-upload-image + $ hcloud ssh-key list -l apricote.de/created-by=hcloud-upload-image + +This command does not handle any parallel executions of hcloud-upload-image +and will remove in-use resources if called at the same time. + +``` +hcloud-upload-image cleanup [flags] +``` + +### Options + +``` + -h, --help help for cleanup +``` + +### Options inherited from parent commands + +``` + -v, --verbose count verbose debug output, can be specified up to 2 times +``` + +### SEE ALSO + +* [hcloud-upload-image](hcloud-upload-image.md) - Manage custom OS images on Hetzner Cloud. + diff --git a/docs/cli/hcloud-upload-image_upload.md b/docs/cli/hcloud-upload-image_upload.md new file mode 100644 index 0000000..e1dd434 --- /dev/null +++ b/docs/cli/hcloud-upload-image_upload.md @@ -0,0 +1,43 @@ +## hcloud-upload-image upload + +Upload the specified disk image into your Hetzner Cloud project. + +### Synopsis + +This command implements a fake "upload", by going through a real server and snapshots. +This does cost a bit of money for the server. + +``` +hcloud-upload-image upload (--image-path= | --image-url=) --architecture= [flags] +``` + +### Examples + +``` + hcloud-upload-image upload --image-path /home/you/images/custom-linux-image-x86.bz2 --architecture x86 --compression bz2 --description "My super duper custom linux" + hcloud-upload-image upload --image-url https://examples.com/image-arm.raw --architecture arm --labels foo=bar,version=latest +``` + +### Options + +``` + --architecture string CPU architecture of the disk image [choices: x86, arm] + --compression string Type of compression that was used on the disk image [choices: bz2, xz] + --description string Description for the resulting image + -h, --help help for upload + --image-path string Local path to the disk image that should be uploaded + --image-url string Remote URL of the disk image that should be uploaded + --labels stringToString Labels for the resulting image (default []) + --server-type string Explicitly use this server type to generate the image. Mutually exclusive with --architecture. +``` + +### Options inherited from parent commands + +``` + -v, --verbose count verbose debug output, can be specified up to 2 times +``` + +### SEE ALSO + +* [hcloud-upload-image](hcloud-upload-image.md) - Manage custom OS images on Hetzner Cloud. + diff --git a/go.mod b/go.mod index 83ebb7c..60d170b 100644 --- a/go.mod +++ b/go.mod @@ -11,17 +11,20 @@ require ( require ( github.com/beorn7/perks v1.0.1 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect + github.com/cpuguy83/go-md2man/v2 v2.0.4 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/prometheus/client_golang v1.19.1 // indirect github.com/prometheus/client_model v0.5.0 // indirect github.com/prometheus/common v0.48.0 // indirect github.com/prometheus/procfs v0.12.0 // indirect + github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/spf13/pflag v1.0.5 // indirect golang.org/x/crypto v0.24.0 // indirect golang.org/x/net v0.25.0 // indirect golang.org/x/sys v0.21.0 // indirect golang.org/x/text v0.16.0 // indirect google.golang.org/protobuf v1.33.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect ) replace github.com/apricote/hcloud-upload-image/hcloudimages => ./hcloudimages diff --git a/go.sum b/go.sum index e681ee3..cd82bf6 100644 --- a/go.sum +++ b/go.sum @@ -2,6 +2,7 @@ github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cpuguy83/go-md2man/v2 v2.0.4 h1:wfIWP927BUkWJb2NmU/kNDYIBTh/ziUX91+lVfRxZq4= github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -11,6 +12,10 @@ github.com/hetznercloud/hcloud-go/v2 v2.9.0 h1:s0N6R7Zoi2DPfMtUF5o9VeUBzTtHVY6MI github.com/hetznercloud/hcloud-go/v2 v2.9.0/go.mod h1:qtW/TuU7Bs16ibXl/ktJarWqU2LwHr7eGlwoilHxtgg= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_golang v1.19.1 h1:wZWJDwK+NameRJuPGDhlnFgx8e8HN3XHQeLaYJFJBOE= @@ -21,6 +26,9 @@ github.com/prometheus/common v0.48.0 h1:QO8U2CdOzSn1BBsmXJXduaaW+dY/5QLjfB8svtSz github.com/prometheus/common v0.48.0/go.mod h1:0/KsvlIEfPQCQ5I2iNSAWKPZziNCvRs5EC6ILDTlAPc= github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= +github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= +github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= +github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= @@ -41,5 +49,7 @@ golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/scripts/cli-help-pages.go b/scripts/cli-help-pages.go new file mode 100644 index 0000000..778a19b --- /dev/null +++ b/scripts/cli-help-pages.go @@ -0,0 +1,35 @@ +package main + +import ( + "fmt" + "os" + + "github.com/spf13/cobra/doc" + + "github.com/apricote/hcloud-upload-image/cmd" +) + +func run() error { + // Define the directory where the docs will be generated + dir := "docs/cli" + + // Ensure the directory exists + if err := os.MkdirAll(dir, 0755); err != nil { + return fmt.Errorf("error creating docs directory: %v", err) + } + + // Generate the docs + if err := doc.GenMarkdownTree(cmd.RootCmd, dir); err != nil { + return fmt.Errorf("error generating docs: %v", err) + } + + fmt.Println("Docs generated successfully in", dir) + return nil +} + +func main() { + if err := run(); err != nil { + fmt.Printf("Error: %v\n", err) + os.Exit(1) + } +}