From 4c93ad2685b80902d083826ab02c8b0a4318b971 Mon Sep 17 00:00:00 2001 From: Josh Sacks Date: Wed, 29 Jan 2025 15:13:49 -0800 Subject: [PATCH 01/20] add sync command to sync production split assignments with local schema --- cmds/sync.go | 113 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 113 insertions(+) create mode 100644 cmds/sync.go diff --git a/cmds/sync.go b/cmds/sync.go new file mode 100644 index 0000000..8ee726e --- /dev/null +++ b/cmds/sync.go @@ -0,0 +1,113 @@ +// fetch json from https://tt.betterment.com/api/v2/split_registry.json +// iterate through splits that start with "retail." +// replace assignments of values at ~/src/retail/testtrack/schema.yml + +package cmds + +import ( + "encoding/json" + "fmt" + "net/http" + "io/ioutil" + "os" + "github.com/spf13/cobra" + "gopkg.in/yaml.v2" +) + +var syncDoc = ` +Sync the local schema TestTrack assignments with the remote production TestTrack assignments. +` + +func init() { + rootCmd.AddCommand(syncCommand) +} + +var syncCommand = &cobra.Command{ + Use: "sync", + Short: "Sync TestTrack assignments with production", + Long: syncDoc, + Run: func(cmd *cobra.Command, args []string) { + Sync() + }, +} + +func readYAML(filePath string) (map[string]interface{}, error) { + file, err := os.Open(filePath) + if err != nil { + return nil, fmt.Errorf("error opening YAML file: %v", err) + } + defer file.Close() + + fileData, err := ioutil.ReadAll(file) + if err != nil { + return nil, fmt.Errorf("error reading YAML file: %v", err) + } + + var yamlData map[string]interface{} + if err := yaml.Unmarshal(fileData, &yamlData); err != nil { + return nil, fmt.Errorf("error unmarshalling YAML: %v", err) + } + + return yamlData, nil +} + +func Sync() { + url := "https://tt.betterment.com/api/v2/split_registry.json" + res, err := http.Get(url) + + if err != nil { + fmt.Printf("Error fetching JSON: %v\n", err) + return + } + + defer res.Body.Close() + var jsonData map[string]interface{} + if err := json.NewDecoder(res.Body).Decode(&jsonData); err != nil { + fmt.Printf("Error decoding JSON: %v\n", err) + return + } + + splits, ok := jsonData["splits"].(map[string]interface{}) + if !ok { + fmt.Println("Error: 'splits' key not found or not a map") + return + } + + // yamlFilePath := "testtrack/schema.yml" + yamlFilePath := "../../retail/retail/testtrack/schema.yml" + yamlData, err := readYAML(yamlFilePath) + if err != nil { + fmt.Printf("Error reading YAML file: %v\n", err) + return + } + + fmt.Printf("YAML data: %+v\n", yamlData) + + for key, value := range splits { + for _, split := range yamlData["splits"].([]interface{}) { + splitMap, ok := split.(map[interface{}]interface{}) + if !ok { + continue + } + if splitMap["name"] == key { + valueMap, ok := value.(map[string]interface{}) + if !ok { + continue + } + splitMap["weights"] = valueMap["weights"] + } + } + } + + fmt.Printf("Yaml data:", yamlData) + + yamlBytes, err := yaml.Marshal(yamlData) + if err != nil { + fmt.Errorf("error marshalling YAML: %v", err) + } + + err = ioutil.WriteFile(yamlFilePath, yamlBytes, 0644) + if err != nil { + fmt.Errorf("error writing YAML file: %v", err) + } +} From ce1fb99ca39d1bf17feb2739cdc21b11d98ce48d Mon Sep 17 00:00:00 2001 From: Josh Sacks Date: Thu, 30 Jan 2025 08:16:19 -0800 Subject: [PATCH 02/20] move remote url to argument --- cmds/sync.go | 45 ++++++++++++++++++--------------------------- 1 file changed, 18 insertions(+), 27 deletions(-) diff --git a/cmds/sync.go b/cmds/sync.go index 8ee726e..f625d40 100644 --- a/cmds/sync.go +++ b/cmds/sync.go @@ -1,15 +1,12 @@ -// fetch json from https://tt.betterment.com/api/v2/split_registry.json -// iterate through splits that start with "retail." -// replace assignments of values at ~/src/retail/testtrack/schema.yml - package cmds import ( "encoding/json" "fmt" - "net/http" "io/ioutil" + "net/http" "os" + "github.com/spf13/cobra" "gopkg.in/yaml.v2" ) @@ -26,15 +23,16 @@ var syncCommand = &cobra.Command{ Use: "sync", Short: "Sync TestTrack assignments with production", Long: syncDoc, - Run: func(cmd *cobra.Command, args []string) { - Sync() + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + return Sync(args[0]) }, } func readYAML(filePath string) (map[string]interface{}, error) { file, err := os.Open(filePath) if err != nil { - return nil, fmt.Errorf("error opening YAML file: %v", err) + return nil, fmt.Errorf("error opening YAML file: %v", err) } defer file.Close() @@ -45,44 +43,37 @@ func readYAML(filePath string) (map[string]interface{}, error) { var yamlData map[string]interface{} if err := yaml.Unmarshal(fileData, &yamlData); err != nil { - return nil, fmt.Errorf("error unmarshalling YAML: %v", err) + return nil, fmt.Errorf("error unmarshalling YAML: %v", err) } return yamlData, nil } -func Sync() { - url := "https://tt.betterment.com/api/v2/split_registry.json" - res, err := http.Get(url) +func Sync(remoteUrl string) error { + res, err := http.Get(remoteUrl) if err != nil { - fmt.Printf("Error fetching JSON: %v\n", err) - return + return fmt.Errorf("Error fetching JSON: %v\n", err) } defer res.Body.Close() var jsonData map[string]interface{} if err := json.NewDecoder(res.Body).Decode(&jsonData); err != nil { - fmt.Printf("Error decoding JSON: %v\n", err) - return + return fmt.Errorf("Error decoding JSON: %v\n", err) } splits, ok := jsonData["splits"].(map[string]interface{}) if !ok { - fmt.Println("Error: 'splits' key not found or not a map") - return + return fmt.Errorf("Error: 'splits' key not found or not a map") } // yamlFilePath := "testtrack/schema.yml" yamlFilePath := "../../retail/retail/testtrack/schema.yml" yamlData, err := readYAML(yamlFilePath) if err != nil { - fmt.Printf("Error reading YAML file: %v\n", err) - return + return fmt.Errorf("Error reading YAML file: %v\n", err) } - fmt.Printf("YAML data: %+v\n", yamlData) - for key, value := range splits { for _, split := range yamlData["splits"].([]interface{}) { splitMap, ok := split.(map[interface{}]interface{}) @@ -92,22 +83,22 @@ func Sync() { if splitMap["name"] == key { valueMap, ok := value.(map[string]interface{}) if !ok { - continue + continue } splitMap["weights"] = valueMap["weights"] } } } - fmt.Printf("Yaml data:", yamlData) - yamlBytes, err := yaml.Marshal(yamlData) if err != nil { - fmt.Errorf("error marshalling YAML: %v", err) + return fmt.Errorf("error marshalling YAML: %v", err) } err = ioutil.WriteFile(yamlFilePath, yamlBytes, 0644) if err != nil { - fmt.Errorf("error writing YAML file: %v", err) + return fmt.Errorf("error writing YAML file: %v", err) } + + return nil } From b46c43b3aff064f52d119e78eb956c8b88f032dc Mon Sep 17 00:00:00 2001 From: Josh Sacks Date: Thu, 30 Jan 2025 08:26:06 -0800 Subject: [PATCH 03/20] cleanup file --- cmds/sync.go | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/cmds/sync.go b/cmds/sync.go index f625d40..c5ced9c 100644 --- a/cmds/sync.go +++ b/cmds/sync.go @@ -13,6 +13,10 @@ import ( var syncDoc = ` Sync the local schema TestTrack assignments with the remote production TestTrack assignments. + +Example: + +testtrack sync http:://example.com/split_registry.json ` func init() { @@ -49,17 +53,18 @@ func readYAML(filePath string) (map[string]interface{}, error) { return yamlData, nil } -func Sync(remoteUrl string) error { - res, err := http.Get(remoteUrl) +// Sync synchronizes the local schema TestTrack assignments with the remote production TestTrack assignments. +func Sync(remoteURL string) error { + res, err := http.Get(remoteURL) if err != nil { - return fmt.Errorf("Error fetching JSON: %v\n", err) + return fmt.Errorf("Error fetching JSON: %v", err) } defer res.Body.Close() var jsonData map[string]interface{} if err := json.NewDecoder(res.Body).Decode(&jsonData); err != nil { - return fmt.Errorf("Error decoding JSON: %v\n", err) + return fmt.Errorf("Error decoding JSON: %v", err) } splits, ok := jsonData["splits"].(map[string]interface{}) @@ -67,11 +72,10 @@ func Sync(remoteUrl string) error { return fmt.Errorf("Error: 'splits' key not found or not a map") } - // yamlFilePath := "testtrack/schema.yml" - yamlFilePath := "../../retail/retail/testtrack/schema.yml" + yamlFilePath := "testtrack/schema.yml" yamlData, err := readYAML(yamlFilePath) if err != nil { - return fmt.Errorf("Error reading YAML file: %v\n", err) + return fmt.Errorf("Error reading YAML file: %v", err) } for key, value := range splits { From fd208c9d7e4f222e84089ad7b77c503741774380 Mon Sep 17 00:00:00 2001 From: Josh Sacks Date: Thu, 30 Jan 2025 08:32:27 -0800 Subject: [PATCH 04/20] cleanup --- cmds/sync.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cmds/sync.go b/cmds/sync.go index c5ced9c..1b4387d 100644 --- a/cmds/sync.go +++ b/cmds/sync.go @@ -3,7 +3,7 @@ package cmds import ( "encoding/json" "fmt" - "io/ioutil" + "io" "net/http" "os" @@ -40,7 +40,7 @@ func readYAML(filePath string) (map[string]interface{}, error) { } defer file.Close() - fileData, err := ioutil.ReadAll(file) + fileData, err := io.ReadAll(file) if err != nil { return nil, fmt.Errorf("error reading YAML file: %v", err) } @@ -99,7 +99,7 @@ func Sync(remoteURL string) error { return fmt.Errorf("error marshalling YAML: %v", err) } - err = ioutil.WriteFile(yamlFilePath, yamlBytes, 0644) + err = os.WriteFile(yamlFilePath, yamlBytes, 0644) if err != nil { return fmt.Errorf("error writing YAML file: %v", err) } From ce195921f17dcf1d2553d9318cacc1d4c8a053ee Mon Sep 17 00:00:00 2001 From: Josh Sacks Date: Thu, 30 Jan 2025 14:27:34 -0800 Subject: [PATCH 05/20] update code to use schema read and write methods --- cmds/sync.go | 63 ++++++++++++++++++---------------------------------- 1 file changed, 21 insertions(+), 42 deletions(-) diff --git a/cmds/sync.go b/cmds/sync.go index 1b4387d..fbc9154 100644 --- a/cmds/sync.go +++ b/cmds/sync.go @@ -3,10 +3,9 @@ package cmds import ( "encoding/json" "fmt" - "io" "net/http" - "os" + "github.com/Betterment/testtrack-cli/schema" "github.com/spf13/cobra" "gopkg.in/yaml.v2" ) @@ -33,24 +32,12 @@ var syncCommand = &cobra.Command{ }, } -func readYAML(filePath string) (map[string]interface{}, error) { - file, err := os.Open(filePath) - if err != nil { - return nil, fmt.Errorf("error opening YAML file: %v", err) - } - defer file.Close() - - fileData, err := io.ReadAll(file) - if err != nil { - return nil, fmt.Errorf("error reading YAML file: %v", err) +func toMapSlice(m map[string]interface{}) yaml.MapSlice { + mapSlice := yaml.MapSlice{} + for k, v := range m { + mapSlice = append(mapSlice, yaml.MapItem{Key: k, Value: v}) } - - var yamlData map[string]interface{} - if err := yaml.Unmarshal(fileData, &yamlData); err != nil { - return nil, fmt.Errorf("error unmarshalling YAML: %v", err) - } - - return yamlData, nil + return mapSlice } // Sync synchronizes the local schema TestTrack assignments with the remote production TestTrack assignments. @@ -67,42 +54,34 @@ func Sync(remoteURL string) error { return fmt.Errorf("Error decoding JSON: %v", err) } - splits, ok := jsonData["splits"].(map[string]interface{}) + remoteSplits, ok := jsonData["splits"].(map[string]interface{}) if !ok { return fmt.Errorf("Error: 'splits' key not found or not a map") } - yamlFilePath := "testtrack/schema.yml" - yamlData, err := readYAML(yamlFilePath) + localSchema, err := schema.Read() if err != nil { - return fmt.Errorf("Error reading YAML file: %v", err) + return err } - for key, value := range splits { - for _, split := range yamlData["splits"].([]interface{}) { - splitMap, ok := split.(map[interface{}]interface{}) - if !ok { - continue - } - if splitMap["name"] == key { - valueMap, ok := value.(map[string]interface{}) + for remoteSplitName, remoteWeight := range remoteSplits { + for ind, localSplit := range localSchema.Splits { + if localSplit.Name == remoteSplitName { + remoteWeightMap, ok := remoteWeight.(map[string]interface{}) if !ok { - continue + return fmt.Errorf("failed to cast remoteWeight to map[string]interface{}") + } + fmt.Println( remoteWeightMap["weights"]) + if weightsMap, ok := remoteWeightMap["weights"].(map[string]interface{}); ok { + localSchema.Splits[ind].Weights = toMapSlice(weightsMap) + } else { + return fmt.Errorf("failed to cast weights to yaml.MapSlice") } - splitMap["weights"] = valueMap["weights"] } } } - yamlBytes, err := yaml.Marshal(yamlData) - if err != nil { - return fmt.Errorf("error marshalling YAML: %v", err) - } - - err = os.WriteFile(yamlFilePath, yamlBytes, 0644) - if err != nil { - return fmt.Errorf("error writing YAML file: %v", err) - } + schema.Write(localSchema) return nil } From cddbe6553a87db608279177164f2d9216867174a Mon Sep 17 00:00:00 2001 From: Josh Sacks Date: Thu, 30 Jan 2025 14:32:33 -0800 Subject: [PATCH 06/20] remove print statement --- cmds/sync.go | 1 - 1 file changed, 1 deletion(-) diff --git a/cmds/sync.go b/cmds/sync.go index fbc9154..e2e237b 100644 --- a/cmds/sync.go +++ b/cmds/sync.go @@ -71,7 +71,6 @@ func Sync(remoteURL string) error { if !ok { return fmt.Errorf("failed to cast remoteWeight to map[string]interface{}") } - fmt.Println( remoteWeightMap["weights"]) if weightsMap, ok := remoteWeightMap["weights"].(map[string]interface{}); ok { localSchema.Splits[ind].Weights = toMapSlice(weightsMap) } else { From ed30cb126f352589b4934b4b0a5d4ce7befafe3b Mon Sep 17 00:00:00 2001 From: Josh Sacks Date: Thu, 30 Jan 2025 15:00:49 -0800 Subject: [PATCH 07/20] use built in server get method instead of passing in remote url --- cmds/sync.go | 22 ++++++---------------- 1 file changed, 6 insertions(+), 16 deletions(-) diff --git a/cmds/sync.go b/cmds/sync.go index e2e237b..adbdc4e 100644 --- a/cmds/sync.go +++ b/cmds/sync.go @@ -1,21 +1,16 @@ package cmds import ( - "encoding/json" "fmt" - "net/http" "github.com/Betterment/testtrack-cli/schema" + "github.com/Betterment/testtrack-cli/servers" "github.com/spf13/cobra" "gopkg.in/yaml.v2" ) var syncDoc = ` Sync the local schema TestTrack assignments with the remote production TestTrack assignments. - -Example: - -testtrack sync http:://example.com/split_registry.json ` func init() { @@ -26,9 +21,8 @@ var syncCommand = &cobra.Command{ Use: "sync", Short: "Sync TestTrack assignments with production", Long: syncDoc, - Args: cobra.ExactArgs(1), RunE: func(cmd *cobra.Command, args []string) error { - return Sync(args[0]) + return Sync() }, } @@ -41,18 +35,14 @@ func toMapSlice(m map[string]interface{}) yaml.MapSlice { } // Sync synchronizes the local schema TestTrack assignments with the remote production TestTrack assignments. -func Sync(remoteURL string) error { - res, err := http.Get(remoteURL) - +func Sync() error { + server, err := servers.New() if err != nil { - return fmt.Errorf("Error fetching JSON: %v", err) + return err } - defer res.Body.Close() var jsonData map[string]interface{} - if err := json.NewDecoder(res.Body).Decode(&jsonData); err != nil { - return fmt.Errorf("Error decoding JSON: %v", err) - } + server.Get("api/v2/split_registry.json", &jsonData) remoteSplits, ok := jsonData["splits"].(map[string]interface{}) if !ok { From 038b2b6e2cced34a8a1f2837302f443360bb9558 Mon Sep 17 00:00:00 2001 From: Josh Sacks Date: Fri, 31 Jan 2025 08:55:28 -0800 Subject: [PATCH 08/20] creating structs for json response --- cmds/sync.go | 39 ++++++++++++++------------------------ serializers/serializers.go | 12 +++++++++++- 2 files changed, 25 insertions(+), 26 deletions(-) diff --git a/cmds/sync.go b/cmds/sync.go index adbdc4e..e6cb29b 100644 --- a/cmds/sync.go +++ b/cmds/sync.go @@ -1,9 +1,8 @@ package cmds import ( - "fmt" - "github.com/Betterment/testtrack-cli/schema" + "github.com/Betterment/testtrack-cli/serializers" "github.com/Betterment/testtrack-cli/servers" "github.com/spf13/cobra" "gopkg.in/yaml.v2" @@ -26,14 +25,6 @@ var syncCommand = &cobra.Command{ }, } -func toMapSlice(m map[string]interface{}) yaml.MapSlice { - mapSlice := yaml.MapSlice{} - for k, v := range m { - mapSlice = append(mapSlice, yaml.MapItem{Key: k, Value: v}) - } - return mapSlice -} - // Sync synchronizes the local schema TestTrack assignments with the remote production TestTrack assignments. func Sync() error { server, err := servers.New() @@ -41,31 +32,20 @@ func Sync() error { return err } - var jsonData map[string]interface{} + var jsonData serializers.SplitRegistryJSON server.Get("api/v2/split_registry.json", &jsonData) - remoteSplits, ok := jsonData["splits"].(map[string]interface{}) - if !ok { - return fmt.Errorf("Error: 'splits' key not found or not a map") - } + remoteSplits := jsonData.Splits localSchema, err := schema.Read() if err != nil { return err } - for remoteSplitName, remoteWeight := range remoteSplits { + for remoteSplitName, remoteSplit := range remoteSplits { for ind, localSplit := range localSchema.Splits { if localSplit.Name == remoteSplitName { - remoteWeightMap, ok := remoteWeight.(map[string]interface{}) - if !ok { - return fmt.Errorf("failed to cast remoteWeight to map[string]interface{}") - } - if weightsMap, ok := remoteWeightMap["weights"].(map[string]interface{}); ok { - localSchema.Splits[ind].Weights = toMapSlice(weightsMap) - } else { - return fmt.Errorf("failed to cast weights to yaml.MapSlice") - } + localSchema.Splits[ind].Weights = convertToMapSlice(remoteSplit.Weights) } } } @@ -74,3 +54,12 @@ func Sync() error { return nil } + +// convertToMapSlice converts a map[string]int to yaml.MapSlice +func convertToMapSlice(weights map[string]int) yaml.MapSlice { + var mapSlice yaml.MapSlice + for k, v := range weights { + mapSlice = append(mapSlice, yaml.MapItem{Key: k, Value: v}) + } + return mapSlice +} diff --git a/serializers/serializers.go b/serializers/serializers.go index 62fa537..95aea84 100644 --- a/serializers/serializers.go +++ b/serializers/serializers.go @@ -45,12 +45,22 @@ type SplitYAML struct { Owner string `yaml:"owner,omitempty"` } -// SplitJSON is is the JSON-marshalabe representation of a Split +// SplitJSON is the JSON-marshalabe representation of a Split type SplitJSON struct { Name string `json:"name"` WeightingRegistry map[string]int `json:"weighting_registry"` } +// RegistryAssignment is the JSON-marshalable representation of an assignment in a SplitRegistry +type RegistryAssignment struct { + Weights map[string]int `json:"weights"` +} + +// SplitRegistryJSON is the JSON-marshalable representation of a SplitRegistry +type SplitRegistry struct { + Splits map[string]RegistryAssignment `json:"splits"` +} + // SplitRetirement is the JSON and YAML-marshalable representation of a SplitRetirement type SplitRetirement struct { Split string `json:"split"` From 57181995fd951c54cc88cc517dbcf93efaca4e6d Mon Sep 17 00:00:00 2001 From: Josh Sacks Date: Fri, 31 Jan 2025 09:01:04 -0800 Subject: [PATCH 09/20] minor fix --- cmds/sync.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmds/sync.go b/cmds/sync.go index e6cb29b..9ca5a8a 100644 --- a/cmds/sync.go +++ b/cmds/sync.go @@ -32,7 +32,7 @@ func Sync() error { return err } - var jsonData serializers.SplitRegistryJSON + var jsonData serializers.SplitRegistry server.Get("api/v2/split_registry.json", &jsonData) remoteSplits := jsonData.Splits From de2bcdd2afc5f9a43e3a7a34807c2df06e967974 Mon Sep 17 00:00:00 2001 From: Josh Sacks Date: Fri, 31 Jan 2025 09:18:00 -0800 Subject: [PATCH 10/20] refactor to resuse ToYAML method from weights --- cmds/sync.go | 22 ++++++---------------- 1 file changed, 6 insertions(+), 16 deletions(-) diff --git a/cmds/sync.go b/cmds/sync.go index 9ca5a8a..8b0932a 100644 --- a/cmds/sync.go +++ b/cmds/sync.go @@ -4,8 +4,8 @@ import ( "github.com/Betterment/testtrack-cli/schema" "github.com/Betterment/testtrack-cli/serializers" "github.com/Betterment/testtrack-cli/servers" + "github.com/Betterment/testtrack-cli/splits" "github.com/spf13/cobra" - "gopkg.in/yaml.v2" ) var syncDoc = ` @@ -32,20 +32,19 @@ func Sync() error { return err } - var jsonData serializers.SplitRegistry - server.Get("api/v2/split_registry.json", &jsonData) - - remoteSplits := jsonData.Splits + var splitRegistry serializers.SplitRegistry + server.Get("api/v2/split_registry.json", &splitRegistry) localSchema, err := schema.Read() if err != nil { return err } - for remoteSplitName, remoteSplit := range remoteSplits { + for remoteSplitName, remoteSplit := range splitRegistry.Splits { for ind, localSplit := range localSchema.Splits { if localSplit.Name == remoteSplitName { - localSchema.Splits[ind].Weights = convertToMapSlice(remoteSplit.Weights) + weights := splits.Weights(remoteSplit.Weights) + localSchema.Splits[ind].Weights = weights.ToYAML() } } } @@ -54,12 +53,3 @@ func Sync() error { return nil } - -// convertToMapSlice converts a map[string]int to yaml.MapSlice -func convertToMapSlice(weights map[string]int) yaml.MapSlice { - var mapSlice yaml.MapSlice - for k, v := range weights { - mapSlice = append(mapSlice, yaml.MapItem{Key: k, Value: v}) - } - return mapSlice -} From f1bdc5357185f9e89956ca63774d931249fcab98 Mon Sep 17 00:00:00 2001 From: Josh Sacks Date: Fri, 31 Jan 2025 09:20:31 -0800 Subject: [PATCH 11/20] renaming --- serializers/serializers.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/serializers/serializers.go b/serializers/serializers.go index 95aea84..ef67afc 100644 --- a/serializers/serializers.go +++ b/serializers/serializers.go @@ -56,7 +56,7 @@ type RegistryAssignment struct { Weights map[string]int `json:"weights"` } -// SplitRegistryJSON is the JSON-marshalable representation of a SplitRegistry +// SplitRegistry is the JSON-marshalable representation of a SplitRegistry type SplitRegistry struct { Splits map[string]RegistryAssignment `json:"splits"` } From 9686b9888c42b4c195354292eef30942edd27499 Mon Sep 17 00:00:00 2001 From: Josh Sacks Date: Fri, 31 Jan 2025 09:26:48 -0800 Subject: [PATCH 12/20] minor optimization --- cmds/sync.go | 1 + 1 file changed, 1 insertion(+) diff --git a/cmds/sync.go b/cmds/sync.go index 8b0932a..f090880 100644 --- a/cmds/sync.go +++ b/cmds/sync.go @@ -45,6 +45,7 @@ func Sync() error { if localSplit.Name == remoteSplitName { weights := splits.Weights(remoteSplit.Weights) localSchema.Splits[ind].Weights = weights.ToYAML() + continue } } } From 32d6c0ff239386fb7780cf529245d885982f04f6 Mon Sep 17 00:00:00 2001 From: Josh Sacks Date: Fri, 31 Jan 2025 09:31:29 -0800 Subject: [PATCH 13/20] another optimization --- cmds/sync.go | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/cmds/sync.go b/cmds/sync.go index f090880..bbc38c8 100644 --- a/cmds/sync.go +++ b/cmds/sync.go @@ -40,13 +40,11 @@ func Sync() error { return err } - for remoteSplitName, remoteSplit := range splitRegistry.Splits { - for ind, localSplit := range localSchema.Splits { - if localSplit.Name == remoteSplitName { - weights := splits.Weights(remoteSplit.Weights) - localSchema.Splits[ind].Weights = weights.ToYAML() - continue - } + for ind, localSplit := range localSchema.Splits { + remoteSplit, exists := splitRegistry.Splits[localSplit.Name] + if exists { + weights := splits.Weights(remoteSplit.Weights) + localSchema.Splits[ind].Weights = weights.ToYAML() } } From 54f9285e3cc6c09a61b24bcb1cb71eaee7f93bfa Mon Sep 17 00:00:00 2001 From: Josh Sacks Date: Fri, 31 Jan 2025 10:30:23 -0800 Subject: [PATCH 14/20] trigger build From 2b4d0748506ede45544e8249fd252fc51231747f Mon Sep 17 00:00:00 2001 From: Josh Sacks Date: Fri, 31 Jan 2025 10:35:28 -0800 Subject: [PATCH 15/20] update var names --- cmds/sync.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmds/sync.go b/cmds/sync.go index bbc38c8..768217f 100644 --- a/cmds/sync.go +++ b/cmds/sync.go @@ -43,8 +43,8 @@ func Sync() error { for ind, localSplit := range localSchema.Splits { remoteSplit, exists := splitRegistry.Splits[localSplit.Name] if exists { - weights := splits.Weights(remoteSplit.Weights) - localSchema.Splits[ind].Weights = weights.ToYAML() + remoteWeights := splits.Weights(remoteSplit.Weights) + localSchema.Splits[ind].Weights = remoteWeights.ToYAML() } } From d3c9d06fdc467d76ff9a7a7f4e70175035cdec24 Mon Sep 17 00:00:00 2001 From: Josh Sacks Date: Fri, 31 Jan 2025 11:47:22 -0800 Subject: [PATCH 16/20] update version --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index a8d3773..03c2a81 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ SHELL = /bin/sh -VERSION=1.5.0 +VERSION=1.6.0 BUILD=`git rev-parse HEAD` LDFLAGS=-ldflags "-w -s \ From f9845ce58749b1c1e84d53d6a9b685325e8db84a Mon Sep 17 00:00:00 2001 From: Josh Sacks Date: Mon, 3 Feb 2025 08:47:57 -0800 Subject: [PATCH 17/20] add error handling for GET and write --- cmds/sync.go | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/cmds/sync.go b/cmds/sync.go index 768217f..a43fef1 100644 --- a/cmds/sync.go +++ b/cmds/sync.go @@ -20,7 +20,8 @@ var syncCommand = &cobra.Command{ Use: "sync", Short: "Sync TestTrack assignments with production", Long: syncDoc, - RunE: func(cmd *cobra.Command, args []string) error { + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, _ []string) error { return Sync() }, } @@ -33,7 +34,10 @@ func Sync() error { } var splitRegistry serializers.SplitRegistry - server.Get("api/v2/split_registry.json", &splitRegistry) + err = server.Get("api/v2/split_registry.json", &splitRegistry) + if err != nil { + return err + } localSchema, err := schema.Read() if err != nil { @@ -48,7 +52,9 @@ func Sync() error { } } - schema.Write(localSchema) + if err:= schema.Write(localSchema); err != nil { + return err + } return nil } From d6cae25d580d9f012d57497749b85ac0942059e3 Mon Sep 17 00:00:00 2001 From: Josh Sacks Date: Mon, 3 Feb 2025 08:50:04 -0800 Subject: [PATCH 18/20] cleanup --- cmds/sync.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmds/sync.go b/cmds/sync.go index a43fef1..f90c589 100644 --- a/cmds/sync.go +++ b/cmds/sync.go @@ -52,7 +52,7 @@ func Sync() error { } } - if err:= schema.Write(localSchema); err != nil { + if err := schema.Write(localSchema); err != nil { return err } From f0e85c6132611ae2961a27c9cbe84a86d15e38d6 Mon Sep 17 00:00:00 2001 From: Josh Sacks Date: Mon, 3 Feb 2025 10:36:10 -0800 Subject: [PATCH 19/20] update type names --- cmds/sync.go | 2 +- serializers/serializers.go | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/cmds/sync.go b/cmds/sync.go index f90c589..b3491e2 100644 --- a/cmds/sync.go +++ b/cmds/sync.go @@ -33,7 +33,7 @@ func Sync() error { return err } - var splitRegistry serializers.SplitRegistry + var splitRegistry serializers.RemoteRegistry err = server.Get("api/v2/split_registry.json", &splitRegistry) if err != nil { return err diff --git a/serializers/serializers.go b/serializers/serializers.go index ef67afc..7188161 100644 --- a/serializers/serializers.go +++ b/serializers/serializers.go @@ -51,14 +51,14 @@ type SplitJSON struct { WeightingRegistry map[string]int `json:"weighting_registry"` } -// RegistryAssignment is the JSON-marshalable representation of an assignment in a SplitRegistry -type RegistryAssignment struct { +// RemoteRegistrySplit is the JSON-marshalable representation of a server-provided split configuration +type RemoteRegistrySplit struct { Weights map[string]int `json:"weights"` } -// SplitRegistry is the JSON-marshalable representation of a SplitRegistry -type SplitRegistry struct { - Splits map[string]RegistryAssignment `json:"splits"` +// RemoteRegistry is the JSON-marshalable representation of a server-provided split registry +type RemoteRegistry struct { + Splits map[string]RemoteRegistrySplit `json:"splits"` } // SplitRetirement is the JSON and YAML-marshalable representation of a SplitRetirement From 8c3ffdc15c1c8e75ef9fd68afebe981470501ad1 Mon Sep 17 00:00:00 2001 From: Josh Sacks Date: Mon, 3 Feb 2025 10:46:29 -0800 Subject: [PATCH 20/20] trigger build