coder/scripts/clidocgen/main.go

151 lines
4.0 KiB
Go

package main
import (
"encoding/json"
"log"
"os"
"os/user"
"path"
"regexp"
"strings"
"github.com/spf13/cobra/doc"
"github.com/coder/coder/buildinfo"
"github.com/coder/coder/cli"
)
type route struct {
Title string `json:"title,omitempty"`
Description string `json:"description,omitempty"`
Path string `json:"path,omitempty"`
IconPath string `json:"icon_path,omitempty"`
State string `json:"state,omitempty"`
Children []route `json:"children,omitempty"`
}
type manifest struct {
Versions []string `json:"versions,omitempty"`
Routes []route `json:"routes,omitempty"`
}
func main() {
for _, env := range os.Environ() {
if strings.HasPrefix(env, "CODER_") {
split := strings.SplitN(env, "=", 2)
if err := os.Unsetenv(split[0]); err != nil {
log.Fatal("Unable to unset ", split[0], ": ", err)
}
}
}
for k, v := range map[string]string{
"CODER_CONFIG_DIR": "~/.config/coderv2",
"CODER_CACHE_DIRECTORY": "~/.cache/coder",
} {
if err := os.Setenv(k, v); err != nil {
log.Fatal("Unable to set default value for ", k, ": ", err)
}
}
u, err := user.Current()
if err != nil {
log.Fatal("Error on getting the current user: ", err)
}
// Get the cmd CLI
cmd := cli.Root(cli.AGPL())
// Get paths
basePath := os.Getenv("BASE_PATH")
if basePath == "" {
log.Fatal("BASE_PATH should be defined")
}
markdownDocsDir := path.Join(basePath, "docs/cli")
manifestFilepath := path.Join(basePath, "docs/manifest.json")
// Generate markdown
err = doc.GenMarkdownTree(cmd, markdownDocsDir)
if err != nil {
log.Fatal("Error on generating CLI markdown docs: ", err)
}
// Create CLI routes
var cliRoutes []route
files, err := os.ReadDir(markdownDocsDir)
if err != nil {
log.Fatal("Error on loading docs/cli files: ", err)
}
for _, file := range files {
// Remove file extension and prefix
title := strings.Replace(file.Name(), ".md", "", 1)
title = strings.Replace(title, "coder_", "", 1)
title = strings.Replace(title, "_", " ", -1)
cliRoutes = append(cliRoutes, route{
Title: title,
Path: "./cli/" + file.Name(),
})
filepath := path.Join(markdownDocsDir, file.Name())
openFile, err := os.ReadFile(filepath)
if err != nil {
log.Fatal("Error on open file at ", filepath, ": ", err)
}
content := string(openFile)
// Remove non printable strings from generated markdown
// https://github.com/spf13/cobra/issues/1878
const ansi = "[\u001B\u009B][[\\]()#;?]*(?:(?:(?:[a-zA-Z\\d]*(?:;[a-zA-Z\\d]*)*)?\u0007)|(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PRZcf-ntqry=><~]))"
ansiRegex := regexp.MustCompile(ansi)
content = ansiRegex.ReplaceAllString(content, "")
// Remove the version and its right space, since during this script running
// there is no build info available
content = strings.ReplaceAll(content, buildinfo.Version()+" ", "")
// Remove references to the current working directory
dir, err := os.Getwd()
if err != nil {
log.Fatal("Error on getting the current directory:", err)
}
content = strings.ReplaceAll(content, dir, "<current-directory>")
// Remove all absolute home paths.
content = strings.ReplaceAll(content, u.HomeDir, "~")
err = os.WriteFile(filepath, []byte(content), 0o644) // #nosec
if err != nil {
log.Fatal("Error on save file at ", filepath, ": ", err)
}
}
// Read manifest
jsonFile, err := os.ReadFile(manifestFilepath)
if err != nil {
log.Fatal("Error on open docs/manifest.json: ", err)
}
var manifest manifest
err = json.Unmarshal(jsonFile, &manifest)
if err != nil {
log.Fatal("Error on unmarshal manifest.json: ", err)
}
// Update manifest
for i, r := range manifest.Routes {
if r.Title != "Command Line" {
continue
}
manifest.Routes[i].Children = cliRoutes
break
}
manifestFile, err := json.MarshalIndent(manifest, "", " ")
if err != nil {
log.Fatal("Error on marshal manifest.json: ", err)
}
err = os.WriteFile(manifestFilepath, manifestFile, 0o644) // #nosec
if err != nil {
log.Fatal("Error on write update on manifest.json: ", err)
}
}