Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
/hcloud
/dist
/bats
/completions
/manpages
/cmd/hcloud/hcloud
hcloud_cli.p12
coverage.txt
70 changes: 58 additions & 12 deletions .goreleaser.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ version: 2
before:
hooks:
- go mod tidy
- ./scripts/completions.sh
- go run scripts/manpages.go

builds:
- <<: &build_defaults
Expand All @@ -17,13 +19,26 @@ builds:
env:
- CGO_ENABLED=0

id: hcloud-build
goos: [freebsd, windows, linux]
id: hcloud-build-linux-main
goos: [linux]
goarch: [amd64, arm64]

- <<: *build_defaults
id: hcloud-build-linux-other
goos: [ linux ]
goarch: [ arm, "386" ]
goarm: [ "6", "7" ]

- <<: *build_defaults
id: hcloud-build-freebsd
goos: [ freebsd ]
goarch: [amd64, arm, arm64, "386"]
goarm: ["6", "7"]
ignore:
- goos: windows
goarch: arm

- <<: *build_defaults
id: hcloud-build-windows
goos: [ windows ]
goarch: [ amd64, arm64, "386" ]

- <<: *build_defaults
id: hcloud-build-darwin
Expand All @@ -37,9 +52,46 @@ builds:
- cmd: bash -c 'quill sign-and-notarize "{{ .Path }}" --dry-run={{ .IsSnapshot }} --ad-hoc={{ .IsSnapshot }} || touch sign-and-notarize.error'
output: true

nfpms:
- id: default
file_name_template: "{{ .ConventionalFileName }}"
package_name: hcloud-cli
ids: [hcloud-build-linux-main]
provides: [hcloud]
vendor: Hetzner Cloud GmbH
homepage: https://github.com/hetznercloud/cli
maintainer: Hetzner Cloud GmbH <support-cloud@hetzner.com>
formats:
- deb
- rpm
description: A command-line interface for Hetzner Cloud
license: MIT

contents:
- src: ./completions/hcloud.bash
dst: /usr/share/bash-completion/completions/hcloud
file_info:
mode: 0644
- src: ./completions/hcloud.fish
dst: /usr/share/fish/vendor_completions.d/hcloud.fish
file_info:
mode: 0644
- src: ./completions/hcloud.zsh
dst: /usr/share/zsh/vendor-completions/_hcloud
file_info:
mode: 0644
- src: ./LICENSE
dst: /usr/share/doc/hcloud/license
file_info:
mode: 0644
- src: ./manpages/*
dst: /usr/share/man/man1/
file_info:
mode: 0644

kos:
- id: container-images
build: hcloud-build
build: hcloud-build-linux-main
main: ./cmd/hcloud/
repositories:
- hetznercloud/cli
Expand Down Expand Up @@ -71,9 +123,6 @@ signs:
- artifacts: all
signature: ${artifact}.sig
id: hcloud-sign
ids:
- hcloud-build
- hcloud-build-darwin
args:
- --batch
- --local-user=github-bot@hetzner-cloud.de
Expand All @@ -84,9 +133,6 @@ signs:

archives:
- id: hcloud-archive
ids:
- hcloud-build
- hcloud-build-darwin
name_template: "{{ .Binary }}-{{ .Os }}-{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}"

format_overrides:
Expand Down
22 changes: 22 additions & 0 deletions internal/cmd/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,42 @@ package config

import (
_ "embed"
"fmt"

"github.com/spf13/cobra"

"github.com/hetznercloud/cli/internal/cmd/util"
"github.com/hetznercloud/cli/internal/state"
"github.com/hetznercloud/cli/internal/state/config"
)

//go:embed helptext/other.txt
var nonPreferenceOptions string

//go:embed helptext/other.md
var nonPreferenceOptionsMd string

//go:embed helptext/preferences.txt
var preferenceOptions string

//go:embed helptext/preferences.md
var preferenceOptionsMd string

func NewCommand(s state.State) *cobra.Command {
var (
nonPreferenceOptions = nonPreferenceOptions
preferenceOptions = preferenceOptions
)

useMarkdown, err := config.OptionMarkdownTableFormat.Get(s.Config())
fmt.Println(useMarkdown)
fmt.Println(err)

if useMarkdown, err := config.OptionMarkdownTableFormat.Get(s.Config()); err == nil && useMarkdown {
nonPreferenceOptions = nonPreferenceOptionsMd
preferenceOptions = preferenceOptionsMd
}

cmd := &cobra.Command{
Use: "config",
Short: "Manage configuration",
Expand Down
25 changes: 11 additions & 14 deletions internal/cmd/config/helptext/generate.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,28 +17,18 @@ import (

func main() {
generateTable(
"preferences.txt",
"preferences",
config.OptionFlagPreference|config.OptionFlagHidden,
config.OptionFlagPreference,
table.Row{"sort.<resource>", "Default sorting for resource", "string list", "sort.<resource>", "HCLOUD_SORT_<RESOURCE>", ""},
)
generateTable("other.txt",
generateTable("other",
config.OptionFlagPreference|config.OptionFlagHidden,
0,
)
}

func generateTable(outFile string, mask, filter config.OptionFlag, extraRows ...table.Row) {
f, err := os.OpenFile(outFile, os.O_TRUNC|os.O_CREATE|os.O_WRONLY, 0644) //nolint:gosec
if err != nil {
panic(err)
}
defer func() {
if err := f.Close(); err != nil {
panic(err)
}
}()

t := table.NewWriter()
t.SetStyle(table.StyleLight)
t.SetColumnConfigs([]table.ColumnConfig{
Expand All @@ -49,7 +39,6 @@ func generateTable(outFile string, mask, filter config.OptionFlag, extraRows ...
},
})

t.SetOutputMirror(f)
t.AppendHeader(table.Row{"Option", "Description", "Type", "Config key", "Environment variable", "Flag"})

var opts []config.IOption
Expand All @@ -74,7 +63,15 @@ func generateTable(outFile string, mask, filter config.OptionFlag, extraRows ...
t.AppendSeparator()
}

t.Render()
err := os.WriteFile(outFile+".txt", []byte(t.Render()+"\n"), 0644)
if err != nil {
panic(err)
}

err = os.WriteFile(outFile+".md", []byte(t.RenderMarkdown()+"\n"), 0644)
if err != nil {
panic(err)
}
}

func getTypeName(opt config.IOption) string {
Expand Down
5 changes: 5 additions & 0 deletions internal/cmd/config/helptext/other.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
| Option | Description | Type | Config key | Environment variable | Flag |
| --- | --- | --- | --- | --- | --- |
| config | Config file path (default "~/.config/hcloud/cli.toml") | string | | HCLOUD_CONFIG | --config |
| context | Currently active context | string | active_context | HCLOUD_CONTEXT | --context |
| token | Hetzner Cloud API token | string | token | HCLOUD_TOKEN | |
12 changes: 12 additions & 0 deletions internal/cmd/config/helptext/preferences.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
| Option | Description | Type | Config key | Environment variable | Flag |
| --- | --- | --- | --- | --- | --- |
| debug | Enable debug output | boolean | debug | HCLOUD_DEBUG | --debug |
| debug-file | File to write debug output to | string | debug_file | HCLOUD_DEBUG_FILE | --debug-file |
| default-ssh-keys | Default SSH Keys for new Servers and Storage Boxes | string list | default_ssh_keys | HCLOUD_DEFAULT_SSH_KEYS | |
| endpoint | Hetzner Cloud API endpoint | string | endpoint | HCLOUD_ENDPOINT | --endpoint |
| hetzner-endpoint | Hetzner API endpoint | string | hetzner_endpoint | HETZNER_ENDPOINT | --hetzner-endpoint |
| markdown-table-format | Force table formatting in help outputs to markdown | boolean | markdown_table_format | HCLOUD_MARKDOWN_TABLE_FORMAT | --markdown-table-format |
| no-experimental-warnings | If true, experimental warnings are not shown | boolean | no_experimental_warnings | HCLOUD_NO_EXPERIMENTAL_WARNINGS | --no-experimental-warnings |
| poll-interval | Interval at which to poll information, for example action progress | duration | poll_interval | HCLOUD_POLL_INTERVAL | --poll-interval |
| quiet | If true, only print error messages | boolean | quiet | HCLOUD_QUIET | --quiet |
| sort.<resource> | Default sorting for resource | string list | sort.<resource> | HCLOUD_SORT_<RESOURCE> | |
4 changes: 4 additions & 0 deletions internal/cmd/config/helptext/preferences.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@
├──────────────────────────┼──────────────────────┼─────────────┼──────────────────────────┼─────────────────────────────────┼────────────────────────────┤
│ hetzner-endpoint │ Hetzner API endpoint │ string │ hetzner_endpoint │ HETZNER_ENDPOINT │ --hetzner-endpoint │
├──────────────────────────┼──────────────────────┼─────────────┼──────────────────────────┼─────────────────────────────────┼────────────────────────────┤
│ markdown-table-format │ Force table │ boolean │ markdown_table_format │ HCLOUD_MARKDOWN_TABLE_FORMAT │ --markdown-table-format │
│ │ formatting in help │ │ │ │ │
│ │ outputs to markdown │ │ │ │ │
├──────────────────────────┼──────────────────────┼─────────────┼──────────────────────────┼─────────────────────────────────┼────────────────────────────┤
│ no-experimental-warnings │ If true, │ boolean │ no_experimental_warnings │ HCLOUD_NO_EXPERIMENTAL_WARNINGS │ --no-experimental-warnings │
│ │ experimental │ │ │ │ │
│ │ warnings are not │ │ │ │ │
Expand Down
1 change: 1 addition & 0 deletions internal/scripts/generate_docs.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ func run() error {
cmd := cli.NewRootCommand(s)

// Generate the docs
config.OptionMarkdownTableFormat.Override(cfg, true)
if err := doc.GenMarkdownTree(cmd, dir); err != nil {
return fmt.Errorf("error generating docs: %w", err)
}
Expand Down
9 changes: 9 additions & 0 deletions internal/state/config/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,15 @@ var (
nil,
)

OptionMarkdownTableFormat = newOpt(
"markdown-table-format",
"Force table formatting in help outputs to markdown",
false,
DefaultPreferenceFlags,
nil,
nil,
)

OptionPollInterval = newOpt(
"poll-interval",
"Interval at which to poll information, for example action progress",
Expand Down
7 changes: 7 additions & 0 deletions scripts/completions.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#!/bin/sh
set -e
rm -rf completions
mkdir completions
for sh in bash zsh fish; do
go run ./cmd/hcloud completion "$sh" >"completions/hcloud.$sh"
done
57 changes: 57 additions & 0 deletions scripts/manpages.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package main

import (
"fmt"
"log"
"os"
"path/filepath"
"regexp"

"github.com/spf13/cobra/doc"

"github.com/hetznercloud/cli/internal/cli"
"github.com/hetznercloud/cli/internal/state"
"github.com/hetznercloud/cli/internal/state/config"
)

const directory = "./manpages"

func main() {
//nolint:gosec
if err := os.MkdirAll(directory, 0755); err != nil {
log.Fatal(err)
}

s, _ := state.New(config.New())
rootCommand := cli.NewRootCommand(s)

err := doc.GenManTree(rootCommand, nil, directory)
if err != nil {
log.Fatal(err)
}

files, err := os.ReadDir(directory)
if err != nil {
log.Fatal(err)
}

generatedOnRegex := regexp.MustCompile(`\n\n\.SH HISTORY\n.* Auto generated by spf13/cobra\n`)

for _, f := range files {
if f.IsDir() {
continue
}
path := filepath.Join(directory, f.Name())
bytes, err := os.ReadFile(path)
if err != nil {
log.Fatalf("could not read file at %q: %v", path, err)
}
bytes = generatedOnRegex.ReplaceAll(bytes, nil)
err = os.WriteFile(path, bytes, f.Type())
if err != nil {
log.Fatalf("could not write file at %q: %w", path, err)
}
}

fmt.Println("Man pages generated successfully")
}
Loading