Skip to content

Support Guzzle 8: regenerate with fern-php-sdk 2.x #407

Description

@crocodele

intercom/intercom-php requires guzzlehttp/guzzle: ^7.4, which blocks projects from upgrading to Guzzle 8 (released August 2026). Widening the constraint isn't enough on its own: the generated code relies on Guzzle 7 behavior that changed in Guzzle 8 (e.g. RequestException::getResponse() no longer exists; network errors that aren't connect failures are no longer ConnectException, so the retry middleware would stop retrying them).

fernapi/fern-php-sdk 2.0.0+ generates PSR-18-agnostic code (fern-api/fern#12151): Guzzle becomes a dev dependency only, and any PSR-18 client works through php-http/discovery. That removes the Guzzle constraint entirely. The change would be bumping php-sdk in Intercom-OpenAPI fern/generators.yml from 1.25.0 to 2.x.

Proof of concept: crocodele/intercom-php@fern-php-sdk-2x (a PR isn't possible since PRs are limited to collaborators).

How this was generated

  • Spec: intercom/Intercom-OpenAPI@184e88b754, the spec behind the last regeneration (🌿 Fern Regeneration -- January 30, 2026 #397), so the diff reflects only the generator change.
  • fern CLI 5.138.1 + fernapi/fern-php-sdk 2.23.0 (2.x needs CLI ≥ 5.44.6).
  • Sanity check: CLI 3.0.2 + 1.25.0 on the same spec reproduces current master (apart from version headers).
  • composer.json (in .fernignore) updated by hand:
    • Generated requirements: psr/http-client(-implementation), psr/http-factory(-implementation), php-http/discovery, php-http/multipart-stream-builder.
    • Kept for src/Legacy: php-http/client-common, php-http/message, nyholm/psr7.
    • guzzlehttp/guzzle moved to require-dev as ^7.4 || ^8.0.
  • README.md kept from master, because local generation doesn't produce the Legacy SDK section.

Known generator bug (worked around here)

2.x generates createMessage(mixed|null $request = null, ...) in Unstable\Messages\MessagesClient. PHP 8.0+ rejects that, so the class fatals on load. The second commit on the branch hand-fixes it to mixed. The upstream fix is fern-api/fern#17893; once released, regenerating won't need this commit.

Verification

  • composer test: 95 tests, 341 assertions, passing with Guzzle 8.2.0 (psr7 3.1, promises 3.0) and Guzzle 7.15.5.
  • All 1,083 classes under src/ load.
  • Smoke test with a Guzzle MockHandler, on both Guzzle 7 and 8:
    • Endpoint call deserializes correctly.
    • 404 → IntercomApiException.
    • Network error → IntercomException.
    • 503 is retried.
    • Default client discovery works.
    • The Legacy client works.
  • composer analyze (phpstan): the only errors are in test files. 3 exist on master already; 2 come from the generated RawClientTest.

Breaking changes for SDK users (would warrant 6.0)

  • Guzzle isn't installed automatically anymore, and a custom client option must be a PSR-18 client.
  • Core\Client\RetryMiddleware is removed; retries now use RetryDecoratingClient.
  • Per-request timeout only works with Guzzle or Symfony HttpClient.
  • JSON-returning endpoint methods now return nullable types (T → ?T, 247 methods); an empty response body returns null instead of throwing (fix(php): Return null for empty JSON responses instead of throwing fern-api/fern#14027).
  • Some request/type classes were renamed by the newer CLI, e.g. ReplyConversationRequest → ReplyConversationBody, UpdateArticleRequestState → UpdateArticleRequestBodyState.

🤖 Generated with Claude Code

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions