Skip to content

Schema migration system for ZIO Schema 2#984

Closed
Godzilla675 wants to merge 12 commits intozio:mainfrom
Godzilla675:schema-migration-for-zio-schema-2-system-v3
Closed

Schema migration system for ZIO Schema 2#984
Godzilla675 wants to merge 12 commits intozio:mainfrom
Godzilla675:schema-migration-for-zio-schema-2-system-v3

Conversation

@Godzilla675
Copy link
Contributor

@Godzilla675 Godzilla675 commented Feb 5, 2026

Summary

  • Implement pure, serializable migration core for ZIO Schema 2 (DynamicMigration + MigrationAction + DynamicSchemaExpr schemas).
  • Add Schema.structural derivation for structural records/variants and structural bindings (Scala 3).
  • Add selector macros + builder syntax for optic-style paths (Scala 2/3).
  • Add build-time validation, DefaultValue resolution, correct transform context, and extended runtime path traversal.

Examples

Structural schema + addField

type PersonV1 = { def name: String }
@schema case class PersonV2(name: String, age: Int)

implicit val v1Schema: Schema[PersonV1] = Schema.structural[PersonV1]

val v1ToV2 =
  MigrationBuilder[PersonV1, PersonV2]
    .addField(_.age, 0)
    .build

Rename + composition

@schema case class PersonV3(fullName: String, age: Int)

val v2ToV3 =
  MigrationBuilder[PersonV2, PersonV3]
    .renameField(_.name, _.fullName)
    .buildPartial

val v1ToV3 = v1ToV2 ++ v2ToV3

Selector grammar (paths)

MigrationBuilder[Old, New]
.dropField(.address.street)
.optionalizeField(
.email)
.buildPartial

Notable behavior

  • build() validates structural changes (including optionality) by simulating actions.
  • DefaultValue resolves at build time (forward strict; reverse best-effort).
  • Typed Migration.apply returns a MigrationError for structural-only schemas; use applyDynamic.

Tests

  • sbt -no-colors schemaJVM/test schemaJS/test

Notes / limitations

  • Scala 2 cannot derive Schema.structural for true structural/union types.
  • Typed apply for structural schemas is intentionally unsupported (use applyDynamic).

Review guide

  • Serialization schemas: schema/shared/src/main/scala/zio/blocks/schema/migration/MigrationSchemas.scala
  • Structural derivation: schema/shared/src/main/scala-3/zio/blocks/schema/SchemaCompanionVersionSpecific.scala (+ bindings)
  • Selector macros + syntax: schema/shared/src/main/scala-2|3/zio/blocks/schema/migration/*
  • Validation: schema/shared/src/main/scala/zio/blocks/schema/migration/MigrationValidator.scala
  • Tests: schema/shared/src/test/scala/zio/blocks/schema/migration/*

Issues

Copilot AI review requested due to automatic review settings February 5, 2026 16:24
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR implements a comprehensive pure, algebraic schema migration system for ZIO Schema 2, enabling type-safe transformations between schema versions as first-class, serializable data.

Changes:

  • Introduces core migration types (Migration, DynamicMigration, MigrationAction, DynamicSchemaExpr) with full serialization support
  • Adds MigrationBuilder with fluent API, default value resolution, and structural validation
  • Implements selector macros for type-safe optic-style paths in both Scala 2 and 3
  • Adds Schema.structural derivation for compile-time-only structural types (Scala 3)
  • Provides comprehensive test coverage with 1000+ tests across multiple spec files

Reviewed changes

Copilot reviewed 38 out of 38 changed files in this pull request and generated no comments.

Show a summary per file
File Description
DynamicMigration.scala Core untyped migration engine operating on DynamicValue with path-based action application
Migration.scala Typed migration wrapper with schemas, providing type-safe apply/compose/reverse operations
MigrationAction.scala ADT of migration actions (AddField, RenameField, etc.) with structural reverse operations
DynamicSchemaExpr.scala Serializable expression DSL for value transformations (arithmetic, logic, coercion)
MigrationBuilder.scala Fluent builder API with build-time default value resolution and validation hooks
MigrationValidator.scala Structural validation engine simulating actions on schema structures
MigrationError.scala Path-aware error types for diagnostics
SelectorMacros.scala (2/3) Compile-time conversion of lambda selectors to DynamicOptic paths
MigrationBuilderSyntax.scala (2/3) Extension methods for type-safe selector syntax
SchemaCompanionVersionSpecific.scala Adds Schema.structural derivation for refinement/union types (Scala 3 only)
Various binding classes Adds StructuralMatcher/Constructor/Deconstructor for compile-time-only types
Test files Comprehensive test coverage for all migration operations and edge cases
migration.md Complete documentation with examples and best practices

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@Godzilla675 Godzilla675 marked this pull request as draft February 5, 2026 17:31
…structure comparison

- Add validatePath/validatePathRecursive to check Wrap path segments match schema structure
- Validate Elements only on sequences, MapKeys/MapValues only on maps, Case only on variants
- Add lenient structure comparison mode when structural migration actions are present
- Handle Split/Join/Mandate/Optionalize by relaxing field presence checks
- Preserve optionality checking for Dynamic fields even in lenient mode
- Fix error message format for optionality and structure mismatches

Fixes 13 failing MigrationValidatorSpec tests and 1 MigrationValidatorOptionalitySpec test.
@Godzilla675 Godzilla675 marked this pull request as ready for review February 6, 2026 02:22
@Godzilla675 Godzilla675 marked this pull request as draft February 6, 2026 02:29
@jdegoes jdegoes closed this Feb 6, 2026
@Godzilla675
Copy link
Contributor Author

@jdegoes why did you close the pr? at least give feedback I am still working on it.
i do not have enough memory on my machine to run the tests that's why I am pushing the changes , to see them in the ci.
this was 4 weeks worth of work.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants