Skip to content
Merged
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: 1 addition & 1 deletion .github/workflows/lint.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,4 @@ jobs:
- name: golangci-lint
uses: golangci/golangci-lint-action@v8
with:
version: v1.54.2
version: v2.1
2 changes: 1 addition & 1 deletion cmd/bundle.go
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,7 @@ func runBundleNew(input *bundleNew) {
}
gqlclient := api.NewClient(c.URL, c.APIKey)

artifactDefs, err := api.GetArtifactDefinitions(gqlclient, c.OrgID)
artifactDefs, err := api.ListArtifactDefinitions(gqlclient, c.OrgID)
if err != nil {
log.Fatal(err)
}
Expand Down
117 changes: 112 additions & 5 deletions cmd/definition.go
Original file line number Diff line number Diff line change
@@ -1,16 +1,27 @@
package cmd

import (
"bytes"
"embed"
"encoding/json"
"fmt"
"os"
"text/template"

"github.com/charmbracelet/glamour"
"github.com/massdriver-cloud/mass/docs/helpdocs"
"github.com/massdriver-cloud/mass/pkg/api"
"github.com/massdriver-cloud/mass/pkg/cli"
"github.com/massdriver-cloud/mass/pkg/config"
"github.com/massdriver-cloud/mass/pkg/definition"
"github.com/massdriver-cloud/mass/pkg/restclient"
"github.com/mitchellh/mapstructure"
"github.com/spf13/cobra"
)

//go:embed templates/definition.get.md.tmpl
var definitionTemplates embed.FS

func NewCmdDefinition() *cobra.Command {
definitionCmd := &cobra.Command{
Use: "definition",
Expand All @@ -22,13 +33,23 @@ func NewCmdDefinition() *cobra.Command {
definitionGetCmd := &cobra.Command{
Use: "get [definition]",
Short: "Get an artifact definition from Massdriver",
Long: helpdocs.MustRender("definition/get"),
Args: cobra.ExactArgs(1),
RunE: runDefinitionGet,
}
definitionGetCmd.Flags().StringP("output", "o", "text", "Output format (text or json)")

definitionListCmd := &cobra.Command{
Use: "list [definition]",
Short: "List artifact definitions",
Long: helpdocs.MustRender("definition/list"),
RunE: runDefinitionList,
}

definitionPublishCmd := &cobra.Command{
Use: "publish",
Short: "Publish an artifact definition to Massdriver",
Long: helpdocs.MustRender("definition/publish"),
RunE: runDefinitionPublish,
SilenceUsage: true,
}
Expand All @@ -37,26 +58,47 @@ func NewCmdDefinition() *cobra.Command {

definitionCmd.AddCommand(definitionGetCmd)
definitionCmd.AddCommand(definitionPublishCmd)
definitionCmd.AddCommand(definitionListCmd)

return definitionCmd
}

func runDefinitionGet(cmd *cobra.Command, args []string) error {
definitionName := args[0]
outputFormat, err := cmd.Flags().GetString("output")
if err != nil {
return err
}

c := restclient.NewClient()

def, err := definition.Get(c, definitionName)
// debt: switch to reading from the graphql API, it has more data in it than the old rest endpoint.
adMap, err := definition.Get(c, definitionName)
if err != nil {
return err
}

bytes, err := json.Marshal(def)
if err != nil {
return err
// Convert map to ArtifactDefinitionWithSchema
var ad api.ArtifactDefinitionWithSchema
if err := mapstructure.Decode(adMap, &ad); err != nil {
return fmt.Errorf("failed to decode definition: %w", err)
}

fmt.Println(string(bytes))
switch outputFormat {
case "json":
jsonBytes, err := json.MarshalIndent(ad, "", " ")
if err != nil {
return fmt.Errorf("failed to marshal definition to JSON: %w", err)
}
fmt.Println(string(jsonBytes))
case "text":
err = renderDefinition(&ad)
if err != nil {
return err
}
default:
return fmt.Errorf("unsupported output format: %s", outputFormat)
}

return nil
}
Expand Down Expand Up @@ -88,3 +130,68 @@ func runDefinitionPublish(cmd *cobra.Command, args []string) error {

return nil
}

func runDefinitionList(cmd *cobra.Command, args []string) error {
config, configErr := config.Get()
if configErr != nil {
return configErr
}

client := api.NewClient(config.URL, config.APIKey)
definitions, err := api.ListArtifactDefinitions(client, config.OrgID)

tbl := cli.NewTable("Name", "Label", "Updated At")

for _, definition := range definitions {
tbl.AddRow(definition.Name, definition.Label, definition.UpdatedAt)
}

tbl.Print()

return err
}

func renderDefinition(ad *api.ArtifactDefinitionWithSchema) error {
schemaJSON, err := json.MarshalIndent(ad.Schema, "", " ")
if err != nil {
return err
}

tmplBytes, err := definitionTemplates.ReadFile("templates/definition.get.md.tmpl")
if err != nil {
return fmt.Errorf("failed to read template: %w", err)
}

tmpl, err := template.New("definition").Parse(string(tmplBytes))
if err != nil {
return fmt.Errorf("failed to parse template: %w", err)
}

data := struct {
Label string
Name string
SchemaJSON string
}{
Label: ad.Label,
Name: ad.Name,
SchemaJSON: string(schemaJSON),
}

var buf bytes.Buffer
if err := tmpl.Execute(&buf, data); err != nil {
return fmt.Errorf("failed to execute template: %w", err)
}

r, err := glamour.NewTermRenderer(glamour.WithAutoStyle())
if err != nil {
return err
}

out, err := r.Render(buf.String())
if err != nil {
return err
}

fmt.Print(out)
return nil
}
55 changes: 39 additions & 16 deletions cmd/package.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
package cmd

import (
"bytes"
"embed"
"encoding/json"
"fmt"
"text/template"

"github.com/charmbracelet/glamour"
"github.com/charmbracelet/lipgloss"
Expand All @@ -21,6 +24,9 @@ var (
pkgPatchQueries []string
)

//go:embed templates/package.get.md.tmpl
var packageTemplates embed.FS

func NewCmdPkg() *cobra.Command {
pkgCmd := &cobra.Command{
Use: "package",
Expand Down Expand Up @@ -70,6 +76,7 @@ func NewCmdPkg() *cobra.Command {
Args: cobra.ExactArgs(1), // Enforce exactly one argument
RunE: runPkgGet,
}
pkgGetCmd.Flags().StringP("output", "o", "text", "Output format (text or json)")

pkgCmd.AddCommand(pkgDeployCmd)
pkgCmd.AddCommand(pkgConfigureCmd)
Expand All @@ -85,44 +92,60 @@ func runPkgGet(cmd *cobra.Command, args []string) error {
return configErr
}

outputFormat, err := cmd.Flags().GetString("output")
if err != nil {
return err
}

client := api.NewClient(config.URL, config.APIKey)
pkgID := args[0]

pkg, err := api.GetPackageByName(client, config.OrgID, pkgID)

if err != nil {
return err
}

err = renderPackage(pkg)
switch outputFormat {
case "json":
jsonBytes, err := json.MarshalIndent(pkg, "", " ")
if err != nil {
return fmt.Errorf("failed to marshal package to JSON: %w", err)
}
fmt.Println(string(jsonBytes))
case "text":
err = renderPackage(pkg)
if err != nil {
return err
}
default:
return fmt.Errorf("unsupported output format: %s", outputFormat)
}

return err
return nil
}

func renderPackage(pkg *api.Package) error {
paramsJSON, err := json.MarshalIndent(pkg.Params, "", " ")
tmplBytes, err := packageTemplates.ReadFile("templates/package.get.md.tmpl")
if err != nil {
return err
return fmt.Errorf("failed to read template: %w", err)
}

md := fmt.Sprintf(`# Package: %s

**Bundle:** %s

**Environment:** %s
tmpl, err := template.New("package").Parse(string(tmplBytes))
if err != nil {
return fmt.Errorf("failed to parse template: %w", err)
}

## Parameters
`+"```json"+`
%s
`+"```"+`
`, pkg.NamePrefix, pkg.Manifest.Bundle.Name, pkg.Environment.Slug, string(paramsJSON))
var buf bytes.Buffer
if err := tmpl.Execute(&buf, pkg); err != nil {
return fmt.Errorf("failed to execute template: %w", err)
}

r, err := glamour.NewTermRenderer(glamour.WithAutoStyle())
if err != nil {
return err
}

out, err := r.Render(md)
out, err := r.Render(buf.String())
if err != nil {
return err
}
Expand Down
Loading
Loading