From 27093ea42e1fe96bb99d84b62b68978d8e3156c2 Mon Sep 17 00:00:00 2001 From: Amolith Date: Wed, 5 Nov 2025 08:49:25 -0700 Subject: [PATCH] feat(config): migrate deprecated co_authored_by MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The old co_authored_by boolean is now deprecated in favor of trailer_style enum. When only the old setting is present, it silently migrates (true → co-authored-by, false → none). When trailer_style is set, co_authored_by is ignored. The deprecated field remains in the schema marked with deprecated: true so editors can warn users. Assisted-by: Claude Sonnet 4.5 via Crush --- internal/config/attribution_migration_test.go | 95 +++++++++++++++++++ internal/config/config.go | 11 +++ internal/config/load.go | 7 ++ schema.json | 5 + 4 files changed, 118 insertions(+) create mode 100644 internal/config/attribution_migration_test.go diff --git a/internal/config/attribution_migration_test.go b/internal/config/attribution_migration_test.go new file mode 100644 index 0000000000000000000000000000000000000000..6f54b170ad4e4eb815e7cf22793584cb2ba4c9e4 --- /dev/null +++ b/internal/config/attribution_migration_test.go @@ -0,0 +1,95 @@ +package config + +import ( + "io" + "strings" + "testing" + + "github.com/stretchr/testify/require" +) + +func TestAttributionMigration(t *testing.T) { + t.Parallel() + + tests := []struct { + name string + configJSON string + expectedTrailer TrailerStyle + expectedGenerate bool + }{ + { + name: "old setting co_authored_by=true migrates to co-authored-by", + configJSON: `{ + "options": { + "attribution": { + "co_authored_by": true, + "generated_with": false + } + } + }`, + expectedTrailer: TrailerStyleCoAuthoredBy, + expectedGenerate: false, + }, + { + name: "old setting co_authored_by=false migrates to none", + configJSON: `{ + "options": { + "attribution": { + "co_authored_by": false, + "generated_with": true + } + } + }`, + expectedTrailer: TrailerStyleNone, + expectedGenerate: true, + }, + { + name: "new setting takes precedence over old setting", + configJSON: `{ + "options": { + "attribution": { + "trailer_style": "assisted-by", + "co_authored_by": true, + "generated_with": false + } + } + }`, + expectedTrailer: TrailerStyleAssistedBy, + expectedGenerate: false, + }, + { + name: "default when neither setting present", + configJSON: `{ + "options": { + "attribution": { + "generated_with": true + } + } + }`, + expectedTrailer: TrailerStyleCoAuthoredBy, + expectedGenerate: true, + }, + { + name: "default when attribution is null", + configJSON: `{ + "options": {} + }`, + expectedTrailer: TrailerStyleCoAuthoredBy, + expectedGenerate: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + + cfg, err := loadFromReaders([]io.Reader{strings.NewReader(tt.configJSON)}) + require.NoError(t, err) + + cfg.setDefaults(t.TempDir(), "") + + require.Equal(t, tt.expectedTrailer, cfg.Options.Attribution.TrailerStyle) + require.Equal(t, tt.expectedGenerate, cfg.Options.Attribution.GeneratedWith) + }) + } +} diff --git a/internal/config/config.go b/internal/config/config.go index b88ff26c9d82c9b00f4cfaa0716ed7b6881233ef..9d49c554034a59a6f549660297d2c59e10536c8b 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -14,6 +14,7 @@ import ( "github.com/charmbracelet/catwalk/pkg/catwalk" "github.com/charmbracelet/crush/internal/csync" "github.com/charmbracelet/crush/internal/env" + "github.com/invopop/jsonschema" "github.com/tidwall/sjson" ) @@ -176,9 +177,19 @@ const ( type Attribution struct { TrailerStyle TrailerStyle `json:"trailer_style,omitempty" jsonschema:"description=Style of attribution trailer to add to commits,enum=none,enum=co-authored-by,enum=assisted-by,default=co-authored-by"` + CoAuthoredBy *bool `json:"co_authored_by,omitempty" jsonschema:"description=Deprecated: use trailer_style instead"` GeneratedWith bool `json:"generated_with,omitempty" jsonschema:"description=Add Generated with Crush line to commit messages and issues and PRs,default=true"` } +// JSONSchemaExtend marks the co_authored_by field as deprecated in the schema. +func (Attribution) JSONSchemaExtend(schema *jsonschema.Schema) { + if schema.Properties != nil { + if prop, ok := schema.Properties.Get("co_authored_by"); ok { + prop.Deprecated = true + } + } +} + type Options struct { ContextPaths []string `json:"context_paths,omitempty" jsonschema:"description=Paths to files containing context information for the AI,example=.cursorrules,example=CRUSH.md"` TUI *TUIOptions `json:"tui,omitempty" jsonschema:"description=Terminal user interface options"` diff --git a/internal/config/load.go b/internal/config/load.go index 80eb031218ceb52a36adaf258c3974f84a0b4db9..77c9377445acadbdeeb49b97996f9a45be0b6dc3 100644 --- a/internal/config/load.go +++ b/internal/config/load.go @@ -356,6 +356,13 @@ func (c *Config) setDefaults(workingDir, dataDir string) { TrailerStyle: TrailerStyleCoAuthoredBy, GeneratedWith: true, } + } else if c.Options.Attribution.TrailerStyle == "" { + // Migrate deprecated co_authored_by or apply default + if c.Options.Attribution.CoAuthoredBy != nil && !*c.Options.Attribution.CoAuthoredBy { + c.Options.Attribution.TrailerStyle = TrailerStyleNone + } else { + c.Options.Attribution.TrailerStyle = TrailerStyleCoAuthoredBy + } } } diff --git a/schema.json b/schema.json index 3a86224fe809816550e61c17b28ded9932656699..61b230aaaea72a4af9c0edab85021760f3d1c199 100644 --- a/schema.json +++ b/schema.json @@ -15,6 +15,11 @@ "description": "Style of attribution trailer to add to commits", "default": "co-authored-by" }, + "co_authored_by": { + "type": "boolean", + "description": "Deprecated: use trailer_style instead", + "deprecated": true + }, "generated_with": { "type": "boolean", "description": "Add Generated with Crush line to commit messages and issues and PRs",