Skip to content

feat(php): support omitting username/password from basic auth when configured in IR#14412

Merged
Swimburger merged 31 commits intomainfrom
devin/1774997779-basic-auth-optional-php-sdk
Apr 7, 2026
Merged

feat(php): support omitting username/password from basic auth when configured in IR#14412
Swimburger merged 31 commits intomainfrom
devin/1774997779-basic-auth-optional-php-sdk

Conversation

@Swimburger
Copy link
Copy Markdown
Member

@Swimburger Swimburger commented Mar 31, 2026

Description

Refs #14378

Split from #14378 (one PR per generator).

Adds conditional support for omitting username or password in basic auth for the PHP SDK generator. When usernameOmit or passwordOmit flags are set in the IR's BasicAuthScheme, the omitted field is completely removed from the generated SDK's constructor (not just made optional). Internally, the omitted field is treated as an empty string when encoding the Authorization header. Default behavior (both required) is preserved when no omit flags are set.

Changes Made

  • RootClientGenerator.tsgetParameterForAuthScheme(): Reads scheme.usernameOmit/scheme.passwordOmit directly (IR SDK v66 has typed fields). When a field is omitted, it is excluded from the returned ConstructorParameter[] entirely — the end user never sees it.
  • RootClientGenerator.tsresolveBasicAuthScheme() (new helper): Extracted helper that resolves a basic auth scheme into its null-check condition and a single credentialExpr string. Builds clean concatenation without redundant empty-string literals (e.g., $username . ":" not $username . ":" . ""). Returns undefined when both fields are omitted, allowing the caller to pre-filter skipped schemes via .map().filter().
  • RootClientGenerator.tsgetConstructorMethod(): Pre-filters basic auth schemes through resolveBasicAuthScheme(), then iterates only resolved schemes. Per-field condition logic: only non-omitted fields are null-checked.
  • EndpointSnippetGenerator.ts: Dynamic snippets exclude omitted fields from generated code examples. Uses as unknown as Record<string, unknown> cast (the @fern-api/dynamic-ir-sdk package lacks typed usernameOmit/passwordOmit fields).
  • WireTestGenerator.tsbuildAuthParamsForTest(): Now checks basicScheme.usernameOmit/passwordOmit before emitting auth params in wire test setUp(), so omitted fields are not passed to the generated SeedClient constructor. Uses test-username/test-password values to match WireMock mapping expectations from mock-utils.
  • Bug fix: Password @param docs now correctly reference password name instead of username (copy-paste bug in existing code, visible in both basic-auth and basic-auth-pw-omitted fixtures).
  • versions.yml: New 2.4.0 entry (irVersion: 66).
  • New basic-auth-pw-omitted test fixture with password: omit: true, wire-tests only (no default output folder). Orphaned root-level seed output cleaned via pnpm seed clean.
  • Wire tests enabled for basic-auth-pw-omitted: Added wire-tests output folder with enable-wire-tests: true in seed.yml. WireMock mappings assert Authorization: Basic dGVzdC11c2VybmFtZTo= (base64("test-username:")) at request time via equalTo matcher.
  • basic-auth wire-tests: WireMock mappings now include Authorization header equalTo matching (from merged shared mock-utils changes). Wire test username corrected from test-user to test-username.
  • test-definitions: Removed unnecessary ir-version: v61 constraint for PHP (already consumes v66); updated Go constraint from v61 to v63.

Testing

  • Seed snapshot generated for basic-auth-pw-omitted fixture — constructor has only $username, dynamic snippets omit password
  • Wire tests enabled for basic-auth-pw-omitted — WireMock mappings assert correct Authorization header at request time
  • Wire test setUp() correctly omits password param for pw-omitted fixture
  • Wire test username aligned with mock-utils (test-username, not test-user)
  • Existing basic-auth fixture regenerated — no regressions (docs fix + WireMock header matching + username fix)
  • Orphaned seed output cleaned (pnpm seed clean — removed root-level .fern/, .github/, src/, tests/ dirs)
  • pnpm run check (biome lint) passing locally
  • CI passing (compile, lint, biome, test, all 17 required seed-test-results)

⚠️ Human Review Checklist

  1. Wire test auth values must match mock-utils: buildAuthParamsForTest() uses test-username/test-password — these must match what mock-utils/index.ts uses to generate WireMock Authorization header equalTo matchers. A mismatch causes WireMock to reject requests at stub-matching time (404), failing wire tests.
  2. Dynamic snippets cast: EndpointSnippetGenerator.ts uses as unknown as Record<string, unknown> because @fern-api/dynamic-ir-sdk lacks typed omit fields. This is intentional but fragile — if IR field names change, the cast will silently produce incorrect behavior. Updating the dynamic IR SDK types is out of scope for this PR.
  3. resolveBasicAuthScheme() credential expression: Three branches — username-omitted produces ":" . $password, password-omitted produces $username . ":", both-present produces $username . ":" . $password. Both-omitted returns undefined and is filtered before the loop. Verify the string building is correct for each case.
  4. WireMock mapping values: basic-auth-pw-omitted asserts Basic dGVzdC11c2VybmFtZTo= (base64("test-username:")). basic-auth asserts Basic dGVzdC11c2VybmFtZTp0ZXN0LXBhc3N3b3Jk (base64("test-username:test-password")). Verify both base64 values.
  5. Go fixture ir-version: v63: The Go SDK uses IR v61 natively, so its seed fixture still needs an explicit ir-version: v63 to test the omit feature. PHP's constraint was removed since PHP already consumes IR v66.

Link to Devin session: https://app.devin.ai/sessions/0786b963284f4799acb409d5373cde0a
Requested by: @Swimburger


Open with Devin

…configured in IR

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
@devin-ai-integration
Copy link
Copy Markdown
Contributor

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment and CI monitoring

Copy link
Copy Markdown

@claude claude bot left a comment

Choose a reason for hiding this comment

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

Claude Code Review

This repository is configured for manual code reviews. Comment @claude review to trigger a review and subscribe this PR to future pushes, or @claude review once for a one-time review.

Tip: disable this comment in your organization's Code Review settings.

devin-ai-integration[bot]

This comment was marked as resolved.

…nstead of coarse eitherOmitted flag

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
devin-ai-integration[bot]

This comment was marked as resolved.

Swimburger and others added 3 commits April 1, 2026 16:20
…sword param docs)

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
… use empty string internally

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
…on-mandatory

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
devin-ai-integration[bot]

This comment was marked as resolved.

Swimburger and others added 4 commits April 2, 2026 17:34
…f when first scheme skipped

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
…log and code comment

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
@devin-ai-integration devin-ai-integration bot changed the title feat(php-sdk): support optional username/password in basic auth when configured in IR feat(php-sdk): support omitting username/password from basic auth when configured in IR Apr 3, 2026
Swimburger and others added 3 commits April 3, 2026 15:41
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
*/
public function __construct(
string $username,
string $password,
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

why is password still here?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Good catch. The password is still in the constructor because the seed test fixture for PHP uses ir-version: v61 in test-definitions/fern/apis/basic-auth-pw-omitted/generators.yml, but usernameOmit/passwordOmit were introduced in IR v63. The v63→v62 migration strips these fields (lines 139-147 of migrateFromV63ToV62.ts), so by the time the IR reaches the PHP generator at v61, passwordOmit is always undefined.

The generator code correctly checks for passwordOmit (line 371 in RootClientGenerator.ts), but it never sees true because the field was removed during IR downgrade.

Fix: Bump ir-version from v61 to v63 (or later) in the seed test's generators.yml for PHP. Same issue applies to Go which also uses ir-version: v61.

Should I go ahead and bump the IR version for the basic-auth-pw-omitted seed fixture?

Swimburger and others added 5 commits April 3, 2026 19:46
…visible to generator

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
…sion)

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
…nerator

The dynamic snippets generator was still including omitted fields in
constructor calls. Updated getConstructorBasicAuthArgs to check for
usernameOmit/passwordOmit flags and skip omitted fields.

Regenerated all 7 dynamic snippet files for basic-auth-pw-omitted.

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Copy link
Copy Markdown
Contributor

@devin-ai-integration devin-ai-integration bot left a comment

Choose a reason for hiding this comment

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

Devin Review found 1 new potential issue.

View 7 additional findings in Devin Review.

Open in Devin Review

Comment on lines +325 to +327
const authRecord = auth as unknown as Record<string, unknown>;
const usernameOmitted = authRecord.usernameOmit === true;
const passwordOmitted = authRecord.passwordOmit === true;
Copy link
Copy Markdown
Contributor

@devin-ai-integration devin-ai-integration bot Apr 3, 2026

Choose a reason for hiding this comment

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

🔴 Prohibited as unknown as X type assertion used instead of fixing the dynamic IR type

The code uses auth as unknown as Record<string, unknown> at line 325, which is explicitly prohibited by the repository's CLAUDE.md rules: "Never use as any or as unknown as X. These are escape hatches that bypass the type system entirely. If the types don't line up, fix the types." The underlying issue is that usernameOmit/passwordOmit are being smuggled through the dynamic IR's BasicAuth type (packages/ir-sdk/src/sdk/api/resources/dynamic/resources/auth/types/BasicAuth.ts) which only declares username and password fields. The DynamicSnippetsConverter.ts:736-749 adds these extra properties to the object, and they survive because JavaScript preserves extra properties through spread. But this is fragile — if the dynamic IR is ever serialized through its schema (packages/ir-sdk/src/sdk/serialization/resources/dynamic/resources/auth/types/BasicAuth.ts), which uses objectWithoutOptionalProperties with only username and password, the extra properties will be silently stripped and the omit logic will stop working. The proper fix is to add usernameOmit and passwordOmit to the dynamic IR's BasicAuth type definition.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This is the same issue that was already discussed in previous review cycles. The @fern-fern/ir-sdk published package (which PHP imports from) does NOT have typed usernameOmit/passwordOmit fields — only the internal @fern-api/ir-sdk package has them. The as unknown as Record<string, unknown> cast is necessary because updating the published IR SDK types is out of scope for this PR (per Niels's instruction to "fix the non-IR changes"). The fields exist at runtime when the IR version is >= v63, but the TypeScript types don't know about them.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Acknowledged — the proper fix is to add usernameOmit/passwordOmit to the dynamic IR's BasicAuth type definition. However, updating the dynamic IR type definition is an IR change, which is out of scope for this PR per maintainer instruction ("Fix the non-IR changes"). The cast is a deliberate workaround to avoid modifying the IR SDK types.

The DynamicSnippetsConverter now passes these fields through as extra properties on the dynamic IR data, and the dynamic snippets generators read them via cast. This is intentionally fragile — once the dynamic IR types are updated to include these fields (in a separate IR PR), these casts can be removed.

@Swimburger Swimburger changed the title feat(php-sdk): support omitting username/password from basic auth when configured in IR feat(php): support omitting username/password from basic auth when configured in IR Apr 3, 2026
Comment on lines +368 to +383
// usernameOmit/passwordOmit may exist in newer IR versions
const scheme = basicAuthScheme as unknown as Record<string, unknown>;
const usernameOmitted = scheme.usernameOmit === true;
const passwordOmitted = scheme.passwordOmit === true;
// Condition: only require non-omitted fields to be present
let condition: string;
if (!usernameOmitted && !passwordOmitted) {
condition = `$${usernameName} !== null && $${passwordName} !== null`;
} else if (usernameOmitted && !passwordOmitted) {
condition = `$${passwordName} !== null`;
} else if (!usernameOmitted && passwordOmitted) {
condition = `$${usernameName} !== null`;
} else {
// Both fields omitted — skip auth header entirely when auth is non-mandatory
continue;
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This code is fairly verbose / difficult to read. Can we extract this into a helper function to clear this up?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Done — extracted a resolveBasicAuthScheme() helper method that returns { condition, usernameExpr, passwordExpr } (or undefined if both fields are omitted). The inline loop now just destructures and uses the resolved values. Also eliminated the isFirstBlock boolean by pre-filtering with .map().filter() and using the array index directly (i === 0 ? "if" : "else if").

);
if (basicAuthSchemes.length > 0) {
const isAuthOptional = !this.context.ir.sdkConfig.isAuthMandatory;
let isFirstBlock = true;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Is there a better way to capture this intent? This dangling boolean checks are often a code smell.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Addressed — replaced isFirstBlock with pre-filtering the schemes via resolveBasicAuthScheme() (which returns undefined for both-omitted cases). The resulting array only contains valid schemes, so i === 0 cleanly determines if/else if without a separate tracking boolean.

Comment on lines +628 to +629
const usernameOmitted = schemeRecord.usernameOmit === true;
const passwordOmitted = schemeRecord.passwordOmit === true;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Is it not sufficient to just check that if (schemeRecord.usernameOmit) rather than an explicit assignment to === true?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Good call — changed to !!schemeRecord.usernameOmit / !!schemeRecord.passwordOmit throughout.

Comment on lines +326 to +327
const usernameOmitted = authRecord.usernameOmit === true;
const passwordOmitted = authRecord.passwordOmit === true;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Is it not sufficient to just check that if (authRecord.usernameOmit) rather than an explicit assignment to === true? The same is true for passwordOmit.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Done — changed to !!authRecord.usernameOmit / !!authRecord.passwordOmit.

…rsion constraint

- Extract resolveBasicAuthScheme() helper to reduce inline verbosity
- Replace isFirstBlock boolean with index-based control flow
- Simplify === true to !! for omit checks
- Remove ir-version: v63 from PHP seed config so passwordOmit survives in v66 IR

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Swimburger and others added 9 commits April 3, 2026 21:15
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
…iome lint

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
…as typed usernameOmit/passwordOmit

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
…to dynamic IR

The DynamicSnippetsConverter was constructing dynamic BasicAuth with only
username and password fields, dropping usernameOmit/passwordOmit from the
main IR's BasicAuthScheme. This caused dynamic snippets generators to
always include omitted auth fields (e.g. $password) since they couldn't
detect the omit flags in the dynamic IR data.

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
…tput

- RootClientGenerator: build clean credential expression (e.g. $username . ":" instead of $username . ":" . "")
- basic-auth-pw-omitted: SeedClient.php now has clean base64_encode($username . ":")
- basic-auth: fix copy-paste bug in @param docs ("username" -> "password")
- basic-auth: add WireMock Authorization header matching (from merged mock-utils changes)

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 7, 2026

SDK Generation Benchmark Results

Comparing PR branch against latest nightly baseline on main (2026-04-07T04:47:12Z).

Full benchmark table (click to expand)
Generator Spec main (generator) main (E2E) PR (generator) Delta
csharp-sdk square 129s 170s 125s -4s (-3.1%)
go-sdk square 281s 352s 298s +17s (+6.0%)
java-sdk square 324s 376s 338s +14s (+4.3%)
php-sdk square 127s 162s 129s +2s (+1.6%)
python-sdk square 164s 206s 166s +2s (+1.2%)
ruby-sdk-v2 square 151s 189s 152s +1s (+0.7%)
rust-sdk square 133s 131s 132s -1s (-0.8%)
swift-sdk square 142s 506s 139s -3s (-2.1%)
ts-sdk square 142s 174s 146s +4s (+2.8%)

main (generator): generator-only time via --skip-scripts (includes Docker image build, container startup, IR parsing, and code generation — this is the same Docker-based flow customers use via fern generate). main (E2E): full customer-observable time including build/test scripts (nightly baseline, informational). Delta is computed against generator-only baseline.
⚠️ = generation exited with a non-zero exit code (timing may not reflect a successful run).
Baseline from nightly runs on main (latest: 2026-04-07T04:47:12Z). Trigger benchmark-baseline to refresh.

@devin-ai-integration devin-ai-integration bot changed the title feat(php): support omitting username/password from basic auth when configured in IR feat(php-sdk): support omitting username/password from basic auth when configured in IR Apr 7, 2026
- Add wire-tests output folder with enable-wire-tests: true in seed.yml
- WireMock mappings assert Authorization: Basic dGVzdC11c2VybmFtZTo= (base64 of test-username:)
- Generated SeedClient.php has only username param, no password
- Wire test class validates basic auth header at request time via equalTo matcher

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Copy link
Copy Markdown
Contributor

@devin-ai-integration devin-ai-integration bot left a comment

Choose a reason for hiding this comment

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

Devin Review found 1 new potential issue.

🐛 1 issue in files not directly in the diff

🐛 WireTestGenerator unconditionally emits password for basic auth, ignoring passwordOmit/usernameOmit (generators/php/sdk/src/wire-tests/WireTestGenerator.ts:492-494)

The buildAuthParamsForTest method in WireTestGenerator.ts always pushes both username and password for basic auth schemes (lines 492-494), without checking the scheme's usernameOmit/passwordOmit fields. This PR adds basic-auth-pw-omitted to seed.yml with enable-wire-tests: true, so the wire test generator now runs for this fixture. The generated wire test (BasicAuthWireTest.php) passes password: 'test-password' to a SeedClient constructor that no longer accepts a password parameter (because passwordOmit is true), causing a PHP compilation/runtime error. The basic visitor callback receives FernIr.BasicAuthScheme which has usernameOmit and passwordOmit fields (packages/ir-sdk/src/sdk/api/resources/auth/types/BasicAuthScheme.ts:10,15), but the callback ignores its argument entirely.

View 13 additional findings in Devin Review.

Open in Devin Review

…buildAuthParamsForTest

- WireTestGenerator now checks basicScheme.usernameOmit/passwordOmit before
  emitting auth params in setUp()
- basic-auth-pw-omitted wire test no longer passes password to SeedClient
  constructor (which doesn't accept it)
- Fixes Devin Review finding: unconditional password emission for omitted fields

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
@devin-ai-integration
Copy link
Copy Markdown
Contributor

Re: Devin Review finding on WireTestGenerator.buildAuthParamsForTest — fixed in b29fcdd. The method now checks basicScheme.usernameOmit/passwordOmit before emitting auth params. The generated BasicAuthWireTest.php no longer passes password to the SeedClient constructor for the basic-auth-pw-omitted fixture.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 7, 2026

SDK Generation Benchmark Results

Comparing PR branch against latest nightly baseline on main (2026-04-07T04:47:12Z).

Full benchmark table (click to expand)
Generator Spec main (generator) main (E2E) PR (generator) Delta
csharp-sdk square 129s 170s 132s +3s (+2.3%)
go-sdk square 281s 352s 292s +11s (+3.9%)
java-sdk square 324s 376s 341s +17s (+5.2%)
php-sdk square 127s 162s 124s -3s (-2.4%)
python-sdk square 164s 206s 162s -2s (-1.2%)
ruby-sdk-v2 square 151s 189s 154s +3s (+2.0%)
rust-sdk square 133s 131s 131s -2s (-1.5%)
swift-sdk square 142s 506s 138s -4s (-2.8%)
ts-sdk square 142s 174s 139s -3s (-2.1%)

main (generator): generator-only time via --skip-scripts (includes Docker image build, container startup, IR parsing, and code generation — this is the same Docker-based flow customers use via fern generate). main (E2E): full customer-observable time including build/test scripts (nightly baseline, informational). Delta is computed against generator-only baseline.
⚠️ = generation exited with a non-zero exit code (timing may not reflect a successful run).
Baseline from nightly runs on main (latest: 2026-04-07T04:47:12Z). Trigger benchmark-baseline to refresh.

… (pnpm seed clean)

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 7, 2026

SDK Generation Benchmark Results

Comparing PR branch against latest nightly baseline on main (2026-04-07T04:47:12Z).

Full benchmark table (click to expand)
Generator Spec main (generator) main (E2E) PR (generator) Delta
csharp-sdk square 129s 170s 131s +2s (+1.6%)
go-sdk square 281s 352s 285s +4s (+1.4%)
java-sdk square 324s 376s 331s +7s (+2.2%)
php-sdk square 127s 162s 124s -3s (-2.4%)
python-sdk square 164s 206s 162s -2s (-1.2%)
ruby-sdk-v2 square 151s 189s 157s +6s (+4.0%)
rust-sdk square 133s 131s 127s -6s (-4.5%)
swift-sdk square 142s 506s 140s -2s (-1.4%)
ts-sdk square 142s 174s 139s -3s (-2.1%)

main (generator): generator-only time via --skip-scripts (includes Docker image build, container startup, IR parsing, and code generation — this is the same Docker-based flow customers use via fern generate). main (E2E): full customer-observable time including build/test scripts (nightly baseline, informational). Delta is computed against generator-only baseline.
⚠️ = generation exited with a non-zero exit code (timing may not reflect a successful run).
Baseline from nightly runs on main (latest: 2026-04-07T04:47:12Z). Trigger benchmark-baseline to refresh.

…mapping expectations

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 7, 2026

SDK Generation Benchmark Results

Comparing PR branch against latest nightly baseline on main (2026-04-07T04:47:12Z).

Full benchmark table (click to expand)
Generator Spec main (generator) main (E2E) PR (generator) Delta
csharp-sdk square 129s 170s 132s +3s (+2.3%)
go-sdk square 281s 352s 295s +14s (+5.0%)
java-sdk square 324s 376s 330s +6s (+1.9%)
php-sdk square 127s 162s 121s -6s (-4.7%)
python-sdk square 164s 206s 168s +4s (+2.4%)
ruby-sdk-v2 square 151s 189s 160s +9s (+6.0%)
rust-sdk square 133s 131s 138s +5s (+3.8%)
swift-sdk square 142s 506s 147s +5s (+3.5%)
ts-sdk square 142s 174s 142s +0s (+0.0%)

main (generator): generator-only time via --skip-scripts (includes Docker image build, container startup, IR parsing, and code generation — this is the same Docker-based flow customers use via fern generate). main (E2E): full customer-observable time including build/test scripts (nightly baseline, informational). Delta is computed against generator-only baseline.
⚠️ = generation exited with a non-zero exit code (timing may not reflect a successful run).
Baseline from nightly runs on main (latest: 2026-04-07T04:47:12Z). Trigger benchmark-baseline to refresh.

@Swimburger Swimburger changed the title feat(php-sdk): support omitting username/password from basic auth when configured in IR feat(php): support omitting username/password from basic auth when configured in IR Apr 7, 2026
@Swimburger Swimburger merged commit 29b315f into main Apr 7, 2026
102 of 103 checks passed
@Swimburger Swimburger deleted the devin/1774997779-basic-auth-optional-php-sdk branch April 7, 2026 21:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

3 participants