Documentation version: nextdevelopment documentation
Skip to content

Prepare for Gesso 2.0

Gesso 2.0 will change the Composer package and PHP namespace so the technical identity matches the project name. The final v1 minor provides a staged path: move PHP imports first on v1.10, then change packages and the remaining integration surfaces when v2 is available.

Stage 1: move PHP imports on v1.10

Upgrade the existing package to v1.10 before changing namespaces:

bash
composer require --dev studio-design/openapi-contract-testing:^1.10

Then replace the public namespace prefix in application and test code:

diff
-use Studio\OpenApiContractTesting\OpenApiResponseValidator;
+use Studio\Gesso\OpenApiResponseValidator;

v1.10 lazily aliases every non-@internal public type from Studio\Gesso\... to its v1 declaration. Classes, interfaces, traits, enums, and attributes are covered. The allowlist is checked against the public API inventory so a newly added public v1 type cannot silently miss its migration alias.

Run the complete test suite after replacing imports. This stage isolates source changes from the later Composer and integration changes.

Move scripts and CI to the unified command while still on v1.10:

diff
-vendor/bin/openapi-contract doctor --spec=openapi.json
+vendor/bin/gesso doctor --spec=openapi.json

-vendor/bin/openapi-coverage-merge --spec-base-path=tests/fixtures/specs
+vendor/bin/gesso coverage:merge --spec-base-path=tests/fixtures/specs

V1.10 supports both forms with the same command options and exit-code semantics. Migrating here avoids combining CLI changes with the later Composer package replacement.

What the v1 aliases do not change

The aliases cover PHP type references only. On v1.10, continue using the v1:

  • Composer package studio-design/openapi-contract-testing;
  • legacy commands openapi-contract and openapi-coverage-merge (the forward gesso command is also available);
  • Laravel configuration key and file openapi-contract-testing;
  • Laravel service provider discovery and PHPUnit extension configuration;
  • machine-readable tool identity and supported wire-format versions.

The declared v1 type remains canonical at runtime. Consequently, get_class(), reflection, and newly serialized objects still contain Studio\OpenApiContractTesting\... on v1.10. Do not rewrite persisted class names or snapshots during this stage.

Internal types are intentionally not aliased. Code using an @internal type must migrate away from that unsupported dependency rather than replace its namespace.

Stage 2: install v2

After studio-design/gesso v2 is published, replace the root Composer requirement instead of treating the package as an in-place update.

To test a published beta, explicitly opt in to beta stability for this package:

bash
composer remove --dev studio-design/openapi-contract-testing --no-update
composer require --dev "studio-design/gesso:^2.0@beta"

After v2.0.0 stable is published, use the normal stable constraint:

bash
composer remove --dev studio-design/openapi-contract-testing --no-update
composer require --dev "studio-design/gesso:^2.0"

The --no-update step edits only the root requirement; the following composer require resolves and installs the complete package switch. Do not run them in separate deployed revisions. Commit the resulting composer.json and composer.lock changes together with the namespace and integration changes described below. Composer does not select beta versions under its default stable policy unless the requirement opts in with a stability flag such as @beta.

Before switching packages, upgrade the test environment to PHP 8.3 or later. Gesso v2 requires PHP ^8.3 and supports PHPUnit ^12.0 || ^13.0; it no longer supports PHP 8.2 or PHPUnit 11. The supported combinations are PHPUnit 12 on PHP 8.3, 8.4, or 8.5 and PHPUnit 13 on PHP 8.4 or 8.5. Pest consumers must use Pest 4 with PHPUnit 12. These requirements are independent of the namespace rename, but resolving them before the package switch keeps dependency failures separate from source and configuration migration failures.

Inject the response observation tracker

Direct construction of OpenApiResponseValidator requires a StrictRequiredTracker as the first argument in v2. Create one instance for a test run and reuse it across validators:

diff
-$validator = new OpenApiResponseValidator(maxErrors: 20);
+$tracker = new StrictRequiredTracker();
+$validator = new OpenApiResponseValidator($tracker, maxErrors: 20);

Laravel, Symfony, and PSR-7 adapters resolve and inject the run-level tracker automatically. This change removes the direct validator's service-locator fallback; maxErrors and skipResponseCodes remain optional named arguments.

Migrate Laravel configuration before changing packages

Laravel applications must rename the published configuration file while v1.10 is still installed, then change the package without booting the application in between:

bash
php artisan config:clear
mv config/openapi-contract-testing.php config/gesso.php

Update any direct lookups in application or test code:

diff
-config('openapi-contract-testing.default_spec')
+config('gesso.default_spec')

Then replace the Composer requirement and boot the application on v2. Once the application starts successfully, rebuild the configuration cache if the deployment uses one:

bash
php artisan config:cache

Do not publish the v2 configuration with --force over the renamed file; the rename preserves project-specific values. V2 uses only the gesso key, the gesso publish tag, and config/gesso.php. If it detects the legacy top-level key (including in a stale configuration cache), its service provider stops with an actionable migration error. It deliberately does not guess precedence when both keys exist or silently accept the old key.

V2 declares Studio\Gesso\ as its only product namespace and does not provide a reverse Studio\OpenApiContractTesting\ shim. It also exposes only the unified gesso binary; the two legacy standalone binaries are removed. Complete Stage 1 before the package switch.

Update the PHPUnit extension FQCN

In the same change that replaces the Composer package, update the extension class in phpunit.xml or phpunit.xml.dist:

diff
 <extensions>
-    <bootstrap class="Studio\OpenApiContractTesting\PHPUnit\OpenApiCoverageExtension">
+    <bootstrap class="Studio\Gesso\PHPUnit\OpenApiCoverageExtension">
         <parameter name="spec_base_path" value="tests/fixtures/specs"/>
         <!-- keep the rest of the existing parameters unchanged -->
     </bootstrap>
 </extensions>

Do not register both FQCNs. Gesso v2 does not contain the legacy namespace, and the extension short name, XML structure, parameter names, defaults, accepted values, path handling, and environment variables are unchanged. PHPUnit's --migrate-configuration command migrates PHPUnit's configuration schema, not this package-owned class name, so make this replacement explicitly.

Update coverage JSON consumers

Gesso v2 coverage JSON uses schema_version: 2 and identifies the writer as studio-design/gesso:

json
{
  "schema_version": 2,
  "tool": {
    "name": "studio-design/gesso",
    "version": "2.0.0"
  }
}

Update validators, routing rules, snapshots, and dashboards that require schema_version: 1 or compare tool.name with the old package. The remaining coverage fields and meanings stay compatible with schema version 1; the version bump makes the documented fixed identity change visible instead of silently passing it through existing consumers.

Laravel route parity JSON also advances to schema_version: 2 because it adds the external_operations result and summary count. Doctor JSON remains at schemaVersion: 1, and the sidecar envelope and tracker-state versions remain unchanged. Gesso v2's merge reader continues to accept the older sidecar payloads documented in the versioning policy, so a branding-only migration does not make supported worker data unreadable.

Update branded diagnostic log rules

Gesso v2 changes the two branded diagnostic prefixes from [openapi-contract-testing] to [Gesso]. Update log routing or assertions for:

  • the warning emitted when the optional fakerphp/faker package is missing;
  • the Laravel contradictory-intent deprecation written to stderr.

Feature-oriented categories such as [OpenAPI Coverage], [OpenAPI Doctor], [OpenAPI Enum Drift], [OpenAPI Strict Required], and [OpenAPI Strict Required per-call] do not change. Keep existing rules for those categories. V2 emits only the Gesso-branded form rather than duplicating each warning under both names.

Reload persisted resolved specifications

The eager resolver's internal discriminator provenance extension changes from x-studio-openapi-contract-testing-implicit-schema-name to x-studio-gesso-implicit-schema-name. If a tool persists the array returned by the spec loader, discard that derived data and reload the original OpenAPI Description after installing v2.

Do not rename the field in persisted resolved arrays. The resolver removes both marker names from authored input to prevent a specification extension from spoofing an implicit discriminator mapping, and it creates the Gesso marker only after successfully resolving a direct local component-schema reference. There is intentionally no legacy-marker read path or configuration switch. Validation behavior for genuine implicit discriminator mappings is otherwise unchanged.

See ADR 0001 for the complete identity decision and the namespace compatibility spike for the tested behavior and identity limits of class_alias().