github.com/koko1123/flow-go-1@v0.29.6/utils/test_matrix/test_matrix.go (about) 1 package main 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "os" 7 "strings" 8 9 "golang.org/x/tools/go/packages" 10 ) 11 12 const flowPackagePrefix = "github.com/koko1123/flow-go-1/" 13 const ciMatrixName = "dynamicMatrix" 14 15 // testMatrix represents a single GitHub Actions test matrix combination that consists of a name and a list of flow-go packages associated with that name. 16 type testMatrix struct { 17 Name string `json:"name"` 18 Packages string `json:"packages"` 19 } 20 21 // Generates a list of packages to test that will be passed to GitHub Actions 22 func main() { 23 if len(os.Args) == 1 { 24 fmt.Fprintln(os.Stderr, "must have at least 1 package listed") 25 return 26 } 27 28 allFlowPackages := listAllFlowPackages() 29 30 targetPackages, seenPackages := listTargetPackages(os.Args[1:], allFlowPackages) 31 32 otherPackages := listOtherPackages(allFlowPackages, seenPackages) 33 34 testMatrix := generateTestMatrix(targetPackages, otherPackages) 35 36 // generate JSON output that will be read in by CI matrix 37 // can't use json.MarshalIndent because fromJSON() in CI can’t read JSON with any spaces 38 testMatrixBytes, err := json.Marshal(testMatrix) 39 if err != nil { 40 panic(err) 41 } 42 43 // this string will be read by CI to generate groups of tests to run in separate CI jobs 44 testMatrixStr := "::set-output name=" + ciMatrixName + "::" + string(testMatrixBytes) 45 46 // very important to add newline character at the end of the compacted JSON - otherwise fromJSON() in CI will throw unmarshalling error 47 fmt.Println(testMatrixStr) 48 } 49 50 func generateTestMatrix(targetPackages map[string][]string, otherPackages []string) []testMatrix { 51 52 var testMatrices []testMatrix 53 54 for names := range targetPackages { 55 targetTestMatrix := testMatrix{ 56 Name: names, 57 Packages: strings.Join(targetPackages[names], " "), 58 } 59 testMatrices = append(testMatrices, targetTestMatrix) 60 } 61 62 // add the other packages after all target packages added 63 otherTestMatrix := testMatrix{ 64 Name: "others", 65 Packages: strings.Join(otherPackages, " "), 66 } 67 68 testMatrices = append(testMatrices, otherTestMatrix) 69 70 return testMatrices 71 } 72 73 // listTargetPackages returns a map-list of target packages to run as separate CI jobs, based on a list of target package prefixes. 74 // It also returns a list of the "seen" packages that can then be used to extract the remaining packages to run (in a separate CI job). 75 func listTargetPackages(targetPackagePrefixes []string, allFlowPackages []string) (map[string][]string, map[string]string) { 76 targetPackages := make(map[string][]string) 77 78 // Stores list of packages already seen / allocated to other lists. Needed for the last package which will 79 // have all the leftover packages that weren't allocated to a separate list (CI job). 80 // It's a map, not a list, to make it easier to check if a package was seen or not. 81 seenPackages := make(map[string]string) 82 83 // iterate over the target packages to run as separate CI jobs 84 for _, targetPackagePrefix := range targetPackagePrefixes { 85 var targetPackage []string 86 87 // go through all packages to see which ones to pull out 88 for _, allPackage := range allFlowPackages { 89 if strings.HasPrefix(allPackage, flowPackagePrefix+targetPackagePrefix) { 90 targetPackage = append(targetPackage, allPackage) 91 seenPackages[allPackage] = allPackage 92 } 93 } 94 if len(targetPackage) == 0 { 95 panic("no packages exist with prefix " + targetPackagePrefix) 96 } 97 targetPackages[targetPackagePrefix] = targetPackage 98 } 99 return targetPackages, seenPackages 100 } 101 102 // listOtherPackages compiles the remaining packages that don't match any of the target packages. 103 func listOtherPackages(allFlowPackages []string, seenPackages map[string]string) []string { 104 var otherPackages []string 105 106 for _, allFlowPackage := range allFlowPackages { 107 _, seen := seenPackages[allFlowPackage] 108 if !seen { 109 otherPackages = append(otherPackages, allFlowPackage) 110 } 111 } 112 113 if len(otherPackages) == 0 { 114 panic("other packages list can't be 0") 115 } 116 return otherPackages 117 } 118 119 func listAllFlowPackages() []string { 120 flowPackages, err := packages.Load(&packages.Config{}, "./...") 121 122 if err != nil { 123 panic(err) 124 } 125 var flowPackagesStr []string 126 for _, p := range flowPackages { 127 flowPackagesStr = append(flowPackagesStr, p.PkgPath) 128 } 129 return flowPackagesStr 130 }