From 8ecf2ceda5b8aef11769e97a8070d213fdee15b2 Mon Sep 17 00:00:00 2001 From: Nadia Mayor Date: Thu, 13 Nov 2025 14:57:40 -0300 Subject: [PATCH 1/3] Added fallback treatment and calculator --- dtos/fallbacktreatment.go | 63 ++++++++++++++++++++++++++++++++++ dtos/fallbacktreatment_test.go | 63 ++++++++++++++++++++++++++++++++++ 2 files changed, 126 insertions(+) create mode 100644 dtos/fallbacktreatment.go create mode 100644 dtos/fallbacktreatment_test.go diff --git a/dtos/fallbacktreatment.go b/dtos/fallbacktreatment.go new file mode 100644 index 00000000..5a0615da --- /dev/null +++ b/dtos/fallbacktreatment.go @@ -0,0 +1,63 @@ +package dtos + +const ( + labelPrefix = "fallback - " +) + +type FallbackTreatment struct { + Treatment string + Config string + Label *string +} + +type FallbackTreatmentConfig struct { + GlobalFallbackTreatment *FallbackTreatment + byFlagFallbackTreatment map[string]FallbackTreatment +} + +type FallbackTreatmentCalculator interface { + Resolve(flagName string, label string) FallbackTreatment +} + +type FallbackTreatmentCalculatorImp struct { + fallbackTreatmentConfig *FallbackTreatmentConfig +} + +func NewFallbackTreatmentCalculatorImp(fallbackTreatmentConfig *FallbackTreatmentConfig) FallbackTreatmentCalculatorImp { + return FallbackTreatmentCalculatorImp{ + fallbackTreatmentConfig: fallbackTreatmentConfig, + } +} + +func (f *FallbackTreatmentCalculatorImp) Resolve(flagName string, label *string) FallbackTreatment { + if f.fallbackTreatmentConfig != nil { + if byFlag := f.fallbackTreatmentConfig.byFlagFallbackTreatment; byFlag != nil { + if val, ok := byFlag[flagName]; ok { + return FallbackTreatment{ + Treatment: val.Treatment, + Config: val.Config, + Label: f.resolveLabel(label), + } + } + } + if f.fallbackTreatmentConfig.GlobalFallbackTreatment != nil { + return FallbackTreatment{ + Treatment: f.fallbackTreatmentConfig.GlobalFallbackTreatment.Treatment, + Config: f.fallbackTreatmentConfig.GlobalFallbackTreatment.Config, + Label: f.resolveLabel(label), + } + } + } + return FallbackTreatment{ + Treatment: "control", + Label: label, + } +} + +func (f *FallbackTreatmentCalculatorImp) resolveLabel(label *string) *string { + if label == nil { + return nil + } + result := labelPrefix + *label + return &result +} diff --git a/dtos/fallbacktreatment_test.go b/dtos/fallbacktreatment_test.go new file mode 100644 index 00000000..c2b9714c --- /dev/null +++ b/dtos/fallbacktreatment_test.go @@ -0,0 +1,63 @@ +package dtos + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestFallbackTreatmentCalculatorResolve(t *testing.T) { + // Initial setup with both global and flag-specific treatments + config := &FallbackTreatmentConfig{ + GlobalFallbackTreatment: &FallbackTreatment{ + Treatment: "global_treatment", + Config: "global_config", + }, + byFlagFallbackTreatment: map[string]FallbackTreatment{ + "flag1": { + Treatment: "flag1_treatment", + Config: "flag1_config", + }, + }, + } + calc := NewFallbackTreatmentCalculatorImp(config) + + // Test flag-specific treatment with label + label := "some_label" + result := calc.Resolve("flag1", &label) + assert.Equal(t, "flag1_treatment", result.Treatment) + assert.Equal(t, "flag1_config", result.Config) + assert.Equal(t, "fallback - some_label", *result.Label) + + // Test fallback to global treatment when flag not found + result = calc.Resolve("flag2", &label) + assert.Equal(t, "global_treatment", result.Treatment) + assert.Equal(t, "global_config", result.Config) + assert.Equal(t, "fallback - some_label", *result.Label) + + // Test nil label handling + result = calc.Resolve("flag1", nil) + assert.Equal(t, "flag1_treatment", result.Treatment) + assert.Equal(t, "flag1_config", result.Config) + assert.Nil(t, result.Label) + + // Test default control when no config + calcNoConfig := NewFallbackTreatmentCalculatorImp(nil) + result = calcNoConfig.Resolve("flag1", &label) + assert.Equal(t, "control", result.Treatment) + assert.Equal(t, "", result.Config) + assert.Equal(t, "some_label", *result.Label) + + // Test global treatment when no flag-specific treatments exist + configGlobalOnly := &FallbackTreatmentConfig{ + GlobalFallbackTreatment: &FallbackTreatment{ + Treatment: "global_treatment", + Config: "global_config", + }, + } + calcGlobalOnly := NewFallbackTreatmentCalculatorImp(configGlobalOnly) + result = calcGlobalOnly.Resolve("any_flag", &label) + assert.Equal(t, "global_treatment", result.Treatment) + assert.Equal(t, "global_config", result.Config) + assert.Equal(t, "fallback - some_label", *result.Label) +} \ No newline at end of file From c1a531abd773d6c1facfca11cf1a50ca1c928a8e Mon Sep 17 00:00:00 2001 From: Nadia Mayor Date: Fri, 14 Nov 2025 11:56:51 -0300 Subject: [PATCH 2/3] Updated test cases --- dtos/fallbacktreatment.go | 2 +- dtos/fallbacktreatment_test.go | 18 +++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/dtos/fallbacktreatment.go b/dtos/fallbacktreatment.go index 5a0615da..e1c30a44 100644 --- a/dtos/fallbacktreatment.go +++ b/dtos/fallbacktreatment.go @@ -6,7 +6,7 @@ const ( type FallbackTreatment struct { Treatment string - Config string + Config *string Label *string } diff --git a/dtos/fallbacktreatment_test.go b/dtos/fallbacktreatment_test.go index c2b9714c..c741a103 100644 --- a/dtos/fallbacktreatment_test.go +++ b/dtos/fallbacktreatment_test.go @@ -8,15 +8,15 @@ import ( func TestFallbackTreatmentCalculatorResolve(t *testing.T) { // Initial setup with both global and flag-specific treatments + stringConfig := "flag1_config" config := &FallbackTreatmentConfig{ GlobalFallbackTreatment: &FallbackTreatment{ Treatment: "global_treatment", - Config: "global_config", }, byFlagFallbackTreatment: map[string]FallbackTreatment{ "flag1": { Treatment: "flag1_treatment", - Config: "flag1_config", + Config: &stringConfig, }, }, } @@ -26,38 +26,38 @@ func TestFallbackTreatmentCalculatorResolve(t *testing.T) { label := "some_label" result := calc.Resolve("flag1", &label) assert.Equal(t, "flag1_treatment", result.Treatment) - assert.Equal(t, "flag1_config", result.Config) + assert.Equal(t, &stringConfig, result.Config) assert.Equal(t, "fallback - some_label", *result.Label) // Test fallback to global treatment when flag not found result = calc.Resolve("flag2", &label) assert.Equal(t, "global_treatment", result.Treatment) - assert.Equal(t, "global_config", result.Config) + assert.Nil(t, result.Config) assert.Equal(t, "fallback - some_label", *result.Label) // Test nil label handling result = calc.Resolve("flag1", nil) assert.Equal(t, "flag1_treatment", result.Treatment) - assert.Equal(t, "flag1_config", result.Config) + assert.Equal(t, &stringConfig, result.Config) assert.Nil(t, result.Label) // Test default control when no config calcNoConfig := NewFallbackTreatmentCalculatorImp(nil) result = calcNoConfig.Resolve("flag1", &label) assert.Equal(t, "control", result.Treatment) - assert.Equal(t, "", result.Config) + assert.Nil(t, result.Config) assert.Equal(t, "some_label", *result.Label) // Test global treatment when no flag-specific treatments exist configGlobalOnly := &FallbackTreatmentConfig{ GlobalFallbackTreatment: &FallbackTreatment{ Treatment: "global_treatment", - Config: "global_config", + Config: nil, }, } calcGlobalOnly := NewFallbackTreatmentCalculatorImp(configGlobalOnly) result = calcGlobalOnly.Resolve("any_flag", &label) assert.Equal(t, "global_treatment", result.Treatment) - assert.Equal(t, "global_config", result.Config) + assert.Nil(t, result.Config) assert.Equal(t, "fallback - some_label", *result.Label) -} \ No newline at end of file +} From 0005e7b4a800d18d7180a91cc957ebb5ef51246d Mon Sep 17 00:00:00 2001 From: Nadia Mayor Date: Fri, 14 Nov 2025 17:25:08 -0300 Subject: [PATCH 3/3] Updated ci --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 007e3a8b..824a59a6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -35,7 +35,7 @@ jobs: - name: SonarQube Scan (Push) if: ${{ github.event_name == 'push' }} - uses: SonarSource/sonarcloud-github-action@v5.0.0 + uses: SonarSource/sonarqube-scan-action@v5.0.0 env: SONAR_TOKEN: ${{ secrets.SONARQUBE_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} @@ -46,7 +46,7 @@ jobs: - name: SonarQube Scan (Pull Request) if: ${{ github.event_name == 'pull_request' }} - uses: SonarSource/sonarcloud-github-action@v5.0.0 + uses: SonarSource/sonarqube-scan-action@v5.0.0 env: SONAR_TOKEN: ${{ secrets.SONARQUBE_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}