From ed22f82c01bf2ef3ca5cf83789fc234b7a03055c Mon Sep 17 00:00:00 2001 From: LaMont Jones Date: Wed, 29 May 2024 13:56:39 -0700 Subject: [PATCH] Create inheritance graph release-config now creates `inhertance_graph-${TARGET_PRODUCT}.dot` showing the inheritance graph for all release configs present for ${TARGET_PRODUCT}. Bug: 328495189 Test: manual, TH Change-Id: I79242eaa848e0374b33f376e44d8938e9d398e21 --- cmd/release_config/release_config/main.go | 10 +++- .../release_config_lib/release_configs.go | 60 ++++++++++++++++++- 2 files changed, 68 insertions(+), 2 deletions(-) diff --git a/cmd/release_config/release_config/main.go b/cmd/release_config/release_config/main.go index 762f5614b..24deacc9a 100644 --- a/cmd/release_config/release_config/main.go +++ b/cmd/release_config/release_config/main.go @@ -31,7 +31,7 @@ func main() { var outputDir string var err error var configs *rc_lib.ReleaseConfigs - var json, pb, textproto bool + var json, pb, textproto, inheritance bool var product string var allMake bool var useBuildVar bool @@ -52,6 +52,7 @@ func main() { flag.BoolVar(&json, "json", true, "write artifacts as json") flag.BoolVar(&pb, "pb", true, "write artifacts as binary protobuf") flag.BoolVar(&allMake, "all_make", false, "write makefiles for all release configs") + flag.BoolVar(&inheritance, "inheritance", true, "write inheritance graph") flag.BoolVar(&useBuildVar, "use_get_build_var", false, "use get_build_var PRODUCT_RELEASE_CONFIG_MAPS") flag.BoolVar(&guard, "guard", true, "whether to guard with RELEASE_BUILD_FLAGS_IN_PROTOBUF") @@ -102,6 +103,13 @@ func main() { } } } + if inheritance { + inheritPath := filepath.Join(outputDir, fmt.Sprintf("inheritance_graph-%s.dot", product)) + err = configs.WriteInheritanceGraph(inheritPath) + if err != nil { + panic(err) + } + } if json { err = configs.WriteArtifact(outputDir, product, "json") if err != nil { diff --git a/cmd/release_config/release_config_lib/release_configs.go b/cmd/release_config/release_config_lib/release_configs.go index c62a78e76..bad91445e 100644 --- a/cmd/release_config/release_config_lib/release_configs.go +++ b/cmd/release_config/release_config_lib/release_configs.go @@ -78,6 +78,54 @@ type ReleaseConfigs struct { configDirIndexes ReleaseConfigDirMap } +func (configs *ReleaseConfigs) WriteInheritanceGraph(outFile string) error { + data := []string{ + "digraph {", + "graph [ ratio=.5 ]", + "node [ shape=box style=filled fillcolor=white colorscheme=svg fontcolor=black ]", + } + usedAliases := make(map[string]bool) + for _, config := range configs.GetSortedReleaseConfigs() { + var fillColor string + inherits := []string{} + for _, inherit := range config.InheritNames { + if inherit == "root" { + // Only show "root" if we have no other inheritance. + if len(config.InheritNames) > 1 { + continue + } + } + data = append(data, fmt.Sprintf(`"%s" -> "%s"`, config.Name, inherit)) + inherits = append(inherits, inherit) + // If inheriting an alias, add a link from the alias to that release config. + if name, found := configs.Aliases[inherit]; found { + if !usedAliases[inherit] { + usedAliases[inherit] = true + data = append(data, fmt.Sprintf(`"%s" -> "%s"`, inherit, *name)) + data = append(data, + fmt.Sprintf(`"%s" [ label="%s\ncurrently: %s" shape=oval ]`, + inherit, inherit, *name)) + } + } + } + label := config.Name + if len(inherits) > 0 { + label += "\\ninherits: " + strings.Join(inherits, " ") + } + if len(config.OtherNames) > 0 { + label += "\\nother names: " + strings.Join(config.OtherNames, " ") + } + // The active release config has a light blue fill. + if config.Name == *configs.Artifact.ReleaseConfig.Name { + fillColor = `fillcolor="#d2e3fc" ` + } + data = append(data, + fmt.Sprintf(`"%s" [ label="%s" %s]`, config.Name, label, fillColor)) + } + data = append(data, "}") + return os.WriteFile(outFile, []byte(strings.Join(data, "\n")), 0644) +} + // Write the "all_release_configs" artifact. // // The file will be in "{outDir}/all_release_configs-{product}.{format}" @@ -256,7 +304,17 @@ func (configs *ReleaseConfigs) LoadReleaseConfigMap(path string, ConfigDirIndex } config := configs.ReleaseConfigs[name] config.FilesUsedMap[path] = true - config.InheritNames = append(config.InheritNames, releaseConfigContribution.proto.Inherits...) + inheritNames := make(map[string]bool) + for _, inh := range config.InheritNames { + inheritNames[inh] = true + } + // If this contribution says to inherit something we already inherited, we do not want the duplicate. + for _, cInh := range releaseConfigContribution.proto.Inherits { + if !inheritNames[cInh] { + config.InheritNames = append(config.InheritNames, cInh) + inheritNames[cInh] = true + } + } // Only walk flag_values/{RELEASE} for defined releases. err2 := WalkTextprotoFiles(dir, filepath.Join("flag_values", name), func(path string, d fs.DirEntry, err error) error {