Skip to content

Commit c500bde

Browse files
committed
fix: remove backwards compatibility for old experiment array format
Remove custom UnmarshalJSON methods and the unmarshalExperimentsField helper that supported the deprecated array format for experiments in config.json. The old format (["exp1"]) now produces a parse error with a remediation hint to update to the object format ({"exp1": true}).
1 parent f0c8bc3 commit c500bde

5 files changed

Lines changed: 18 additions & 88 deletions

File tree

internal/config/experiments.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@ import (
2525
"github.com/slackapi/slack-cli/internal/slackerror"
2626
)
2727

28+
// experimentsFormatHint is a remediation hint for config files that use the
29+
// deprecated array format for experiments instead of the current object format.
30+
const experimentsFormatHint = `If the "experiments" field is an array (e.g. ["exp1"]), update it to an object (e.g. {"exp1": true})`
31+
2832
// LoadExperiments parses experiments from the command flags and configuration
2933
// files and stores the findings in Config
3034
func (c *Config) LoadExperiments(

internal/config/experiments_test.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,11 +49,11 @@ func Test_Config_WithExperimentOn(t *testing.T) {
4949
fmt.Sprintf("active system experiments: [%s]", validExperiment))
5050
})
5151

52-
t.Run("Correctly finds experiments from old array format in config.json", func(t *testing.T) {
52+
t.Run("Returns a parse error with remediation for old array format in config.json", func(t *testing.T) {
5353
// Setup
5454
ctx, fs, _, config, pathToConfigJSON, teardown := setup(t)
5555
defer teardown(t)
56-
_, mockPrintDebug := setupMockPrintDebug()
56+
mockOutput, mockPrintDebug := setupMockPrintDebug()
5757

5858
// Write old array format
5959
jsonContents := []byte(
@@ -66,7 +66,8 @@ func Test_Config_WithExperimentOn(t *testing.T) {
6666

6767
config.LoadExperiments(ctx, mockPrintDebug)
6868
experimentOn := config.WithExperimentOn(validExperiment)
69-
assert.Equal(t, true, experimentOn)
69+
assert.Equal(t, false, experimentOn)
70+
assert.Contains(t, mockOutput.String(), "failed to parse system-level config file")
7071
})
7172

7273
t.Run("Correctly returns false when experiments are not in config.json", func(t *testing.T) {

internal/config/experiments_unmarshal.go

Lines changed: 0 additions & 47 deletions
This file was deleted.

internal/config/project.go

Lines changed: 5 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -71,23 +71,6 @@ type ProjectConfig struct {
7171
os types.Os
7272
}
7373

74-
// UnmarshalJSON implements custom JSON unmarshaling for ProjectConfig to support
75-
// backwards compatibility with the old array format for experiments.
76-
func (c *ProjectConfig) UnmarshalJSON(data []byte) error {
77-
type Alias ProjectConfig
78-
aux := &struct {
79-
RawExperiments json.RawMessage `json:"experiments,omitempty"`
80-
*Alias
81-
}{
82-
Alias: (*Alias)(c),
83-
}
84-
if err := json.Unmarshal(data, aux); err != nil {
85-
return err
86-
}
87-
c.Experiments = unmarshalExperimentsField(aux.RawExperiments)
88-
return nil
89-
}
90-
9174
// NewProjectConfig read and writes to the project-level configuration file
9275
func NewProjectConfig(fs afero.Fs, os types.Os) *ProjectConfig {
9376
projectConfig := &ProjectConfig{
@@ -276,7 +259,11 @@ func ReadProjectConfigFile(ctx context.Context, fs afero.Fs, os types.Os) (Proje
276259
return projectConfig, slackerror.New(slackerror.ErrUnableToParseJSON).
277260
WithMessage("Failed to parse contents of project-level config file").
278261
WithRootCause(err).
279-
WithRemediation("Check that %s is valid JSON", style.HomePath(projectConfigFilePath))
262+
WithRemediation(
263+
"Check that %s is valid JSON. %s",
264+
style.HomePath(projectConfigFilePath),
265+
experimentsFormatHint,
266+
)
280267
}
281268
if projectConfig.Surveys == nil {
282269
projectConfig.Surveys = map[string]SurveyConfig{}

internal/config/system.go

Lines changed: 5 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -81,25 +81,6 @@ type SystemConfig struct {
8181
configFileLock sync.Mutex
8282
}
8383

84-
// UnmarshalJSON implements custom JSON unmarshaling for SystemConfig to support
85-
// backwards compatibility with the old array format for experiments.
86-
// Old format: "experiments": ["charm", "sandboxes"]
87-
// New format: "experiments": {"charm": true, "sandboxes": true}
88-
func (c *SystemConfig) UnmarshalJSON(data []byte) error {
89-
type Alias SystemConfig
90-
aux := &struct {
91-
RawExperiments json.RawMessage `json:"experiments,omitempty"`
92-
*Alias
93-
}{
94-
Alias: (*Alias)(c),
95-
}
96-
if err := json.Unmarshal(data, aux); err != nil {
97-
return err
98-
}
99-
c.Experiments = unmarshalExperimentsField(aux.RawExperiments)
100-
return nil
101-
}
102-
10384
// NewSystemConfig read and writes to the system-level configuration directory
10485
func NewSystemConfig(fs afero.Fs, os types.Os) *SystemConfig {
10586
systemConfig := &SystemConfig{
@@ -151,7 +132,11 @@ func (c *SystemConfig) UserConfig(ctx context.Context) (*SystemConfig, error) {
151132
return &config, slackerror.New(slackerror.ErrUnableToParseJSON).
152133
WithMessage("Failed to parse contents of system-level config file").
153134
WithRootCause(err).
154-
WithRemediation("Check that %s is valid JSON", style.HomePath(path))
135+
WithRemediation(
136+
"Check that %s is valid JSON. %s",
137+
style.HomePath(path),
138+
experimentsFormatHint,
139+
)
155140
}
156141

157142
if config.Surveys == nil {

0 commit comments

Comments
 (0)