// Copyright (c) 2019, Drone IO Inc. // Copyright (c) 2021, Robert Kaussow package pretty import ( "github.com/drone/drone-yaml/yaml" ) // helper function to pretty print the pipeline resource. func printPipeline(w writer, v *yaml.Pipeline) { _, _ = w.WriteString("---") w.WriteTagValue("version", v.Version) w.WriteTagValue("kind", v.Kind) w.WriteTagValue("type", v.Type) w.WriteTagValue("name", v.Name) _ = w.WriteByte('\n') if !isPlatformEmpty(v.Platform) { printPlatform(w, v.Platform) } else { printPlatformDefault(w) } if !isCloneEmpty(v.Clone) { printClone(w, v.Clone) } if !isConcurrencyEmpty(v.Concurrency) { printConcurrency(w, v.Concurrency) } if !isWorkspaceEmpty(v.Workspace) { printWorkspace(w, v.Workspace) } if len(v.Steps) > 0 { w.WriteTag("steps") for _, step := range v.Steps { if step == nil { continue } seq := new(indexWriter) seq.writer = w seq.IndentIncrease() printContainer(seq, step) seq.IndentDecrease() } } if len(v.Services) > 0 { w.WriteTag("services") for _, step := range v.Services { if step == nil { continue } seq := new(indexWriter) seq.writer = w seq.IndentIncrease() printContainer(seq, step) seq.IndentDecrease() } } if len(v.Volumes) != 0 { printVolumes(w, v.Volumes) _ = w.WriteByte('\n') } if len(v.PullSecrets) > 0 { w.WriteTagValue("image_pull_secrets", v.PullSecrets) _ = w.WriteByte('\n') } if len(v.Node) > 0 { printNode(w, v.Node) _ = w.WriteByte('\n') } if !isConditionsEmpty(v.Trigger) { printConditions(w, "trigger", v.Trigger) _ = w.WriteByte('\n') } if len(v.DependsOn) > 0 { printDependsOn(w, v.DependsOn) _ = w.WriteByte('\n') } _ = w.WriteByte('\n') } // helper function pretty prints the clone block. func printClone(w writer, v yaml.Clone) { w.WriteTag("clone") w.IndentIncrease() w.WriteTagValue("depth", v.Depth) w.WriteTagValue("disable", v.Disable) w.WriteTagValue("skip_verify", v.SkipVerify) _ = w.WriteByte('\n') w.IndentDecrease() } // helper function pretty prints the clone block. func printConcurrency(w writer, v yaml.Concurrency) { w.WriteTag("concurrency") w.IndentIncrease() w.WriteTagValue("limit", v.Limit) _ = w.WriteByte('\n') w.IndentDecrease() } // helper function pretty prints the conditions mapping. func printConditions(w writer, name string, v yaml.Conditions) { w.WriteTag(name) w.IndentIncrease() if !isConditionEmpty(v.Action) { printCondition(w, "action", v.Action) } if !isConditionEmpty(v.Branch) { printCondition(w, "branch", v.Branch) } if !isConditionEmpty(v.Cron) { printCondition(w, "cron", v.Cron) } if !isConditionEmpty(v.Event) { printCondition(w, "event", v.Event) } if !isConditionEmpty(v.Instance) { printCondition(w, "instance", v.Instance) } if !isConditionEmpty(v.Paths) { printCondition(w, "paths", v.Paths) } if !isConditionEmpty(v.Ref) { printCondition(w, "ref", v.Ref) } if !isConditionEmpty(v.Repo) { printCondition(w, "repo", v.Repo) } if !isConditionEmpty(v.Status) { printCondition(w, "status", v.Status) } if !isConditionEmpty(v.Target) { printCondition(w, "target", v.Target) } w.IndentDecrease() } // helper function pretty prints a condition mapping. func printCondition(w writer, k string, v yaml.Condition) { w.WriteTag(k) if len(v.Include) != 0 && len(v.Exclude) == 0 { _ = w.WriteByte('\n') w.IndentIncrease() w.Indent() writeValue(w, v.Include) w.IndentDecrease() } if len(v.Include) != 0 && len(v.Exclude) != 0 { w.IndentIncrease() w.WriteTagValue("include", v.Include) w.IndentDecrease() } if len(v.Exclude) != 0 { w.IndentIncrease() w.WriteTagValue("exclude", v.Exclude) w.IndentDecrease() } } // helper function pretty prints the node mapping. func printNode(w writer, v map[string]string) { w.WriteTagValue("node", v) } // helper function pretty prints the target platform. func printPlatform(w writer, v yaml.Platform) { w.WriteTag("platform") w.IndentIncrease() w.WriteTagValue("os", v.OS) w.WriteTagValue("arch", v.Arch) w.WriteTagValue("variant", v.Variant) w.WriteTagValue("version", v.Version) _ = w.WriteByte('\n') w.IndentDecrease() } // helper function prints default platform values. // Including target platform is considered a best-practive. func printPlatformDefault(w writer) { w.WriteTag("platform") w.IndentIncrease() w.WriteTagValue("os", "linux") w.WriteTagValue("arch", "amd64") _ = w.WriteByte('\n') w.IndentDecrease() } // helper function pretty prints the volume sequence. func printVolumes(w writer, v []*yaml.Volume) { w.WriteTag("volumes") for _, v := range v { s := new(indexWriter) s.writer = w w.IndentIncrease() s.IndentIncrease() s.WriteTagValue("name", v.Name) if v := v.EmptyDir; v != nil { s.WriteTag("temp") if isEmptyDirEmpty(v) { _ = w.WriteByte(' ') _ = w.WriteByte('{') _ = w.WriteByte('}') } else { s.IndentIncrease() s.WriteTagValue("medium", v.Medium) s.WriteTagValue("size_limit", v.SizeLimit) s.IndentDecrease() } } if v := v.HostPath; v != nil { s.WriteTag("host") s.IndentIncrease() s.WriteTagValue("path", v.Path) s.IndentDecrease() } s.IndentDecrease() w.IndentDecrease() } } // helper function pretty prints the workspace block. func printWorkspace(w writer, v yaml.Workspace) { w.WriteTag("workspace") w.IndentIncrease() w.WriteTagValue("base", v.Base) w.WriteTagValue("path", v.Path) _ = w.WriteByte('\n') w.IndentDecrease() } // helper function returns true if the workspace // object is empty. func isWorkspaceEmpty(v yaml.Workspace) bool { return v.Path == "" && v.Base == "" } // helper function returns true if the platform // object is empty. func isPlatformEmpty(v yaml.Platform) bool { return v.OS == "" && v.Arch == "" && v.Variant == "" && v.Version == "" } // helper function returns true if the clone // object is empty. func isCloneEmpty(v yaml.Clone) bool { return v.Depth == 0 && !v.Disable && !v.SkipVerify } // helper function returns true if the concurrency // object is empty. func isConcurrencyEmpty(v yaml.Concurrency) bool { return v.Limit == 0 } // helper function returns true if the conditions // object is empty. func isConditionsEmpty(v yaml.Conditions) bool { return isConditionEmpty(v.Action) && isConditionEmpty(v.Branch) && isConditionEmpty(v.Cron) && isConditionEmpty(v.Event) && isConditionEmpty(v.Instance) && isConditionEmpty(v.Paths) && isConditionEmpty(v.Ref) && isConditionEmpty(v.Repo) && isConditionEmpty(v.Status) && isConditionEmpty(v.Target) } // helper function returns true if the condition // object is empty. func isConditionEmpty(v yaml.Condition) bool { return len(v.Exclude) == 0 && len(v.Include) == 0 } // helper function returns true if the emptydir // object is empty. func isEmptyDirEmpty(v *yaml.VolumeEmptyDir) bool { return v.SizeLimit == 0 && len(v.Medium) == 0 }