mirror of https://github.com/databricks/cli.git
Work in progress to automate doc generation
This commit is contained in:
parent
a014d50a6a
commit
53289dabdd
|
@ -0,0 +1,58 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"slices"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/databricks/databricks-sdk-go/service/serving"
|
||||||
|
)
|
||||||
|
|
||||||
|
func PromptMessage() ([]serving.ChatMessage, error) {
|
||||||
|
home, err := os.UserHomeDir()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
dir := filepath.Join(home, "emu/docs/source/dev-tools/cli")
|
||||||
|
files, err := filepath.Glob(filepath.Join(dir, "*.md"))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
messages := []string{`
|
||||||
|
You're helping write documentation for the Databricks CLI.
|
||||||
|
Forget everything you know about the Databricks CLI and start from scratch.
|
||||||
|
You'll be provided with all the information you need to write the documentation.
|
||||||
|
Example invocations must be wrapped in Markdown code blocks.
|
||||||
|
|
||||||
|
What follows is existing official documentation for the Databricks CLI.
|
||||||
|
`}
|
||||||
|
|
||||||
|
ignore := []string{
|
||||||
|
"completion-commands.md",
|
||||||
|
"migrate.md",
|
||||||
|
"bundle-commands.md",
|
||||||
|
}
|
||||||
|
for _, file := range files {
|
||||||
|
if slices.Contains(ignore, filepath.Base(file)) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
contents, err := os.ReadFile(file)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
messages = append(messages, fmt.Sprintf("File %s:\n\n------------%s\n------------", file, string(contents)))
|
||||||
|
}
|
||||||
|
|
||||||
|
return []serving.ChatMessage{
|
||||||
|
{
|
||||||
|
Role: serving.ChatMessageRoleSystem,
|
||||||
|
Content: strings.Join(messages, "\n\n"),
|
||||||
|
},
|
||||||
|
}, nil
|
||||||
|
}
|
|
@ -0,0 +1,60 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/databricks/cli/cmd"
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Group struct {
|
||||||
|
Name string
|
||||||
|
Package string
|
||||||
|
Command *cobra.Command
|
||||||
|
Subcommands []*cobra.Command
|
||||||
|
}
|
||||||
|
|
||||||
|
func Find(name string) *Group {
|
||||||
|
root := cmd.New(context.Background())
|
||||||
|
for _, c := range root.Commands() {
|
||||||
|
if c.Use != name {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
return &Group{
|
||||||
|
Name: name,
|
||||||
|
Package: c.Annotations["package"],
|
||||||
|
Command: c,
|
||||||
|
Subcommands: c.Commands(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *Group) Prompt() string {
|
||||||
|
msg := fmt.Sprintf(`
|
||||||
|
We're authoring documentation and examples for the "%s" command group.
|
||||||
|
|
||||||
|
All output must be valid Markdown.
|
||||||
|
|
||||||
|
Do not include expected command output; you don't know.
|
||||||
|
|
||||||
|
Every command has its own Markdown header.
|
||||||
|
|
||||||
|
The documentation should be written in Markdown, with code blocks for each command invocation.
|
||||||
|
By concatenating the code blocks, you should be able to run the script and see the output.
|
||||||
|
|
||||||
|
Below is the help output of each one of the commands.
|
||||||
|
`, Invocation(g.Command))
|
||||||
|
|
||||||
|
sep := "SEPARATOR BETWEEN INSTRUCTION AND HELP OUTPUT"
|
||||||
|
all := append([]*cobra.Command{g.Command}, g.Subcommands...)
|
||||||
|
for _, c := range all {
|
||||||
|
inv := Invocation(c)
|
||||||
|
msg += "\n\n" + sep + "\n\n$ " + inv + " --help\n\n" + CaptureHelp(c)
|
||||||
|
}
|
||||||
|
|
||||||
|
msg += "\n\n" + sep + "\n\n"
|
||||||
|
return msg
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
package main_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
main "github.com/databricks/cli/experimental/docs"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestGroupFind(t *testing.T) {
|
||||||
|
g := main.Find("catalogs")
|
||||||
|
require.NotNil(t, g)
|
||||||
|
assert.Equal(t, "catalogs", g.Name)
|
||||||
|
assert.Equal(t, "catalogs", g.Command.Use)
|
||||||
|
assert.Len(t, g.Subcommands, 5)
|
||||||
|
g.Command.CalledAs()
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"slices"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
)
|
||||||
|
|
||||||
|
func CaptureHelp(cmd *cobra.Command) string {
|
||||||
|
var buf bytes.Buffer
|
||||||
|
cmd.SetOut(&buf)
|
||||||
|
if err := cmd.Help(); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return buf.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
func Invocation(cmd *cobra.Command) string {
|
||||||
|
var args []string
|
||||||
|
|
||||||
|
for cmd != nil {
|
||||||
|
args = append(args, cmd.Use)
|
||||||
|
cmd = cmd.Parent()
|
||||||
|
}
|
||||||
|
|
||||||
|
slices.Reverse(args)
|
||||||
|
return strings.Join(args, " ")
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
package main_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/databricks/cli/cmd"
|
||||||
|
main "github.com/databricks/cli/experimental/docs"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestCaptureHelp(t *testing.T) {
|
||||||
|
c := cmd.New(context.Background())
|
||||||
|
h := main.CaptureHelp(c)
|
||||||
|
require.NotNil(t, h)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestInvocation(t *testing.T) {
|
||||||
|
g := main.Find("catalogs")
|
||||||
|
require.NotNil(t, g)
|
||||||
|
assert.Equal(t, "databricks catalogs", main.Invocation(g.Command))
|
||||||
|
}
|
|
@ -0,0 +1,89 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/databricks/databricks-sdk-go"
|
||||||
|
"github.com/databricks/databricks-sdk-go/service/serving"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
ctx := context.Background()
|
||||||
|
w, err := databricks.NewWorkspaceClient()
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
messages, err := PromptMessage()
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Please author Markdown documentation that first
|
||||||
|
// creates the necessary resources, demonstrates usage of the commands, and then
|
||||||
|
// finally cleans up the resources. Make sure to demonstrate usage of necessary flags. Remember to not delete
|
||||||
|
// the resource before demonstrating the other commands. If the final step is to delete the resource, then
|
||||||
|
// you can delete the resource at the end of the script.
|
||||||
|
|
||||||
|
g := Find("jobs")
|
||||||
|
contents := g.Prompt()
|
||||||
|
|
||||||
|
// contents += `
|
||||||
|
|
||||||
|
// The output should have the following structure:
|
||||||
|
|
||||||
|
// # <command group>
|
||||||
|
|
||||||
|
// <prose description of the command group>
|
||||||
|
|
||||||
|
// ## Quick start
|
||||||
|
|
||||||
|
// BEGIN
|
||||||
|
|
||||||
|
// <
|
||||||
|
// Markdown documentation that first creates the necessary resources, demonstrates usage of the commands, and then
|
||||||
|
// finally cleans up the resources. Make sure to demonstrate usage of necessary flags. Remember to not delete
|
||||||
|
// the resource before demonstrating the other commands. If the final step is to delete the resource, then
|
||||||
|
// you can delete the resource at the end of the script.
|
||||||
|
// Each command is a separate code block with prose separating them.
|
||||||
|
// Do not include command output; you don't know.
|
||||||
|
// Never use placeholders in the commands, but use for example "my_catalog" for a "CATALOG_NAME" placeholder.
|
||||||
|
// All code blocks concatenated should be runnable as a bash script.
|
||||||
|
// If commands depend on pre-existing resources, do not include the commands to create or destroy them,
|
||||||
|
// but call out this requirement in a comment.
|
||||||
|
// >
|
||||||
|
|
||||||
|
// END
|
||||||
|
// `
|
||||||
|
|
||||||
|
// `
|
||||||
|
// ## Commands
|
||||||
|
|
||||||
|
// <Markdown headers for each command, with the command name as the header text>
|
||||||
|
// `
|
||||||
|
|
||||||
|
contents += `
|
||||||
|
Output an executable Bash script that demonstrates how to use these commands.
|
||||||
|
Insert comments where you expect the user to have pre-existing resources.
|
||||||
|
`
|
||||||
|
|
||||||
|
messages = append(messages, serving.ChatMessage{
|
||||||
|
Role: serving.ChatMessageRoleUser,
|
||||||
|
Content: contents,
|
||||||
|
})
|
||||||
|
|
||||||
|
res, err := w.ServingEndpoints.Query(ctx, serving.QueryEndpointInput{
|
||||||
|
Name: "databricks-dbrx-instruct",
|
||||||
|
Messages: messages,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// enc := json.NewEncoder(os.Stdout)
|
||||||
|
// enc.SetIndent("", " ")
|
||||||
|
// enc.Encode(res)
|
||||||
|
|
||||||
|
fmt.Printf("Output: %s\n", res.Choices[0].Message.Content)
|
||||||
|
}
|
|
@ -0,0 +1,39 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"github.com/databricks/cli/cmd"
|
||||||
|
"golang.org/x/exp/maps"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Package struct {
|
||||||
|
Name string
|
||||||
|
Groups []*Group
|
||||||
|
}
|
||||||
|
|
||||||
|
func Packages() []Package {
|
||||||
|
root := cmd.New(context.Background())
|
||||||
|
packages := make(map[string]Package)
|
||||||
|
for _, c := range root.Commands() {
|
||||||
|
pkg := c.Annotations["package"]
|
||||||
|
if pkg == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
g := Find(c.Use)
|
||||||
|
p, ok := packages[pkg]
|
||||||
|
if !ok {
|
||||||
|
p = Package{
|
||||||
|
Name: pkg,
|
||||||
|
Groups: []*Group{g},
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
p.Groups = append(p.Groups, g)
|
||||||
|
}
|
||||||
|
|
||||||
|
packages[pkg] = p
|
||||||
|
}
|
||||||
|
|
||||||
|
return maps.Values(packages)
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
package main_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
main "github.com/databricks/cli/experimental/docs"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestPackagesAll(t *testing.T) {
|
||||||
|
pkgs := main.Packages()
|
||||||
|
require.NotEmpty(t, pkgs)
|
||||||
|
}
|
Loading…
Reference in New Issue