Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: added basic branch pruning logic #427

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
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
7 changes: 6 additions & 1 deletion internal/cmd/apply.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,12 @@ func applyFunc(cmd *cobra.Command, _ []string) error {
defer cfg.Close()
ctx := cmd.Context()

dg, err := graph.ToDeploymentGraph(cfg, commonFlags.outputPath)
g, err := graph.ToDependencyGraph(cfg, commonFlags.outputPath)
if err != nil {
return err
}

dg, err := graph.ToDeploymentGraph(g)
if err != nil {
return err
}
Expand Down
8 changes: 2 additions & 6 deletions internal/cmd/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import (

type CommonFlags struct {
configFile string
siteName string
site string
ignoreVersion bool
outputPath string
varFile string
Expand All @@ -29,7 +29,7 @@ var commonFlags CommonFlags
func registerCommonFlags(cmd *cobra.Command) {
cmd.Flags().StringVarP(&commonFlags.configFile, "file", "f", "main.yml", "YAML file to parse.")
cmd.Flags().StringVarP(&commonFlags.varFile, "var-file", "", "", "Use a variable file to parse the configuration with.")
cmd.Flags().StringVarP(&commonFlags.siteName, "site", "s", "", "Site to parse. If not set parse all sites.")
cmd.Flags().StringVarP(&commonFlags.site, "site", "s", "", "Site to parse. If not set parse all sites.")
cmd.Flags().BoolVarP(&commonFlags.ignoreVersion, "ignore-version", "", false, "Skip MACH composer version check")
cmd.Flags().StringVarP(&commonFlags.outputPath, "output-path", "", "deployments",
"Outputs path to store the generated files.")
Expand All @@ -39,10 +39,6 @@ func registerCommonFlags(cmd *cobra.Command) {
}

func preprocessCommonFlags(cmd *cobra.Command) {
if commonFlags.siteName != "" {
log.Warn().Msgf("Site option not implemented")
}

handleError(cmd.MarkFlagFilename("var-file", "yml", "yaml"))
handleError(cmd.MarkFlagFilename("file", "yml", "yaml"))

Expand Down
7 changes: 6 additions & 1 deletion internal/cmd/generate.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,12 @@ func generateFunc(cmd *cobra.Command) error {
cfg := loadConfig(cmd, true)
defer cfg.Close()

gd, err := graph.ToDeploymentGraph(cfg, commonFlags.outputPath)
g, err := graph.ToDependencyGraph(cfg, commonFlags.outputPath)
if err != nil {
return err
}

gd, err := graph.ToDeploymentGraph(g)
if err != nil {
return err
}
Expand Down
7 changes: 6 additions & 1 deletion internal/cmd/graph.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,12 @@ func graphFunc(cmd *cobra.Command, _ []string) error {
}

if graphFlags.deployment {
dg, err := graph.ToDeploymentGraph(cfg, commonFlags.outputPath)
var opts []graph.Option
if commonFlags.site != "" {
opts = append(opts, graph.WithSite(commonFlags.site))
}

dg, err := graph.ToDeploymentGraph(g, opts...)
if err != nil {
return err
}
Expand Down
7 changes: 6 additions & 1 deletion internal/cmd/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,12 @@ func initFunc(cmd *cobra.Command, _ []string) error {
defer cfg.Close()
ctx := cmd.Context()

dg, err := graph.ToDeploymentGraph(cfg, commonFlags.outputPath)
g, err := graph.ToDependencyGraph(cfg, commonFlags.outputPath)
if err != nil {
return err
}

dg, err := graph.ToDeploymentGraph(g)
if err != nil {
return err
}
Expand Down
7 changes: 6 additions & 1 deletion internal/cmd/plan.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,12 @@ func planFunc(cmd *cobra.Command, _ []string) error {
defer cfg.Close()
ctx := cmd.Context()

dg, err := graph.ToDeploymentGraph(cfg, commonFlags.outputPath)
g, err := graph.ToDependencyGraph(cfg, commonFlags.outputPath)
if err != nil {
return err
}

dg, err := graph.ToDeploymentGraph(g)
if err != nil {
return err
}
Expand Down
7 changes: 6 additions & 1 deletion internal/cmd/show-plan.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,12 @@ func showPlanFunc(cmd *cobra.Command, _ []string) error {
defer cfg.Close()
ctx := cmd.Context()

dg, err := graph.ToDeploymentGraph(cfg, commonFlags.outputPath)
g, err := graph.ToDependencyGraph(cfg, commonFlags.outputPath)
if err != nil {
return err
}

dg, err := graph.ToDeploymentGraph(g)
if err != nil {
return err
}
Expand Down
7 changes: 6 additions & 1 deletion internal/cmd/terraform.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,12 @@ func terraformFunc(cmd *cobra.Command, args []string) error {
ctx := cmd.Context()
defer cfg.Close()

dg, err := graph.ToDeploymentGraph(cfg, commonFlags.outputPath)
g, err := graph.ToDependencyGraph(cfg, commonFlags.outputPath)
if err != nil {
return err
}

dg, err := graph.ToDeploymentGraph(g)
if err != nil {
return err
}
Expand Down
50 changes: 43 additions & 7 deletions internal/graph/deployment.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,42 @@ import (
"errors"
"fmt"
"github.com/dominikbraun/graph"
"github.com/mach-composer/mach-composer-cli/internal/config"
)

type options struct {
site string
}

type Option func(o *options)

func WithSite(site string) Option {
return func(o *options) {
o.site = site
}
}

// ToDeploymentGraph converts a MachConfig to a Graph ready for deployment.
// This means that all nodes that are not independently deployable are pruned from the graph.
func ToDeploymentGraph(cfg *config.MachConfig, outPath string) (*Graph, error) {
g, err := ToDependencyGraph(cfg, outPath)
if err != nil {
return nil, err
func ToDeploymentGraph(g *Graph, opts ...Option) (*Graph, error) {
o := options{
site: "",
}

for _, opt := range opts {
opt(&o)
}

if err = validateDeployment(g); err != nil {
if err := validateDeployment(g); err != nil {
return nil, err
}

// Remove all nodes that are not independent to site node
if err = reduceNodes(g); err != nil {
if err := reduceNodes(g); err != nil {
return nil, err
}

//Prune to only include the site node if provided
if err := pruneSiteNodes(g, o.site); err != nil {
return nil, err
}

Expand Down Expand Up @@ -132,3 +151,20 @@ func reduceNodes(g *Graph) error {

return pErr
}

func pruneSiteNodes(g *Graph, site string) error {
if site == "" {
return nil
}

for _, v := range g.Vertices() {
if v.Type() == SiteType && v.Identifier() != site {
err := pruneBranch(g, v)
if err != nil {
return err
}
}
}

return nil
}
5 changes: 4 additions & 1 deletion internal/graph/deployment_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,10 @@ func TestToDeploymentGraphSimple(t *testing.T) {
},
}

g, err := ToDeploymentGraph(cfg, "")
dg, err := ToDependencyGraph(cfg, "")
assert.NoError(t, err)

g, err := ToDeploymentGraph(dg)
assert.NoError(t, err)

o, _ := g.Order()
Expand Down
47 changes: 47 additions & 0 deletions internal/graph/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,50 @@ func fetchPathsToTarget(source, target string, pm map[string]map[string]graph.Ed

return paths
}

func pruneBranch(g *Graph, n Node) error {
var pErr error
graph.DFS(g.Graph, n.Path(), func(p string) bool {
n, err := g.Graph.Vertex(p)
if err != nil {
pErr = err
return true
}

e, err := g.Edges()
if err != nil {
pErr = err
return true
}

var edges []graph.Edge[string]

for _, edge := range e {
if edge.Target == n.Path() {
edges = append(edges, edge)
}

if edge.Source == n.Path() {
edges = append(edges, edge)
}
}

for _, edge := range edges {
err = g.RemoveEdge(edge.Source, edge.Target)
if err != nil {
pErr = err
return true
}
}

err = g.RemoveVertex(n.Path())
if err != nil {
pErr = err
return true
}

return false
})

return pErr
}
Loading