From 6f87b9bf34f54b881a9fa9a69bcab8a34ac9f9d9 Mon Sep 17 00:00:00 2001 From: grokspawn Date: Fri, 15 Aug 2025 11:07:20 -0500 Subject: [PATCH 1/3] initial working viz of ignored v0 edges Signed-off-by: grokspawn --- alpha/declcfg/write.go | 101 +++++++++++++++++++++++++++++------------ 1 file changed, 73 insertions(+), 28 deletions(-) diff --git a/alpha/declcfg/write.go b/alpha/declcfg/write.go index 293d9363b..afa2c2349 100644 --- a/alpha/declcfg/write.go +++ b/alpha/declcfg/write.go @@ -20,6 +20,7 @@ import ( type MermaidWriter struct { MinEdgeName string SpecifiedPackageName string + UseV0Semantics bool } type MermaidOption func(*MermaidWriter) @@ -52,6 +53,12 @@ func WithSpecifiedPackageName(specifiedPackageName string) MermaidOption { } } +func WithV0Semantics() MermaidOption { + return func(o *MermaidWriter) { + o.UseV0Semantics = true + } +} + // writes out the channel edges of the declarative config graph in a mermaid format capable of being pasted into // mermaid renderers like github, mermaid.live, etc. // output is sorted lexicographically by package name, and then by channel name @@ -125,6 +132,8 @@ func (writer *MermaidWriter) WriteChannels(cfg DeclarativeConfig, out io.Writer) var deprecatedPackage string deprecatedChannels := []string{} + linkID := 0 + skippedLinkIDs := []string{} for _, c := range cfg.Channels { filteredChannel := writer.filterChannel(&c, versionMap, minVersion, minEdgePackage) @@ -137,8 +146,8 @@ func (writer *MermaidWriter) WriteChannels(cfg DeclarativeConfig, out io.Writer) } channelID := fmt.Sprintf("%s-%s", filteredChannel.Package, filteredChannel.Name) - pkgBuilder.WriteString(fmt.Sprintf(" %%%% channel %q\n", filteredChannel.Name)) - pkgBuilder.WriteString(fmt.Sprintf(" subgraph %s[%q]\n", channelID, filteredChannel.Name)) + fmt.Fprintf(pkgBuilder, " %%%% channel %q\n", filteredChannel.Name) + fmt.Fprintf(pkgBuilder, " subgraph %s[%q]\n", channelID, filteredChannel.Name) if depByPackage.Has(filteredChannel.Package) { deprecatedPackage = filteredChannel.Package @@ -148,47 +157,79 @@ func (writer *MermaidWriter) WriteChannels(cfg DeclarativeConfig, out io.Writer) deprecatedChannels = append(deprecatedChannels, channelID) } - for _, ce := range filteredChannel.Entries { - if versionMap[ce.Name].GE(minVersion) { - bundleDeprecation := "" - if depByBundle.Has(ce.Name) { - bundleDeprecation = ":::deprecated" - } + // sort edges by decreasing version + sortedEntries := make([]*ChannelEntry, 0, len(filteredChannel.Entries)) + for i := range filteredChannel.Entries { + sortedEntries = append(sortedEntries, &filteredChannel.Entries[i]) + } + sort.Slice(sortedEntries, func(i, j int) bool { + // Sort by decreasing version: greater version comes first + return versionMap[sortedEntries[i].Name].GT(versionMap[sortedEntries[j].Name]) + }) + + skippedEntities := sets.Set[string]{} + + for _, ce := range sortedEntries { + bundleDecoration := "" + switch { + case depByBundle.Has(ce.Name) && skippedEntities.Has(ce.Name): + bundleDecoration = ":::depandskip" + case depByBundle.Has(ce.Name): + bundleDecoration = ":::deprecated" + case skippedEntities.Has(ce.Name): + bundleDecoration = ":::skipped" + } - entryID := fmt.Sprintf("%s-%s", channelID, ce.Name) - pkgBuilder.WriteString(fmt.Sprintf(" %s[%q]%s\n", entryID, ce.Name, bundleDeprecation)) + entryID := fmt.Sprintf("%s-%s", channelID, ce.Name) + fmt.Fprintf(pkgBuilder, " %s[%q]%s\n", entryID, ce.Name, bundleDecoration) - if len(ce.Replaces) > 0 { - replacesID := fmt.Sprintf("%s-%s", channelID, ce.Replaces) - pkgBuilder.WriteString(fmt.Sprintf(" %s[%q]-- %s --> %s[%q]\n", replacesID, ce.Replaces, "replace", entryID, ce.Name)) - } - if len(ce.Skips) > 0 { - for _, s := range ce.Skips { - skipsID := fmt.Sprintf("%s-%s", channelID, s) - pkgBuilder.WriteString(fmt.Sprintf(" %s[%q]-- %s --> %s[%q]\n", skipsID, s, "skip", entryID, ce.Name)) + if len(ce.Skips) > 0 { + for _, s := range ce.Skips { + skipsID := fmt.Sprintf("%s-%s", channelID, s) + fmt.Fprintf(pkgBuilder, " %s[%q]-- %s --> %s[%q]\n", skipsID, s, "skip", entryID, ce.Name) + if skippedEntities.Has(s) { + skippedLinkIDs = append(skippedLinkIDs, fmt.Sprintf("%d", linkID)) + } else { + skippedEntities.Insert(s) } + linkID++ } - if len(ce.SkipRange) > 0 { - skipRange, err := semver.ParseRange(ce.SkipRange) - if err == nil { - for _, edgeName := range filteredChannel.Entries { - if skipRange(versionMap[edgeName.Name]) { - skipRangeID := fmt.Sprintf("%s-%s", channelID, edgeName.Name) - pkgBuilder.WriteString(fmt.Sprintf(" %s[%q]-- \"%s(%s)\" --> %s[%q]\n", skipRangeID, edgeName.Name, "skipRange", ce.SkipRange, entryID, ce.Name)) + } + if len(ce.SkipRange) > 0 { + skipRange, err := semver.ParseRange(ce.SkipRange) + if err == nil { + for _, edgeName := range filteredChannel.Entries { + if skipRange(versionMap[edgeName.Name]) { + skipRangeID := fmt.Sprintf("%s-%s", channelID, edgeName.Name) + fmt.Fprintf(pkgBuilder, " %s[%q]-- \"%s(%s)\" --> %s[%q]\n", skipRangeID, edgeName.Name, "skipRange", ce.SkipRange, entryID, ce.Name) + if skippedEntities.Has(ce.Name) { + skippedLinkIDs = append(skippedLinkIDs, fmt.Sprintf("%d", linkID)) } + linkID++ } - } else { - fmt.Fprintf(os.Stderr, "warning: ignoring invalid SkipRange for package/edge %q/%q: %v\n", c.Package, ce.Name, err) } + } else { + fmt.Fprintf(os.Stderr, "warning: ignoring invalid SkipRange for package/edge %q/%q: %v\n", c.Package, ce.Name, err) } } + // have to process replaces last, because applicablity can be impacted by skips + if len(ce.Replaces) > 0 { + replacesID := fmt.Sprintf("%s-%s", channelID, ce.Replaces) + fmt.Fprintf(pkgBuilder, " %s[%q]-- %s --> %s[%q]\n", replacesID, ce.Replaces, "replace", entryID, ce.Name) + if skippedEntities.Has(ce.Name) { + skippedLinkIDs = append(skippedLinkIDs, fmt.Sprintf("%d", linkID)) + } + linkID++ + } } - pkgBuilder.WriteString(" end\n") + fmt.Fprintf(pkgBuilder, " end\n") } } _, _ = out.Write([]byte("graph LR\n")) _, _ = out.Write([]byte(" classDef deprecated fill:#E8960F\n")) + _, _ = out.Write([]byte(" classDef skipped stroke:#FF0000,stroke-width:4px\n")) + _, _ = out.Write([]byte(" classDef depandskip fill:#E8960,stroke:#FF0000,stroke-width:4px\n")) pkgNames := []string{} for pname := range pkgs { pkgNames = append(pkgNames, pname) @@ -213,6 +254,10 @@ func (writer *MermaidWriter) WriteChannels(cfg DeclarativeConfig, out io.Writer) } } + if len(skippedLinkIDs) > 0 { + _, _ = out.Write([]byte("linkStyle " + strings.Join(skippedLinkIDs, ",") + " stroke:#FF0000,stroke-width:3px,stroke-dasharray:5;")) + } + return nil } From b35b44c2629cf5fe2d4b3b205b4afd7268984185 Mon Sep 17 00:00:00 2001 From: grokspawn Date: Fri, 15 Aug 2025 14:32:12 -0500 Subject: [PATCH 2/3] initial semantic refactoring --- alpha/declcfg/write.go | 78 ++++++++++++++++++++----------- alpha/declcfg/write_test.go | 26 +++++++---- cmd/opm/alpha/render-graph/cmd.go | 7 ++- 3 files changed, 75 insertions(+), 36 deletions(-) diff --git a/alpha/declcfg/write.go b/alpha/declcfg/write.go index afa2c2349..99f28e8fc 100644 --- a/alpha/declcfg/write.go +++ b/alpha/declcfg/write.go @@ -7,6 +7,7 @@ import ( "io" "os" "path/filepath" + "slices" "sort" "strings" @@ -20,7 +21,7 @@ import ( type MermaidWriter struct { MinEdgeName string SpecifiedPackageName string - UseV0Semantics bool + DrawV0Semantics bool } type MermaidOption func(*MermaidWriter) @@ -33,6 +34,7 @@ func NewMermaidWriter(opts ...MermaidOption) *MermaidWriter { m := &MermaidWriter{ MinEdgeName: minEdgeName, SpecifiedPackageName: specifiedPackageName, + DrawV0Semantics: true, } for _, opt := range opts { @@ -53,9 +55,9 @@ func WithSpecifiedPackageName(specifiedPackageName string) MermaidOption { } } -func WithV0Semantics() MermaidOption { +func WithV0Semantics(drawV0Semantics bool) MermaidOption { return func(o *MermaidWriter) { - o.UseV0Semantics = true + o.DrawV0Semantics = drawV0Semantics } } @@ -131,7 +133,8 @@ func (writer *MermaidWriter) WriteChannels(cfg DeclarativeConfig, out io.Writer) } var deprecatedPackage string - deprecatedChannels := []string{} + deprecatedChannelIDs := []string{} + decoratedBundleIDs := map[string][]string{"deprecated": {}, "skipped": {}, "deprecatedskipped": {}} linkID := 0 skippedLinkIDs := []string{} @@ -154,7 +157,7 @@ func (writer *MermaidWriter) WriteChannels(cfg DeclarativeConfig, out io.Writer) } if depByChannel.Has(filteredChannel.Name) { - deprecatedChannels = append(deprecatedChannels, channelID) + deprecatedChannelIDs = append(deprecatedChannelIDs, channelID) } // sort edges by decreasing version @@ -169,29 +172,45 @@ func (writer *MermaidWriter) WriteChannels(cfg DeclarativeConfig, out io.Writer) skippedEntities := sets.Set[string]{} + const ( + captureNewEntry = true + processExisting = false + ) + handleSemantics := func(edge string, linkID int, captureNew bool) { + if writer.DrawV0Semantics { + if captureNew { + if skippedEntities.Has(edge) { + skippedLinkIDs = append(skippedLinkIDs, fmt.Sprintf("%d", linkID)) + } else { + skippedEntities.Insert(edge) + } + } else { + if skippedEntities.Has(edge) { + skippedLinkIDs = append(skippedLinkIDs, fmt.Sprintf("%d", linkID)) + } + } + } + } + for _, ce := range sortedEntries { - bundleDecoration := "" + entryID := fmt.Sprintf("%s-%s", channelID, ce.Name) + fmt.Fprintf(pkgBuilder, " %s[%q]\n", entryID, ce.Name) + + // mermaid allows specification of only a single decoration class, so any combinations must be independently represented switch { case depByBundle.Has(ce.Name) && skippedEntities.Has(ce.Name): - bundleDecoration = ":::depandskip" + decoratedBundleIDs["deprecatedskipped"] = append(decoratedBundleIDs["deprecatedskipped"], entryID) case depByBundle.Has(ce.Name): - bundleDecoration = ":::deprecated" + decoratedBundleIDs["deprecated"] = append(decoratedBundleIDs["deprecated"], entryID) case skippedEntities.Has(ce.Name): - bundleDecoration = ":::skipped" + decoratedBundleIDs["skipped"] = append(decoratedBundleIDs["skipped"], entryID) } - entryID := fmt.Sprintf("%s-%s", channelID, ce.Name) - fmt.Fprintf(pkgBuilder, " %s[%q]%s\n", entryID, ce.Name, bundleDecoration) - if len(ce.Skips) > 0 { for _, s := range ce.Skips { skipsID := fmt.Sprintf("%s-%s", channelID, s) fmt.Fprintf(pkgBuilder, " %s[%q]-- %s --> %s[%q]\n", skipsID, s, "skip", entryID, ce.Name) - if skippedEntities.Has(s) { - skippedLinkIDs = append(skippedLinkIDs, fmt.Sprintf("%d", linkID)) - } else { - skippedEntities.Insert(s) - } + handleSemantics(s, linkID, captureNewEntry) linkID++ } } @@ -202,9 +221,7 @@ func (writer *MermaidWriter) WriteChannels(cfg DeclarativeConfig, out io.Writer) if skipRange(versionMap[edgeName.Name]) { skipRangeID := fmt.Sprintf("%s-%s", channelID, edgeName.Name) fmt.Fprintf(pkgBuilder, " %s[%q]-- \"%s(%s)\" --> %s[%q]\n", skipRangeID, edgeName.Name, "skipRange", ce.SkipRange, entryID, ce.Name) - if skippedEntities.Has(ce.Name) { - skippedLinkIDs = append(skippedLinkIDs, fmt.Sprintf("%d", linkID)) - } + handleSemantics(ce.Name, linkID, processExisting) linkID++ } } @@ -216,9 +233,7 @@ func (writer *MermaidWriter) WriteChannels(cfg DeclarativeConfig, out io.Writer) if len(ce.Replaces) > 0 { replacesID := fmt.Sprintf("%s-%s", channelID, ce.Replaces) fmt.Fprintf(pkgBuilder, " %s[%q]-- %s --> %s[%q]\n", replacesID, ce.Replaces, "replace", entryID, ce.Name) - if skippedEntities.Has(ce.Name) { - skippedLinkIDs = append(skippedLinkIDs, fmt.Sprintf("%d", linkID)) - } + handleSemantics(ce.Name, linkID, processExisting) linkID++ } } @@ -229,7 +244,7 @@ func (writer *MermaidWriter) WriteChannels(cfg DeclarativeConfig, out io.Writer) _, _ = out.Write([]byte("graph LR\n")) _, _ = out.Write([]byte(" classDef deprecated fill:#E8960F\n")) _, _ = out.Write([]byte(" classDef skipped stroke:#FF0000,stroke-width:4px\n")) - _, _ = out.Write([]byte(" classDef depandskip fill:#E8960,stroke:#FF0000,stroke-width:4px\n")) + _, _ = out.Write([]byte(" classDef deprecatedskipped fill:#E8960F,stroke:#FF0000,stroke-width:4px\n")) pkgNames := []string{} for pname := range pkgs { pkgNames = append(pkgNames, pname) @@ -248,14 +263,23 @@ func (writer *MermaidWriter) WriteChannels(cfg DeclarativeConfig, out io.Writer) _, _ = out.Write([]byte(fmt.Sprintf("style %s fill:#989695\n", deprecatedPackage))) } - if len(deprecatedChannels) > 0 { - for _, deprecatedChannel := range deprecatedChannels { + if len(deprecatedChannelIDs) > 0 { + for _, deprecatedChannel := range deprecatedChannelIDs { _, _ = out.Write([]byte(fmt.Sprintf("style %s fill:#DCD0FF\n", deprecatedChannel))) } } + // express the decoration classes + for key := range decoratedBundleIDs { + if len(decoratedBundleIDs[key]) > 0 { + b := slices.Clone(decoratedBundleIDs[key]) + slices.Sort(b) + _, _ = out.Write([]byte(fmt.Sprintf("class %s %s\n", strings.Join(b, ","), key))) + } + } + if len(skippedLinkIDs) > 0 { - _, _ = out.Write([]byte("linkStyle " + strings.Join(skippedLinkIDs, ",") + " stroke:#FF0000,stroke-width:3px,stroke-dasharray:5;")) + _, _ = out.Write([]byte("linkStyle " + strings.Join(skippedLinkIDs, ",") + " stroke:#FF0000,stroke-width:3px,stroke-dasharray:5;\n")) } return nil diff --git a/alpha/declcfg/write_test.go b/alpha/declcfg/write_test.go index eca428768..fd3c9fb20 100644 --- a/alpha/declcfg/write_test.go +++ b/alpha/declcfg/write_test.go @@ -527,35 +527,40 @@ func TestWriteMermaidChannels(t *testing.T) { packageFilter: "", expected: `graph LR classDef deprecated fill:#E8960F + classDef skipped stroke:#FF0000,stroke-width:4px + classDef deprecatedskipped fill:#E8960F,stroke:#FF0000,stroke-width:4px %% package "anakin" subgraph "anakin" %% channel "dark" subgraph anakin-dark["dark"] - anakin-dark-anakin.v0.0.1["anakin.v0.0.1"]:::deprecated - anakin-dark-anakin.v0.1.0["anakin.v0.1.0"] - anakin-dark-anakin.v0.0.1["anakin.v0.0.1"]-- replace --> anakin-dark-anakin.v0.1.0["anakin.v0.1.0"] anakin-dark-anakin.v0.1.1["anakin.v0.1.1"] - anakin-dark-anakin.v0.0.1["anakin.v0.0.1"]-- replace --> anakin-dark-anakin.v0.1.1["anakin.v0.1.1"] anakin-dark-anakin.v0.1.0["anakin.v0.1.0"]-- skip --> anakin-dark-anakin.v0.1.1["anakin.v0.1.1"] + anakin-dark-anakin.v0.0.1["anakin.v0.0.1"]-- replace --> anakin-dark-anakin.v0.1.1["anakin.v0.1.1"] + anakin-dark-anakin.v0.1.0["anakin.v0.1.0"] + anakin-dark-anakin.v0.0.1["anakin.v0.0.1"]-- replace --> anakin-dark-anakin.v0.1.0["anakin.v0.1.0"] + anakin-dark-anakin.v0.0.1["anakin.v0.0.1"] end %% channel "light" subgraph anakin-light["light"] - anakin-light-anakin.v0.0.1["anakin.v0.0.1"]:::deprecated anakin-light-anakin.v0.1.0["anakin.v0.1.0"] anakin-light-anakin.v0.0.1["anakin.v0.0.1"]-- replace --> anakin-light-anakin.v0.1.0["anakin.v0.1.0"] + anakin-light-anakin.v0.0.1["anakin.v0.0.1"] end end %% package "boba-fett" subgraph "boba-fett" %% channel "mando" subgraph boba-fett-mando["mando"] - boba-fett-mando-boba-fett.v1.0.0["boba-fett.v1.0.0"] boba-fett-mando-boba-fett.v2.0.0["boba-fett.v2.0.0"] boba-fett-mando-boba-fett.v1.0.0["boba-fett.v1.0.0"]-- replace --> boba-fett-mando-boba-fett.v2.0.0["boba-fett.v2.0.0"] + boba-fett-mando-boba-fett.v1.0.0["boba-fett.v1.0.0"] end end style anakin fill:#989695 style anakin-light fill:#DCD0FF +class anakin-dark-anakin.v0.0.1,anakin-light-anakin.v0.0.1 deprecated +class anakin-dark-anakin.v0.1.0 skipped +linkStyle 2 stroke:#FF0000,stroke-width:3px,stroke-dasharray:5; `, }, { @@ -565,13 +570,15 @@ style anakin-light fill:#DCD0FF packageFilter: "", expected: `graph LR classDef deprecated fill:#E8960F + classDef skipped stroke:#FF0000,stroke-width:4px + classDef deprecatedskipped fill:#E8960F,stroke:#FF0000,stroke-width:4px %% package "anakin" subgraph "anakin" %% channel "dark" subgraph anakin-dark["dark"] - anakin-dark-anakin.v0.1.0["anakin.v0.1.0"] anakin-dark-anakin.v0.1.1["anakin.v0.1.1"] anakin-dark-anakin.v0.1.0["anakin.v0.1.0"]-- skip --> anakin-dark-anakin.v0.1.1["anakin.v0.1.1"] + anakin-dark-anakin.v0.1.0["anakin.v0.1.0"] end %% channel "light" subgraph anakin-light["light"] @@ -580,6 +587,7 @@ style anakin-light fill:#DCD0FF end style anakin fill:#989695 style anakin-light fill:#DCD0FF +class anakin-dark-anakin.v0.1.0 skipped `, }, { @@ -589,13 +597,15 @@ style anakin-light fill:#DCD0FF packageFilter: "boba-fett", expected: `graph LR classDef deprecated fill:#E8960F + classDef skipped stroke:#FF0000,stroke-width:4px + classDef deprecatedskipped fill:#E8960F,stroke:#FF0000,stroke-width:4px %% package "boba-fett" subgraph "boba-fett" %% channel "mando" subgraph boba-fett-mando["mando"] - boba-fett-mando-boba-fett.v1.0.0["boba-fett.v1.0.0"] boba-fett-mando-boba-fett.v2.0.0["boba-fett.v2.0.0"] boba-fett-mando-boba-fett.v1.0.0["boba-fett.v1.0.0"]-- replace --> boba-fett-mando-boba-fett.v2.0.0["boba-fett.v2.0.0"] + boba-fett-mando-boba-fett.v1.0.0["boba-fett.v1.0.0"] end end `, diff --git a/cmd/opm/alpha/render-graph/cmd.go b/cmd/opm/alpha/render-graph/cmd.go index 29d36eef9..67ecc32f5 100644 --- a/cmd/opm/alpha/render-graph/cmd.go +++ b/cmd/opm/alpha/render-graph/cmd.go @@ -18,6 +18,7 @@ func NewCmd() *cobra.Command { render action.Render minEdge string specifiedPackageName string + drawV0Semantics bool ) cmd := &cobra.Command{ Use: "render-graph [index-image | fbc-dir]", @@ -67,7 +68,10 @@ $ opm alpha render-graph quay.io/operatorhubio/catalog:latest | \ log.Fatal(err) } - writer := declcfg.NewMermaidWriter(declcfg.WithMinEdgeName(minEdge), declcfg.WithSpecifiedPackageName(specifiedPackageName)) + writer := declcfg.NewMermaidWriter( + declcfg.WithMinEdgeName(minEdge), + declcfg.WithSpecifiedPackageName(specifiedPackageName), + declcfg.WithV0Semantics(drawV0Semantics)) if err := writer.WriteChannels(*cfg, os.Stdout); err != nil { log.Fatal(err) } @@ -75,5 +79,6 @@ $ opm alpha render-graph quay.io/operatorhubio/catalog:latest | \ } cmd.Flags().StringVar(&minEdge, "minimum-edge", "", "the channel edge to be used as the lower bound of the set of edges composing the upgrade graph; default is to include all edges") cmd.Flags().StringVarP(&specifiedPackageName, "package-name", "p", "", "a specific package name to filter output; default is to include all packages in reference") + cmd.Flags().BoolVar(&drawV0Semantics, "draw-v0-semantics", false, "whether to indicate OLMv0 semantics in the output; default is to simply represent the upgrade graph") return cmd } From f1c21be8cadae87beb0bae7637a35a4f9bd83604 Mon Sep 17 00:00:00 2001 From: grokspawn Date: Thu, 21 Aug 2025 08:44:12 -0500 Subject: [PATCH 3/3] lint updates Signed-off-by: grokspawn --- alpha/declcfg/write.go | 12 ++++++------ cmd/opm/alpha/render-graph/cmd.go | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/alpha/declcfg/write.go b/alpha/declcfg/write.go index 99f28e8fc..52b2a67f3 100644 --- a/alpha/declcfg/write.go +++ b/alpha/declcfg/write.go @@ -253,19 +253,19 @@ func (writer *MermaidWriter) WriteChannels(cfg DeclarativeConfig, out io.Writer) return pkgNames[i] < pkgNames[j] }) for _, pkgName := range pkgNames { - _, _ = out.Write([]byte(fmt.Sprintf(" %%%% package %q\n", pkgName))) - _, _ = out.Write([]byte(fmt.Sprintf(" subgraph %q\n", pkgName))) + _, _ = fmt.Fprintf(out, " %%%% package %q\n", pkgName) + _, _ = fmt.Fprintf(out, " subgraph %q\n", pkgName) _, _ = out.Write([]byte(pkgs[pkgName].String())) _, _ = out.Write([]byte(" end\n")) } if deprecatedPackage != "" { - _, _ = out.Write([]byte(fmt.Sprintf("style %s fill:#989695\n", deprecatedPackage))) + _, _ = fmt.Fprintf(out, "style %s fill:#989695\n", deprecatedPackage) } if len(deprecatedChannelIDs) > 0 { for _, deprecatedChannel := range deprecatedChannelIDs { - _, _ = out.Write([]byte(fmt.Sprintf("style %s fill:#DCD0FF\n", deprecatedChannel))) + _, _ = fmt.Fprintf(out, "style %s fill:#DCD0FF\n", deprecatedChannel) } } @@ -274,12 +274,12 @@ func (writer *MermaidWriter) WriteChannels(cfg DeclarativeConfig, out io.Writer) if len(decoratedBundleIDs[key]) > 0 { b := slices.Clone(decoratedBundleIDs[key]) slices.Sort(b) - _, _ = out.Write([]byte(fmt.Sprintf("class %s %s\n", strings.Join(b, ","), key))) + _, _ = fmt.Fprintf(out, "class %s %s\n", strings.Join(b, ","), key) } } if len(skippedLinkIDs) > 0 { - _, _ = out.Write([]byte("linkStyle " + strings.Join(skippedLinkIDs, ",") + " stroke:#FF0000,stroke-width:3px,stroke-dasharray:5;\n")) + _, _ = fmt.Fprintf(out, "linkStyle %s %s\n", strings.Join(skippedLinkIDs, ","), "stroke:#FF0000,stroke-width:3px,stroke-dasharray:5;") } return nil diff --git a/cmd/opm/alpha/render-graph/cmd.go b/cmd/opm/alpha/render-graph/cmd.go index 67ecc32f5..a8a35ae5a 100644 --- a/cmd/opm/alpha/render-graph/cmd.go +++ b/cmd/opm/alpha/render-graph/cmd.go @@ -18,7 +18,7 @@ func NewCmd() *cobra.Command { render action.Render minEdge string specifiedPackageName string - drawV0Semantics bool + drawV0Semantics bool ) cmd := &cobra.Command{ Use: "render-graph [index-image | fbc-dir]",