mirror of
https://github.com/foomo/sesamy-cli.git
synced 2025-10-16 12:35:36 +00:00
feat: add open & diff command
This commit is contained in:
parent
c6f5292df3
commit
5fdd26d867
23
cmd/diff.go
Normal file
23
cmd/diff.go
Normal file
@ -0,0 +1,23 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"log/slog"
|
||||
|
||||
"github.com/foomo/sesamy-cli/cmd/diff"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// NewDiff represents the diff command
|
||||
func NewDiff(l *slog.Logger) *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "diff",
|
||||
Short: "Print Google Tag Manager container status diff",
|
||||
}
|
||||
|
||||
cmd.AddCommand(
|
||||
diff.NewWeb(l),
|
||||
diff.NewServer(l),
|
||||
)
|
||||
|
||||
return cmd
|
||||
}
|
||||
396
cmd/diff/diff.go
Normal file
396
cmd/diff/diff.go
Normal file
@ -0,0 +1,396 @@
|
||||
package diff
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"log/slog"
|
||||
"strings"
|
||||
|
||||
"github.com/foomo/sesamy-cli/pkg/tagmanager"
|
||||
"github.com/itchyny/json2yaml"
|
||||
"github.com/sters/yaml-diff/yamldiff"
|
||||
)
|
||||
|
||||
func diff(ctx context.Context, l *slog.Logger, tm *tagmanager.TagManager) (string, error) {
|
||||
l.Info("└ ⬇︎ Loading status")
|
||||
s, err := tm.Service().Accounts.Containers.Workspaces.GetStatus(tm.WorkspacePath()).Context(ctx).Do()
|
||||
if err != nil {
|
||||
return "", err
|
||||
} else if len(s.WorkspaceChange) == 0 {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
l.Info("└ ⬇︎ Loading live version")
|
||||
live, err := tm.Service().Accounts.Containers.Versions.Live(tm.ContainerPath()).Do()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
var res []string
|
||||
for _, entity := range s.WorkspaceChange {
|
||||
switch {
|
||||
case entity.Tag != nil:
|
||||
res = append(res, " # Tag: "+entity.Tag.Name+" ("+entity.ChangeStatus+")\n")
|
||||
|
||||
// unset props
|
||||
entity.Tag.Path = ""
|
||||
entity.Tag.Fingerprint = ""
|
||||
entity.Tag.WorkspaceId = ""
|
||||
entity.Tag.TagManagerUrl = ""
|
||||
|
||||
var changed string
|
||||
if entity.ChangeStatus != "deleted" {
|
||||
changed, err = ToYalm(entity.Tag)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
|
||||
var original string
|
||||
for _, value := range live.Tag {
|
||||
if value.Name == entity.Tag.Name {
|
||||
// unset props
|
||||
value.Fingerprint = ""
|
||||
|
||||
original, err = ToYalm(value)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
d, err := ToDiff(original, changed)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
res = append(res, d...)
|
||||
case entity.Folder != nil:
|
||||
res = append(res, " # Folder: "+entity.Folder.Name+" ("+entity.ChangeStatus+")")
|
||||
|
||||
// unset props
|
||||
entity.Folder.Path = ""
|
||||
entity.Folder.Fingerprint = ""
|
||||
entity.Folder.WorkspaceId = ""
|
||||
entity.Folder.TagManagerUrl = ""
|
||||
|
||||
var changed string
|
||||
if entity.ChangeStatus != "deleted" {
|
||||
changed, err = ToYalm(entity.Folder)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
|
||||
var original string
|
||||
for _, value := range live.Folder {
|
||||
if value.Name == entity.Folder.Name {
|
||||
// unset props
|
||||
value.Fingerprint = ""
|
||||
|
||||
original, err = ToYalm(value)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
d, err := ToDiff(original, changed)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
res = append(res, d...)
|
||||
case entity.Trigger != nil:
|
||||
res = append(res, " # Trigger: "+entity.Trigger.Name+" ("+entity.ChangeStatus+")")
|
||||
|
||||
// unset props
|
||||
entity.Trigger.Path = ""
|
||||
entity.Trigger.Fingerprint = ""
|
||||
entity.Trigger.WorkspaceId = ""
|
||||
entity.Trigger.TagManagerUrl = ""
|
||||
|
||||
var changed string
|
||||
if entity.ChangeStatus != "deleted" {
|
||||
changed, err = ToYalm(entity.Trigger)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
|
||||
var original string
|
||||
for _, value := range live.Trigger {
|
||||
if value.Name == entity.Trigger.Name {
|
||||
// unset props
|
||||
value.Fingerprint = ""
|
||||
|
||||
original, err = ToYalm(value)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
d, err := ToDiff(original, changed)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
res = append(res, d...)
|
||||
case entity.Variable != nil:
|
||||
res = append(res, " # Variable: "+entity.Variable.Name+" ("+entity.ChangeStatus+")")
|
||||
|
||||
// unset props
|
||||
entity.Variable.Path = ""
|
||||
entity.Variable.Fingerprint = ""
|
||||
entity.Variable.WorkspaceId = ""
|
||||
entity.Variable.TagManagerUrl = ""
|
||||
|
||||
var changed string
|
||||
if entity.ChangeStatus != "deleted" {
|
||||
changed, err = ToYalm(entity.Variable)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
|
||||
var original string
|
||||
for _, value := range live.Variable {
|
||||
if value.Name == entity.Variable.Name {
|
||||
// unset props
|
||||
value.Fingerprint = ""
|
||||
|
||||
original, err = ToYalm(value)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
d, err := ToDiff(original, changed)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
res = append(res, d...)
|
||||
case entity.Client != nil:
|
||||
res = append(res, " # Client: "+entity.Client.Name+" ("+entity.ChangeStatus+")")
|
||||
|
||||
// unset props
|
||||
entity.Client.Path = ""
|
||||
entity.Client.Fingerprint = ""
|
||||
entity.Client.WorkspaceId = ""
|
||||
entity.Client.TagManagerUrl = ""
|
||||
|
||||
var changed string
|
||||
if entity.ChangeStatus != "deleted" {
|
||||
changed, err = ToYalm(entity.Client)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
|
||||
var original string
|
||||
for _, value := range live.Client {
|
||||
if value.Name == entity.Client.Name {
|
||||
// unset props
|
||||
value.Fingerprint = ""
|
||||
|
||||
original, err = ToYalm(value)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
d, err := ToDiff(original, changed)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
res = append(res, d...)
|
||||
case entity.GtagConfig != nil:
|
||||
res = append(res, " # GtagConfig: "+entity.GtagConfig.AccountId+" ("+entity.ChangeStatus+")")
|
||||
|
||||
// unset props
|
||||
entity.GtagConfig.Path = ""
|
||||
entity.GtagConfig.Fingerprint = ""
|
||||
entity.GtagConfig.WorkspaceId = ""
|
||||
entity.GtagConfig.TagManagerUrl = ""
|
||||
|
||||
var changed string
|
||||
if entity.ChangeStatus != "deleted" {
|
||||
changed, err = ToYalm(entity.GtagConfig)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
|
||||
var original string
|
||||
for _, value := range live.GtagConfig {
|
||||
if value.AccountId == entity.GtagConfig.AccountId {
|
||||
// unset props
|
||||
value.Fingerprint = ""
|
||||
|
||||
original, err = ToYalm(value)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
d, err := ToDiff(original, changed)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
res = append(res, d...)
|
||||
case entity.BuiltInVariable != nil:
|
||||
res = append(res, " # BuiltInVariable: "+entity.BuiltInVariable.Name+" ("+entity.ChangeStatus+")")
|
||||
|
||||
// unset props
|
||||
entity.BuiltInVariable.Path = ""
|
||||
entity.BuiltInVariable.WorkspaceId = ""
|
||||
|
||||
var changed string
|
||||
if entity.ChangeStatus != "deleted" {
|
||||
changed, err = ToYalm(entity.BuiltInVariable)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
|
||||
var original string
|
||||
for _, value := range live.BuiltInVariable {
|
||||
if value.Name == entity.BuiltInVariable.Name {
|
||||
original, err = ToYalm(value)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
d, err := ToDiff(original, changed)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
res = append(res, d...)
|
||||
case entity.CustomTemplate != nil:
|
||||
res = append(res, " # CustomTemplate: "+entity.CustomTemplate.Name+" ("+entity.ChangeStatus+")")
|
||||
|
||||
// unset props
|
||||
entity.CustomTemplate.Path = ""
|
||||
entity.CustomTemplate.Fingerprint = ""
|
||||
entity.CustomTemplate.WorkspaceId = ""
|
||||
entity.CustomTemplate.TagManagerUrl = ""
|
||||
|
||||
var changed string
|
||||
if entity.ChangeStatus != "deleted" {
|
||||
changed, err = ToYalm(entity.CustomTemplate)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
|
||||
var original string
|
||||
for _, value := range live.CustomTemplate {
|
||||
if value.Name == entity.CustomTemplate.Name {
|
||||
// unset props
|
||||
value.Fingerprint = ""
|
||||
|
||||
original, err = ToYalm(value)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
d, err := ToDiff(original, changed)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
res = append(res, d...)
|
||||
case entity.Transformation != nil:
|
||||
res = append(res, " # Transformation: "+entity.Transformation.Name+" ("+entity.ChangeStatus+")")
|
||||
|
||||
// unset props
|
||||
entity.Transformation.Path = ""
|
||||
entity.Transformation.Fingerprint = ""
|
||||
entity.Transformation.WorkspaceId = ""
|
||||
entity.Transformation.TagManagerUrl = ""
|
||||
|
||||
var changed string
|
||||
if entity.ChangeStatus != "deleted" {
|
||||
changed, err = ToYalm(entity.Transformation)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
|
||||
var original string
|
||||
for _, value := range live.Transformation {
|
||||
if value.Name == entity.Transformation.Name {
|
||||
// unset props
|
||||
value.Fingerprint = ""
|
||||
|
||||
original, err = ToYalm(value)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
d, err := ToDiff(original, changed)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
res = append(res, d...)
|
||||
}
|
||||
}
|
||||
return strings.Join(res, " ---\n"), nil
|
||||
}
|
||||
|
||||
type Marshelable interface {
|
||||
MarshalJSON() ([]byte, error)
|
||||
}
|
||||
|
||||
func ToDiff(original, changed string) ([]string, error) {
|
||||
yamls1, err := yamldiff.Load(original)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
yamls2, err := yamldiff.Load(changed)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var ret []string
|
||||
for _, d := range yamldiff.Do(yamls1, yamls2) {
|
||||
if value := d.Dump(); len(value) > 4 {
|
||||
ret = append(ret, value)
|
||||
}
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func ToYalm(m Marshelable) (string, error) {
|
||||
if m == nil {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
out, err := m.MarshalJSON()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
var ret bytes.Buffer
|
||||
if err := json2yaml.Convert(&ret, bytes.NewBuffer(out)); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return ret.String(), nil
|
||||
}
|
||||
68
cmd/diff/server.go
Normal file
68
cmd/diff/server.go
Normal file
@ -0,0 +1,68 @@
|
||||
package diff
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log/slog"
|
||||
|
||||
pkgcmd "github.com/foomo/sesamy-cli/pkg/cmd"
|
||||
"github.com/foomo/sesamy-cli/pkg/tagmanager"
|
||||
"github.com/foomo/sesamy-cli/pkg/utils"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
// NewServer represents the server command
|
||||
func NewServer(l *slog.Logger) *cobra.Command {
|
||||
c := viper.New()
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "server",
|
||||
Short: "Print Google Tag Manager Server Container status diff",
|
||||
Args: cobra.NoArgs,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
l.Info("☕ Retrieving Server Container status")
|
||||
|
||||
cfg, err := pkgcmd.ReadConfig(l, c, cmd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
tm, err := tagmanager.New(
|
||||
cmd.Context(),
|
||||
l,
|
||||
cfg.GoogleTagManager.AccountID,
|
||||
cfg.GoogleTagManager.ServerContainer,
|
||||
tagmanager.WithRequestQuota(cfg.GoogleAPI.RequestQuota),
|
||||
tagmanager.WithClientOptions(cfg.GoogleAPI.GetClientOption()),
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := tm.EnsureWorkspaceID(cmd.Context()); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
out, err := diff(cmd.Context(), l, tm)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !c.GetBool("raw") {
|
||||
out = utils.Highlight(out)
|
||||
}
|
||||
_, err = fmt.Println(out)
|
||||
return err
|
||||
},
|
||||
}
|
||||
|
||||
flags := cmd.Flags()
|
||||
|
||||
flags.Bool("raw", false, "print raw output")
|
||||
_ = c.BindPFlag("raw", flags.Lookup("raw"))
|
||||
|
||||
flags.StringSliceP("config", "c", []string{"sesamy.yaml"}, "config files (default is sesamy.yaml)")
|
||||
_ = c.BindPFlag("config", flags.Lookup("config"))
|
||||
|
||||
return cmd
|
||||
}
|
||||
68
cmd/diff/web.go
Normal file
68
cmd/diff/web.go
Normal file
@ -0,0 +1,68 @@
|
||||
package diff
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log/slog"
|
||||
|
||||
pkgcmd "github.com/foomo/sesamy-cli/pkg/cmd"
|
||||
"github.com/foomo/sesamy-cli/pkg/tagmanager"
|
||||
"github.com/foomo/sesamy-cli/pkg/utils"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
// NewWeb represents the web command
|
||||
func NewWeb(l *slog.Logger) *cobra.Command {
|
||||
c := viper.New()
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "web",
|
||||
Short: "Print Google Tag Manager Web Container status diff",
|
||||
Args: cobra.NoArgs,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
l.Info("☕ Retrieving Web Container status")
|
||||
|
||||
cfg, err := pkgcmd.ReadConfig(l, c, cmd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
tm, err := tagmanager.New(
|
||||
cmd.Context(),
|
||||
l,
|
||||
cfg.GoogleTagManager.AccountID,
|
||||
cfg.GoogleTagManager.WebContainer,
|
||||
tagmanager.WithRequestQuota(cfg.GoogleAPI.RequestQuota),
|
||||
tagmanager.WithClientOptions(cfg.GoogleAPI.GetClientOption()),
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := tm.EnsureWorkspaceID(cmd.Context()); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
out, err := diff(cmd.Context(), l, tm)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !c.GetBool("raw") {
|
||||
out = utils.Highlight(out)
|
||||
}
|
||||
_, err = fmt.Println(out)
|
||||
return err
|
||||
},
|
||||
}
|
||||
|
||||
flags := cmd.Flags()
|
||||
|
||||
flags.Bool("raw", false, "print raw output")
|
||||
_ = c.BindPFlag("raw", flags.Lookup("raw"))
|
||||
|
||||
flags.StringSliceP("config", "c", []string{"sesamy.yaml"}, "config files (default is sesamy.yaml)")
|
||||
_ = c.BindPFlag("config", flags.Lookup("config"))
|
||||
|
||||
return cmd
|
||||
}
|
||||
@ -5,42 +5,34 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/alecthomas/chroma/quick"
|
||||
"github.com/foomo/sesamy-cli/pkg/tagmanager"
|
||||
"github.com/itchyny/json2yaml"
|
||||
)
|
||||
|
||||
func dump(i interface{ MarshalJSON() ([]byte, error) }, err error) error {
|
||||
func dump(i interface{ MarshalJSON() ([]byte, error) }, err error) (string, error) {
|
||||
if err != nil {
|
||||
return err
|
||||
return "", err
|
||||
}
|
||||
out, err := i.MarshalJSON()
|
||||
if err != nil {
|
||||
return err
|
||||
return "", err
|
||||
}
|
||||
// if err := json.Indent(ret, out, "", " "); err != nil {
|
||||
// return err
|
||||
// }
|
||||
// fmt.Println(ret.String())
|
||||
|
||||
var output strings.Builder
|
||||
if err := json2yaml.Convert(&output, bytes.NewBuffer(out)); err != nil {
|
||||
return err
|
||||
return "", err
|
||||
}
|
||||
// fmt.Print(output.String())
|
||||
return quick.Highlight(os.Stdout, output.String(), "yaml", "terminal", "monokai")
|
||||
return output.String(), nil
|
||||
}
|
||||
|
||||
func list(ctx context.Context, l *slog.Logger, tm *tagmanager.TagManager, resource string) error {
|
||||
func list(ctx context.Context, l *slog.Logger, tm *tagmanager.TagManager, resource string) (string, error) {
|
||||
switch resource {
|
||||
case "environments":
|
||||
return dump(tm.Service().Accounts.Containers.Environments.List(tm.ContainerPath()).Context(ctx).Do())
|
||||
case "workspaces":
|
||||
return dump(tm.Service().Accounts.Containers.Workspaces.List(tm.ContainerPath()).Context(ctx).Do())
|
||||
case "status":
|
||||
return dump(tm.Service().Accounts.Containers.Workspaces.GetStatus(tm.WorkspacePath()).Context(ctx).Do())
|
||||
case "clients":
|
||||
return dump(tm.Service().Accounts.Containers.Workspaces.Clients.List(tm.WorkspacePath()).Context(ctx).Do())
|
||||
case "tags":
|
||||
@ -56,13 +48,14 @@ func list(ctx context.Context, l *slog.Logger, tm *tagmanager.TagManager, resour
|
||||
case "templates-data":
|
||||
r, err := tm.Service().Accounts.Containers.Workspaces.Templates.List(tm.WorkspacePath()).Context(ctx).Do()
|
||||
if err != nil {
|
||||
return err
|
||||
return "", err
|
||||
}
|
||||
var ret strings.Builder
|
||||
for _, template := range r.Template {
|
||||
l.Info("---- Template data: " + template.Name + " ----------------------")
|
||||
fmt.Println(template.TemplateData)
|
||||
ret.WriteString("---- Template data: " + template.Name + " ----------------------\n")
|
||||
ret.WriteString(template.TemplateData + "\n")
|
||||
}
|
||||
return nil
|
||||
return ret.String(), nil
|
||||
case "gtag-config":
|
||||
return dump(tm.Service().Accounts.Containers.Workspaces.GtagConfig.List(tm.WorkspacePath()).Context(ctx).Do())
|
||||
case "triggers":
|
||||
@ -72,6 +65,6 @@ func list(ctx context.Context, l *slog.Logger, tm *tagmanager.TagManager, resour
|
||||
case "zones":
|
||||
return dump(tm.Service().Accounts.Containers.Workspaces.Zones.List(tm.WorkspacePath()).Context(ctx).Do())
|
||||
default:
|
||||
return fmt.Errorf("unknown resource %s", resource)
|
||||
return "", fmt.Errorf("unknown resource %s", resource)
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,10 +1,12 @@
|
||||
package list
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log/slog"
|
||||
|
||||
pkgcmd "github.com/foomo/sesamy-cli/pkg/cmd"
|
||||
"github.com/foomo/sesamy-cli/pkg/tagmanager"
|
||||
"github.com/foomo/sesamy-cli/pkg/utils"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
@ -58,12 +60,24 @@ func NewServer(l *slog.Logger) *cobra.Command {
|
||||
return err
|
||||
}
|
||||
|
||||
return list(cmd.Context(), l, tm, resource)
|
||||
out, err := list(cmd.Context(), l, tm, resource)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !c.GetBool("raw") {
|
||||
out = utils.Highlight(out)
|
||||
}
|
||||
_, err = fmt.Println(out)
|
||||
return err
|
||||
},
|
||||
}
|
||||
|
||||
flags := cmd.Flags()
|
||||
|
||||
flags.Bool("raw", false, "print raw output")
|
||||
_ = c.BindPFlag("raw", flags.Lookup("raw"))
|
||||
|
||||
flags.StringSliceP("config", "c", []string{"sesamy.yaml"}, "config files (default is sesamy.yaml)")
|
||||
_ = c.BindPFlag("config", flags.Lookup("config"))
|
||||
|
||||
|
||||
@ -1,10 +1,12 @@
|
||||
package list
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log/slog"
|
||||
|
||||
pkgcmd "github.com/foomo/sesamy-cli/pkg/cmd"
|
||||
"github.com/foomo/sesamy-cli/pkg/tagmanager"
|
||||
"github.com/foomo/sesamy-cli/pkg/utils"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
@ -57,12 +59,24 @@ func NewWeb(l *slog.Logger) *cobra.Command {
|
||||
return err
|
||||
}
|
||||
|
||||
return list(cmd.Context(), l, tm, resource)
|
||||
out, err := list(cmd.Context(), l, tm, resource)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !c.GetBool("raw") {
|
||||
out = utils.Highlight(out)
|
||||
}
|
||||
_, err = fmt.Println(out)
|
||||
return err
|
||||
},
|
||||
}
|
||||
|
||||
flags := cmd.Flags()
|
||||
|
||||
flags.Bool("raw", false, "print raw output")
|
||||
_ = c.BindPFlag("raw", flags.Lookup("raw"))
|
||||
|
||||
flags.StringSliceP("config", "c", []string{"sesamy.yaml"}, "config files (default is sesamy.yaml)")
|
||||
_ = c.BindPFlag("config", flags.Lookup("config"))
|
||||
|
||||
|
||||
70
cmd/open.go
Normal file
70
cmd/open.go
Normal file
@ -0,0 +1,70 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log/slog"
|
||||
|
||||
pkgcmd "github.com/foomo/sesamy-cli/pkg/cmd"
|
||||
"github.com/pkg/browser"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
// NewOpen represents the open command
|
||||
func NewOpen(l *slog.Logger) *cobra.Command {
|
||||
c := viper.New()
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "open",
|
||||
Short: "Open links in the browser",
|
||||
Args: cobra.OnlyValidArgs,
|
||||
ValidArgs: []cobra.Completion{
|
||||
"ga",
|
||||
"gtm-web",
|
||||
"gtm-server",
|
||||
},
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
cfg, err := pkgcmd.ReadConfig(l, c, cmd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var url string
|
||||
switch args[0] {
|
||||
case "ga":
|
||||
if cfg.GoogleAnalytics.PropertyID == "" {
|
||||
return fmt.Errorf("missing Google Analytics Property ID")
|
||||
}
|
||||
url = fmt.Sprintf(
|
||||
"https://analytics.google.com/analytics/web/#/p%s/",
|
||||
cfg.GoogleAnalytics.PropertyID,
|
||||
)
|
||||
case "gtm-web":
|
||||
url = fmt.Sprintf(
|
||||
"https://tagmanager.google.com/#/container/accounts/%s/containers/%s/",
|
||||
cfg.GoogleTagManager.AccountID,
|
||||
cfg.GoogleTagManager.WebContainer.ContainerID,
|
||||
)
|
||||
case "gtm-server":
|
||||
url = fmt.Sprintf(
|
||||
"https://tagmanager.google.com/#/container/accounts/%s/containers/%s/",
|
||||
cfg.GoogleTagManager.AccountID,
|
||||
cfg.GoogleTagManager.ServerContainer.ContainerID,
|
||||
)
|
||||
default:
|
||||
return fmt.Errorf("invalid container type: %s", args[0])
|
||||
}
|
||||
|
||||
l.Info("↗ Navigating to Google Tag Manager Container: " + url)
|
||||
|
||||
return browser.OpenURL(url)
|
||||
},
|
||||
}
|
||||
|
||||
flags := cmd.Flags()
|
||||
|
||||
flags.StringSliceP("config", "c", []string{"sesamy.yaml"}, "config files (default is sesamy.yaml)")
|
||||
_ = c.BindPFlag("config", flags.Lookup("config"))
|
||||
|
||||
return cmd
|
||||
}
|
||||
3
go.mod
3
go.mod
@ -16,10 +16,12 @@ require (
|
||||
github.com/knadh/koanf/providers/file v1.2.0
|
||||
github.com/knadh/koanf/providers/rawbytes v1.0.0
|
||||
github.com/knadh/koanf/v2 v2.2.0
|
||||
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/pterm/pterm v0.12.80
|
||||
github.com/spf13/cobra v1.9.1
|
||||
github.com/spf13/viper v1.20.1
|
||||
github.com/sters/yaml-diff v1.4.1
|
||||
github.com/stoewer/go-strcase v1.3.0
|
||||
github.com/stretchr/testify v1.10.0
|
||||
github.com/wissance/stringFormatter v1.4.1
|
||||
@ -45,6 +47,7 @@ require (
|
||||
github.com/go-logr/logr v1.4.2 // indirect
|
||||
github.com/go-logr/stdr v1.2.2 // indirect
|
||||
github.com/go-viper/mapstructure/v2 v2.2.1 // indirect
|
||||
github.com/goccy/go-yaml v1.15.6 // indirect
|
||||
github.com/google/s2a-go v0.1.9 // indirect
|
||||
github.com/google/uuid v1.6.0 // indirect
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.6 // indirect
|
||||
|
||||
6
go.sum
6
go.sum
@ -66,6 +66,8 @@ github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
||||
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
|
||||
github.com/go-viper/mapstructure/v2 v2.2.1 h1:ZAaOCxANMuZx5RCeg0mBdEZk7DZasvvZIxtHqx8aGss=
|
||||
github.com/go-viper/mapstructure/v2 v2.2.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
|
||||
github.com/goccy/go-yaml v1.15.6 h1:gy5kf1yjMia3/c3wWD+u1z3lU5XlhpT8FZGaLJU9cOA=
|
||||
github.com/goccy/go-yaml v1.15.6/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA=
|
||||
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
|
||||
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
|
||||
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
@ -129,6 +131,8 @@ github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zx
|
||||
github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
|
||||
github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4=
|
||||
github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY=
|
||||
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ=
|
||||
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
@ -165,6 +169,8 @@ github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o=
|
||||
github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/spf13/viper v1.20.1 h1:ZMi+z/lvLyPSCoNtFCpqjy0S4kPbirhpTMwl8BkW9X4=
|
||||
github.com/spf13/viper v1.20.1/go.mod h1:P9Mdzt1zoHIG8m2eZQinpiBjo6kCmZSKBClNNqjJvu4=
|
||||
github.com/sters/yaml-diff v1.4.1 h1:0W3jnFKCu8/DV7nh2aXSDA2VVfxfHu2+qdh81CuFmZo=
|
||||
github.com/sters/yaml-diff v1.4.1/go.mod h1:K286Xp2z+aGkok7z9k3zXcq0ZsrDaDp7/wyGwFjM9Y8=
|
||||
github.com/stoewer/go-strcase v1.3.0 h1:g0eASXYtp+yvN9fK8sH94oCIk0fau9uV1/ZdJ0AVEzs=
|
||||
github.com/stoewer/go-strcase v1.3.0/go.mod h1:fAH5hQ5pehh+j3nZfvwdk2RgEgQjAoM8wodgtPmh1xo=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
|
||||
2
main.go
2
main.go
@ -19,6 +19,8 @@ func main() {
|
||||
root.AddCommand(
|
||||
cmd.NewConfig(l),
|
||||
cmd.NewList(l),
|
||||
cmd.NewDiff(l),
|
||||
cmd.NewOpen(l),
|
||||
cmd.NewProvision(l),
|
||||
cmd.NewTags(l),
|
||||
cmd.NewTypeScript(l),
|
||||
|
||||
@ -7,6 +7,10 @@ import (
|
||||
type GoogleAnalytics struct {
|
||||
// Enable provider
|
||||
Enabled bool `json:"enabled" yaml:"enabled"`
|
||||
// Google Analytics account id
|
||||
AccountID string `json:"accountId" yaml:"accountId"`
|
||||
// Google Analytics property id
|
||||
PropertyID string `json:"propertyId" yaml:"propertyId"`
|
||||
// Google Consent settings
|
||||
GoogleConsent GoogleConsent `json:"googleConsent" yaml:"googleConsent"`
|
||||
// GTag.js override configuration
|
||||
|
||||
98
pkg/utils/highlight.go
Normal file
98
pkg/utils/highlight.go
Normal file
@ -0,0 +1,98 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
|
||||
"github.com/alecthomas/chroma"
|
||||
"github.com/alecthomas/chroma/formatters"
|
||||
"github.com/alecthomas/chroma/lexers"
|
||||
"github.com/alecthomas/chroma/styles"
|
||||
"github.com/pterm/pterm"
|
||||
)
|
||||
|
||||
func Highlight(source string) string {
|
||||
out := &numberWriter{
|
||||
w: bytes.NewBufferString(""),
|
||||
currentLine: 1,
|
||||
}
|
||||
// Determine lexer.
|
||||
l := lexers.Get("yaml")
|
||||
if l == nil {
|
||||
l = lexers.Analyse(source)
|
||||
}
|
||||
if l == nil {
|
||||
l = lexers.Fallback
|
||||
}
|
||||
l = chroma.Coalesce(l)
|
||||
|
||||
// Determine formatter.
|
||||
f := formatters.Get("terminal256")
|
||||
if f == nil {
|
||||
f = formatters.Fallback
|
||||
}
|
||||
|
||||
// Determine style.
|
||||
s := styles.Get("monokai")
|
||||
if s == nil {
|
||||
s = styles.Fallback
|
||||
}
|
||||
|
||||
it, err := l.Tokenise(nil, source)
|
||||
if err != nil {
|
||||
pterm.Error.Println(err.Error())
|
||||
}
|
||||
|
||||
if err = f.Format(out, s, it); err != nil {
|
||||
pterm.Error.Println(err.Error())
|
||||
}
|
||||
|
||||
return out.w.String()
|
||||
}
|
||||
|
||||
type numberWriter struct {
|
||||
w *bytes.Buffer
|
||||
currentLine uint64
|
||||
buf []byte
|
||||
}
|
||||
|
||||
func (w *numberWriter) Write(p []byte) (int, error) {
|
||||
// Early return.
|
||||
// Can't calculate the line numbers until the line breaks are made, so store them all in a buffer.
|
||||
if !bytes.Contains(p, []byte{'\n'}) {
|
||||
w.buf = append(w.buf, p...)
|
||||
return len(p), nil
|
||||
}
|
||||
|
||||
var (
|
||||
original = p
|
||||
tokenLen uint
|
||||
)
|
||||
for i, c := range original {
|
||||
tokenLen++
|
||||
if c != '\n' {
|
||||
continue
|
||||
}
|
||||
|
||||
token := p[:tokenLen]
|
||||
p = original[i+1:]
|
||||
tokenLen = 0
|
||||
|
||||
format := "%4d |\t%s%s"
|
||||
if w.currentLine > 9999 {
|
||||
format = "%d |\t%s%s"
|
||||
}
|
||||
format = "\033[34m" + format + "\033[0m"
|
||||
|
||||
if _, err := fmt.Fprintf(w.w, format, w.currentLine, string(w.buf), string(token)); err != nil {
|
||||
return i + 1, err
|
||||
}
|
||||
w.buf = w.buf[:0]
|
||||
w.currentLine++
|
||||
}
|
||||
|
||||
if len(p) > 0 {
|
||||
w.buf = append(w.buf, p...)
|
||||
}
|
||||
return len(original), nil
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user