From 51055a08668c9fb38de9405de4e47ecce5d68cab Mon Sep 17 00:00:00 2001 From: Harris Effron Date: Wed, 15 Jul 2026 11:11:43 -0400 Subject: [PATCH 1/2] feat: stop tracking applied migration versions in the schema file Comparison-only variant answering: what if v2 is deleting the record instead of reshaping it? The schema file becomes body-only. schema load marks every migration on disk as applied when bootstrapping a server, trusting that the body reflects disk (the CLI always writes them together). Gains: the merge-conflict hotspot is deleted rather than scattered; no format break (1.x reads a scalar-less schema fine, so no flag day, no guards, no schema upgrade command); the first 2.0 write drops the scalar organically. Gives up: the load-time unrecorded-migrations warning (body/disk drift becomes undetectable) and the bootstrap self-heal (a pending migration is stamped applied on fresh servers instead of being left for migrate). Co-Authored-By: Claude Fable 5 --- fakeserver/server_test.go | 2 -- migrationmanagers/migrationmanagers.go | 16 +--------------- schema/schema.go | 3 --- schemaloaders/schemaloaders.go | 7 +++---- serializers/serializers.go | 1 - 5 files changed, 4 insertions(+), 25 deletions(-) diff --git a/fakeserver/server_test.go b/fakeserver/server_test.go index a0a554a..07862a7 100644 --- a/fakeserver/server_test.go +++ b/fakeserver/server_test.go @@ -21,7 +21,6 @@ import ( var testSchema = ` serializer_version: 1 -schema_version: "2020011774023" splits: - name: test.test_experiment weights: @@ -35,7 +34,6 @@ splits: var otherTestSchema = `{ "serializer_version": 1, - "schema_version": "2020011774023", "splits": [ { "name": "test.json_experiment", diff --git a/migrationmanagers/migrationmanagers.go b/migrationmanagers/migrationmanagers.go index 2d43455..e2c752c 100644 --- a/migrationmanagers/migrationmanagers.go +++ b/migrationmanagers/migrationmanagers.go @@ -88,16 +88,7 @@ func (m *MigrationManager) ApplyToSchema(migrationRepo migrations.Repository, id return err } - err = m.migration.ApplyToSchema(m.schema, migrationRepo, idempotently) - if err != nil { - return err - } - - appliedVersion := m.migration.MigrationVersion() - if appliedVersion != nil && m.schema.SchemaVersion < *appliedVersion { - m.schema.SchemaVersion = *appliedVersion - } - return nil + return m.migration.ApplyToSchema(m.schema, migrationRepo, idempotently) } // Sync applies the contents of a migration to the TestTrack server @@ -160,10 +151,5 @@ func (m *MigrationManager) SyncVersion() error { return fmt.Errorf("got %d status code", resp.StatusCode) } - appliedVersion := m.migration.MigrationVersion() - if m.schema.SchemaVersion < *appliedVersion { - m.schema.SchemaVersion = *appliedVersion - } - return nil } diff --git a/schema/schema.go b/schema/schema.go index 9916da8..3992a0d 100644 --- a/schema/schema.go +++ b/schema/schema.go @@ -204,9 +204,6 @@ func applyAllMigrationsToSchema(schema *serializers.Schema) error { return err } } - if len(versions) != 0 { - schema.SchemaVersion = versions[len(versions)-1] - } return nil } diff --git a/schemaloaders/schemaloaders.go b/schemaloaders/schemaloaders.go index cbf5d22..c04d14f 100644 --- a/schemaloaders/schemaloaders.go +++ b/schemaloaders/schemaloaders.go @@ -71,11 +71,10 @@ func (s *SchemaLoader) Load() error { } } + // The schema body is assumed to reflect every migration on disk (the CLI + // always writes them together), so mark them all applied - this is what + // lets a freshly bootstrapped server skip replaying history. for _, version := range s.migrationRepo.SortedVersions() { - if version > s.schema.SchemaVersion { - fmt.Println("Schema load complete, but there are migrations newer than the schema file - run testtrack migrate to apply them.") - break - } err := migrationmanagers.NewWithServer((*s.migrationRepo)[version], s.server).SyncVersion() if err != nil { return err diff --git a/serializers/serializers.go b/serializers/serializers.go index 34f06ae..b98b06a 100644 --- a/serializers/serializers.go +++ b/serializers/serializers.go @@ -90,7 +90,6 @@ type SchemaSplit struct { // migration validation and bootstrapping of new ecosystems type Schema struct { SerializerVersion int `yaml:"serializer_version" json:"serializer_version"` - SchemaVersion string `yaml:"schema_version" json:"schema_version"` Splits []SchemaSplit `yaml:"splits,omitempty" json:"splits,omitempty"` IdentifierTypes []IdentifierType `yaml:"identifier_types,omitempty" json:"identifier_types,omitempty"` RemoteKills []RemoteKill `yaml:"remote_kills,omitempty" json:"remote_kills,omitempty"` From 049c158dca8903b3baf8f7079a0351c58bef98c4 Mon Sep 17 00:00:00 2001 From: Harris Effron Date: Wed, 15 Jul 2026 11:30:18 -0400 Subject: [PATCH 2/2] chore: bump CLI version to 1.10.0 schema.yml loses the schema_version field and schema load marks all disk migrations applied instead of skipping unrecorded ones, but old and new binaries interoperate with no coordination, so this ships as a minor. Co-Authored-By: Claude Fable 5 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 48d6742..aa310f9 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ SHELL = /bin/sh -VERSION=1.9.0 +VERSION=1.10.0 BUILD=`git rev-parse HEAD` LDFLAGS=-ldflags "-w -s \