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
File renamed without changes.
32 changes: 32 additions & 0 deletions action.dependencies.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
runtime: plugin
action:
title: Dependencies
description: "Shows dependencies and dependent resources of selected resource"
alias:
- deps
arguments:
- name: target
title: Target
description: Target resource
required: true
options:
- name: source
title: Source
description: Resources source dir
type: string
default: ".compose/build"
- name: mrn
title: MRN
description: Show MRN instead of paths
type: boolean
default: false
- name: tree
title: Tree
description: "Show dependencies in tree-like output"
type: boolean
default: false
- name: depth
title: Depth
description: "Limit recursion lookup depth"
type: integer
default: 99
122 changes: 122 additions & 0 deletions dependencies.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
package plasmactlbump

import (
"fmt"
"sort"

"github.com/launchrctl/launchr"
"github.com/launchrctl/launchr/pkg/action"
"github.com/skilld-labs/plasmactl-bump/v2/pkg/sync"
)

type dependenciesAction struct {
action.WithLogger
action.WithTerm
}

func (a *dependenciesAction) run(target, source string, toPath, showTree bool, depth int8) error {
searchMrn := target
_, errConvert := sync.ConvertMRNtoPath(searchMrn)

if errConvert != nil {
r := sync.BuildResourceFromPath(target, source)
if r == nil {
return fmt.Errorf("not valid resource %q", target)
}

searchMrn = r.GetName()
}

var header string
if toPath {
header, _ = sync.ConvertMRNtoPath(searchMrn)
} else {
header = searchMrn
}

inv, err := sync.NewInventory(source, a.Log())
if err != nil {
return err
}
parents := inv.GetRequiredByResources(searchMrn, depth)
if len(parents) > 0 {
a.Term().Info().Println("Dependent resources:")
if showTree {
var parentsTree forwardTree = inv.GetRequiredByMap()
parentsTree.print(a.Term(), header, "", 1, depth, searchMrn, toPath)
} else {
a.printList(parents, toPath)
}
}

children := inv.GetDependsOnResources(searchMrn, depth)
if len(children) > 0 {
a.Term().Info().Println("Dependencies:")
if showTree {
var childrenTree forwardTree = inv.GetDependsOnMap()
childrenTree.print(a.Term(), header, "", 1, depth, searchMrn, toPath)
} else {
a.printList(children, toPath)
}
}

return nil
}

func (a *dependenciesAction) printList(items map[string]bool, toPath bool) {
keys := make([]string, 0, len(items))
for k := range items {
keys = append(keys, k)
}

sort.Strings(keys)
for _, item := range keys {
res := item
if toPath {
res, _ = sync.ConvertMRNtoPath(res)
}

a.Term().Print(res + "\n")
}
}

type forwardTree map[string]*sync.OrderedMap[bool]

func (t forwardTree) print(printer *launchr.Terminal, header, indent string, depth, limit int8, parent string, toPath bool) {
if indent == "" {
printer.Printfln(header)
}

if depth == limit {
return
}

children, ok := t[parent]
if !ok {
return
}

keys := children.Keys()
sort.Strings(keys)

for i, node := range keys {
isLast := i == len(keys)-1
var newIndent, edge string

if isLast {
newIndent = indent + " "
edge = "└── "
} else {
newIndent = indent + "│ "
edge = "├── "
}

value := node
if toPath {
value, _ = sync.ConvertMRNtoPath(value)
}

printer.Printfln(indent + edge + value)
t.print(printer, "", newIndent, depth+1, limit, node, toPath)
}
}
43 changes: 38 additions & 5 deletions plugin.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,19 @@ package plasmactlbump
import (
"context"
_ "embed"
"fmt"
"os"

"github.com/launchrctl/keyring"
"github.com/launchrctl/launchr"
"github.com/launchrctl/launchr/pkg/action"
)

//go:embed action.yaml
var actionYaml []byte
//go:embed action.bump.yaml
var actionBumpYaml []byte

//go:embed action.dependencies.yaml
var actionDependenciesYaml []byte

func init() {
launchr.RegisterPlugin(&Plugin{})
Expand Down Expand Up @@ -39,8 +44,8 @@ func (p *Plugin) OnAppInit(app launchr.App) error {

// DiscoverActions implements [launchr.ActionDiscoveryPlugin] interface.
func (p *Plugin) DiscoverActions(_ context.Context) ([]*action.Action, error) {
a := action.NewFromYAML("bump", actionYaml)
a.SetRuntime(action.NewFnRuntime(func(_ context.Context, a *action.Action) error {
ba := action.NewFromYAML("bump", actionBumpYaml)
ba.SetRuntime(action.NewFnRuntime(func(_ context.Context, a *action.Action) error {
input := a.Input()
doSync := input.Opt("sync").(bool)
dryRun := input.Opt("dry-run").(bool)
Expand Down Expand Up @@ -88,7 +93,35 @@ func (p *Plugin) DiscoverActions(_ context.Context) ([]*action.Action, error) {

return nil
}))
return []*action.Action{a}, nil

da := action.NewFromYAML("dependencies", actionDependenciesYaml)
da.SetRuntime(action.NewFnRuntime(func(_ context.Context, a *action.Action) error {
log, _, _, term := getLogger(a)

input := a.Input()
source := input.Opt("source").(string)
if _, err := os.Stat(source); os.IsNotExist(err) {
term.Warning().Printfln("%s doesn't exist, fallback to current dir", source)
source = "."
} else {
term.Info().Printfln("Selected source is %s", source)
}

showPaths := input.Opt("mrn").(bool)
showTree := input.Opt("tree").(bool)
depth := int8(input.Opt("depth").(int)) //nolint:gosec
if depth == 0 {
return fmt.Errorf("depth value should not be zero")
}

target := input.Arg("target").(string)
dependencies := &dependenciesAction{}
dependencies.SetLogger(log)
dependencies.SetTerm(term)
return dependencies.run(target, source, !showPaths, showTree, depth)
}))

return []*action.Action{ba, da}, nil
}

func getLogger(a *action.Action) (*launchr.Logger, launchr.LogLevel, launchr.Streams, *launchr.Terminal) {
Expand Down