Skip to content

ci: reduce test overhead and unshard to conserve runners and reduce flakes - #686

Merged
apcha-oai merged 2 commits into
mainfrom
apcha/ruby-ci-test-performance
Sep 8, 2026
Merged

ci: reduce test overhead and unshard to conserve runners and reduce flakes#686
apcha-oai merged 2 commits into
mainfrom
apcha/ruby-ci-test-performance

Conversation

@apcha-oai

@apcha-oai apcha-oai commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

Ruby CI repeatedly copied and loaded the full RBS signature tree for ten tiny consumer checks, and a mock-process startup race could add a 60-second wait. This change batches the compatibility fixtures, fixes the mock handshake, and returns the Ruby matrix to one shard per version for simplicity and fewer opportunities for flakes from repeated job setup.

Why return to one shard

Unsharding is intentional. Three-way sharding brought elapsed CI time back toward baseline, but multiplied the Ruby matrix from three jobs to nine. That consumes more runners and creates more opportunities for flakes through additional dependency installation, mock startup, and cleanup. We prefer to remove redundant test work and keep one complete-suite job per Ruby version; sharding should be a last resort if further test improvements cannot provide acceptable feedback time.

This is a deliberate tradeoff: individual unsharded jobs take longer than shards, while CI uses fewer runners and has fewer independent setup/cleanup paths. The current sequential-RBI implementation completes public jobs in 3m59s–4m43s and internal jobs in 5m11s–5m35s. The original under-five-minute target is not met on the internal runners, and we intentionally retain one shard rather than restore nine jobs to meet it.

Changes

  • Check all ten positive/negative RBS consumers in one Steep invocation. Each stays a separate source file; exact negative diagnostics are checked with --with-expectations. Runtime and declaration assertions remain in their original suites.
  • Publish the waiting mock's PID from initialized Ruby and require the interrupted launcher to exit within five seconds.
  • Run one complete-suite shard for each supported Ruby (3.3, 3.4, 4.0). Keep the sharding helper and verify that the configured shard covers every test file exactly once.
  • Preserve Tapioca's canonical sequential RBI merge and add the mixed typed/untyped counterexample from review. Pairwise merging was withdrawn because the operation is not associative: a later typed declaration can hide an earlier method conflict when files are regrouped.

Rebased onto main 31bbd60de2775f90f46dcaddda8089d5e322bc5b. The upstream 15-minute timeout from #683 is unchanged; this PR changes the three-way sharding added in #684. No SDK runtime, signature, dependency, or generated-surface changes. Large-payload tests retain their original sizes and assertions.

Root cause and remaining cost

Internal Ruby 3.4 test execution grew from 2.9 seconds on July 15 (460 tests), to 31.1 seconds on August 14 (723 tests), to 498.4 seconds on September 8 (1,872 tests). Expanded coverage explains some growth; the measured overhead above identifies specific additional costs.

Validation

  • The review's four-file mixed typed/untyped regression fails against the pairwise helper (expected one conflict, got zero), then passes with sequential merging.
  • Both exported-RBI tests pass locally: 2 tests, 6 assertions, 50.8 seconds. Changed-file RuboCop, rubyfmt, and whitespace checks pass.
  • The one-shard workflow regression passes: 4 tests, 23 assertions.
  • Removing one expected negative diagnostic and introducing one error in a valid fixture makes the consolidated RBS check fail with exactly one missing and one unexpected diagnostic.
  • All required checks pass at c03d0ed004366b0e283581a74bacf9c7a75b6dbc in both repositories. Each complete-suite job ran 1,868 tests with no failures, errors, or skips. Earlier 2m39s–4m04s timings used the withdrawn pairwise optimization and do not describe this revision.

Current hosted validation

Whole-job times include setup and cleanup; every row uses one shard.

Repository Ruby Whole job Test execution
Internal 3.3 5m35s 312.8s
Internal 3.4 5m34s 309.3s
Internal 4.0 5m11s 289.9s
Public 3.3 3m59s 215.9s
Public 3.4 4m43s 260.6s
Public 4.0 4m29s 244.1s

Runs: internal, public.

Measurement sources

SDK-team review is requested. Measurements use each repository's normal runner selection and are reported separately because observed runtimes differ.

Linked counterpart: https://github.com/openai/openai-ruby-internal/pull/97

@apcha-oai
apcha-oai requested a review from a team September 8, 2026 16:41
@github-actions

github-actions Bot commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

Castiron custom code

✅ No new custom-code files detected.

50 mixed files remain; 0 existing customizations changed.

Compared 31bbd60de277c03d0ed00436. Generated baselines verified.

50 existing customizations unchanged
  • lib/openai.rb
  • lib/openai/client.rb
  • lib/openai/models/audio/transcription_create_response.rb
  • lib/openai/models/chat/chat_completion_message.rb
  • lib/openai/models/chat/chat_completion_message_function_tool_call.rb
  • lib/openai/models/chat/completion_create_params.rb
  • lib/openai/models/response_format_json_schema.rb
  • lib/openai/models/responses/function_tool.rb
  • lib/openai/models/responses/response.rb
  • lib/openai/models/responses/response_create_params.rb
  • lib/openai/models/responses/response_format_text_config.rb
  • lib/openai/models/responses/response_format_text_json_schema_config.rb
  • lib/openai/models/responses/response_function_tool_call.rb
  • lib/openai/models/responses/response_function_web_search.rb
  • lib/openai/models/responses/response_output_text.rb
  • lib/openai/models/responses/tool.rb
  • lib/openai/resources/beta/threads.rb
  • lib/openai/resources/chat/completions.rb
  • lib/openai/resources/containers/files.rb
  • lib/openai/resources/files.rb
  • lib/openai/resources/responses.rb
  • lib/openai/resources/vector_stores/file_batches.rb
  • lib/openai/resources/vector_stores/files.rb
  • lib/openai/resources/webhooks.rb
  • rbi/openai/client.rbi
  • rbi/openai/models/chat/chat_completion_message.rbi
  • rbi/openai/models/chat/chat_completion_message_function_tool_call.rbi
  • rbi/openai/models/chat/completion_create_params.rbi
  • rbi/openai/models/response_format_json_schema.rbi
  • rbi/openai/models/responses/response.rbi
  • rbi/openai/models/responses/response_create_params.rbi
  • rbi/openai/models/responses/response_function_tool_call.rbi
  • rbi/openai/models/responses/response_function_web_search.rbi
  • rbi/openai/models/responses/response_output_text.rbi
  • rbi/openai/resources/chat/completions.rbi
  • rbi/openai/resources/files.rbi
  • rbi/openai/resources/responses.rbi
  • rbi/openai/resources/vector_stores/file_batches.rbi
  • rbi/openai/resources/vector_stores/files.rbi
  • scripts/castiron/README.md

10 more in the full report.

A changed generated baseline means this report cannot reliably identify which handwritten lines changed.

Inspect the custom-code diff

Download the exact patch produced by this run (requires repository access):

gh run download 34255805262 --repo openai/openai-ruby \
  --name castiron-custom-code-34255805262-1 --dir /tmp/castiron-custom-code-34255805262-1
git apply --stat /tmp/castiron-custom-code-34255805262-1/custom-code.patch
cat /tmp/castiron-custom-code-34255805262-1/custom-code.patch

Or reproduce it from an SDK checkout containing the vendored reporter:

git fetch --no-tags origin 31bbd60de2775f90f46dcaddda8089d5e322bc5b c03d0ed004366b0e283581a74bacf9c7a75b6dbc
python3 scripts/castiron/custom_code_report.py report \
  --base 31bbd60de2775f90f46dcaddda8089d5e322bc5b \
  --head c03d0ed004366b0e283581a74bacf9c7a75b6dbc --fetch --require-head-hash --public \
  --out /tmp/castiron-custom-code-c03d0ed00436
cat /tmp/castiron-custom-code-c03d0ed00436/custom-code.patch

This is the current full custom patch for mixed files, not an attribution of only the handwritten lines changed by this PR.

Full report and patch

@apcha-oai
apcha-oai marked this pull request as ready for review September 8, 2026 16:49
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 8, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-09-08T17:10:21.254002Z c03d0ed New commits
🔒 Security Review Completed 2026-09-08T17:09:10.226016Z c03d0ed New commits
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@openai-sdks

openai-sdks Bot commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

OkTest Summary

236/236 SDK tests passed in 9.35s for Ruby SDK PR #686.

Test results — 42 files
Test Result Time
tests/chat-completions-complex-body.test.ts ✅ Passed 223ms
tests/chat-completions-create.test.ts ✅ Passed 240ms
tests/chat-completions-stream.test.ts ✅ Passed 132ms
tests/files-content-binary.test.ts ✅ Passed 161ms
tests/files-create-multipart.test.ts ✅ Passed 167ms
tests/files-list-pagination.test.ts ✅ Passed 165ms
tests/initialize-config.test.ts ✅ Passed 102ms
tests/instance-isolation.test.ts ✅ Passed 179ms
tests/models-list.test.ts ✅ Passed 179ms
tests/responses-background-lifecycle.test.ts ✅ Passed 155ms
tests/responses-body-method-errors.test.ts ✅ Passed 566ms
tests/responses-cancel-timeout.test.ts ✅ Passed 318ms
tests/responses-cancel.test.ts ✅ Passed 225ms
tests/responses-compact-retries.test.ts ✅ Passed 229ms
tests/responses-compact.test.ts ✅ Passed 205ms
tests/responses-create-advanced-stream.test.ts ✅ Passed 162ms
tests/responses-create-advanced.test.ts ✅ Passed 164ms
tests/responses-create-disconnect.test.ts ✅ Passed 140ms
tests/responses-create-errors.test.ts ✅ Passed 308ms
tests/responses-create-malformed-api-responses.test.ts ✅ Passed 158ms
tests/responses-create-retries.test.ts ✅ Passed 164ms
tests/responses-create-stream-failures.test.ts ✅ Passed 118ms
tests/responses-create-stream-timeout.test.ts ✅ Passed 206ms
tests/responses-create-stream-wire.test.ts ✅ Passed 1.963s
tests/responses-create-stream.test.ts ✅ Passed 258ms
tests/responses-create-terminal-states.test.ts ✅ Passed 302ms
tests/responses-create-timeout.test.ts ✅ Passed 333ms
tests/responses-create.test.ts ✅ Passed 175ms
tests/responses-delete.test.ts ✅ Passed 208ms
tests/responses-input-items-errors.test.ts ✅ Passed 204ms
tests/responses-input-items-list.test.ts ✅ Passed 170ms
tests/responses-input-items-options.test.ts ✅ Passed 117ms
tests/responses-input-tokens-count-timeout.test.ts ✅ Passed 307ms
tests/responses-input-tokens-count.test.ts ✅ Passed 231ms
tests/responses-malformed-inputs.test.ts ✅ Passed 2.131s
tests/responses-not-found-errors.test.ts ✅ Passed 476ms
tests/responses-parse.test.ts ✅ Passed 191ms
tests/responses-retrieve-retries.test.ts ✅ Passed 236ms
tests/responses-retrieve.test.ts ✅ Passed 179ms
tests/responses-stored-method-errors.test.ts ✅ Passed 933ms
tests/retry-behavior.test.ts ✅ Passed 3.102s
tests/sdk-error-shape.test.ts ✅ Passed 507ms

View OkTest run #34255092493

SDK merge (9c435556760d) · head (c03d0ed00436) · base (31bbd60de277) · OkTest (08ec4299e769)

@apcha-oai
apcha-oai force-pushed the apcha/ruby-ci-test-performance branch from 9db65bc to 95b780e Compare September 8, 2026 16:54
Comment thread .github/workflows/ci-checks.yml

@jbeckwith-oai jbeckwith-oai left a comment

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.

Reviewed the complete exact-head 23-file diff against the test-efficiency outcome and the stated non-goals. The consolidated RBS harness preserves the ten separate consumer files and exact negative diagnostics, the pairwise RBI merge retains within-pair, cross-pair, and odd-tail conflict coverage, and the initialized-Ruby PID publication closes the lost-TERM fixture race with a bounded launcher wait. git diff --check passes, no runtime/signature/dependency/generated-surface changes are present, and all completed exact-head lint/type/package/RBS/Bedrock/CodeQL/Castiron checks are green. One blocking scope/CI regression remains: this head undoes the just-merged three-way Ruby test matrix even though the PR description says job selection is unchanged and cites sharded validation from an older head. Restore the three-way matrix, or explicitly re-scope and revalidate the unsharding decision on the current head.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 95b780e12d

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread .github/workflows/ci-checks.yml
@apcha-oai apcha-oai changed the title ci: reduce redundant type-test setup and cleanup waits ci: reduce test overhead and use one shard per Ruby Sep 8, 2026
@apcha-oai
apcha-oai requested a review from a team September 8, 2026 16:58

@markstuart-oai markstuart-oai left a comment

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.

Reviewed all 23 changed files against main/base 31bbd60d, including the surrounding RBS/RBI and launcher contracts. One substantive issue remains: the balanced RBI merge is not equivalent to the original ordered merge and can silently lose a conflict (reproduction inline). Collecting every level's conflict metadata does not fix conflicts erased before that level is merged.

The RBS consolidation otherwise removes duplicated setup cleanly: all ten consumer sources remain separate, and an independent mutation produced exactly one missing and one unexpected diagnostic. Both original Client superclass regressions are still detected. No file crosses 1,000 lines, and no SDK runtime/signature/dependency/generated-surface changes are present.

Fresh local Ruby 4.0.6 validation: 23 focused tests / 115 assertions passed; the interrupt test passed (1 test / 3 assertions). The broader launcher run had one readiness-timeout assertion failure, so I am not claiming a clean full launcher suite or full-suite/older-Ruby/platform validation.

I also verified the three-to-one shard change. The author has now explicitly documented its rationale and separated current-head validation from historical timing evidence. The optimized consumer/RBI/launcher code matches 9db65bc; control da9304781 differs from that historical head only by workflow dispatch. Historical timings are not fresh measurements of this review.

Comment thread test/openai/exported_rbi_test.rb Outdated
while trees.size > 1
trees = trees.each_slice(2).map do |pair|
merger = RBI::Rewriters::Merge.new(keep: RBI::Rewriters::Merge::Keep::NONE)
pair.each { merger.merge(_1) }

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.

[P2] Preserve ordered merge conflict semantics

RBI::Rewriters::Merge is not associative, so preserving file order while changing the grouping can make this regression test pass for an export the original merge rejects. With locked RBI 0.4.3, parse these as four separate trees in order:

class A; def m(x); end; end
class A; def m(x); end; end
class A; def m(y); end; end
class A; sig {params(x: String).void}; def m(x); end; end

The previous single merger records Conflicting definitions for ::A#m(x) when it reaches tree 3; this helper returns []. In the second pair, merging the typed declaration into the untyped method replaces its parameters/signature, erasing the conflict before the two pairs meet. Saving intermediate conflict arrays cannot recover a conflict that was never emitted.

Please retain the canonical ordered merge semantics (the sequential merge is a safe fallback) and add this mixed typed/untyped regression before introducing an equivalent optimization. The superclass-only probe does not establish equivalence for method declarations.

@apcha-oai apcha-oai changed the title ci: reduce test overhead and use one shard per Ruby ci: reduce test overhead and unshard to conserve runners and reduce flakes Sep 8, 2026

@jbeckwith-oai jbeckwith-oai left a comment

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.

Follow-up exact-head review found one remaining in-scope documentation regression. This PR intentionally changes CI from three shards per Ruby to one complete-suite job, but CONTRIBUTING.md still states that CI partitions the suite into three groups and tells contributors to reproduce CI with TEST_SHARD=1/3, 2/3, or 3/3. That guidance was added by the base commit being reversed here, so it becomes false at this head. Please update the contributor documentation to describe the one-shard CI behavior while retaining the helper optional local sharding instructions if desired. The current title/body, sequential RBI fix, consolidated RBS fixtures, mock-handshake change, exact-head CI, and 23-file patch otherwise match the approved scope. Local focused execution was unavailable because this checkout lacks the locked bundle; exact-head required CI is green.

@jbeckwith-oai jbeckwith-oai left a comment

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.

Agent version of me, please don't request changes

@markstuart-oai markstuart-oai left a comment

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.

Follow-up to review 5144715509 and the explicitly requested re-review: the RBI finding is fixed. The exact four-file counterexample now runs through the same canonical sequential merger as the exported-tree check; the pairwise loop and intermediate-conflict bookkeeping are deleted. This restores the required semantics with a simpler implementation.

Reconciled all 23 changed files against main/base 31bbd60d; only the RBI test changed since my prior review. Fresh Ruby 4.0.6 checks passed: 7 tests / 32 assertions across exported RBI, consolidated RBS, and shard coverage. Independent probes also confirmed that the previous helper misses the exact counterexample, the current helper reports it, and restoring either Client superclass omission still produces a conflict. Inventory confirms all 251 non-Bedrock test files, including the unchanged large-payload suite, run in each configured 1/1 job. No file crosses 1,000 lines.

The intentional one-job-per-Ruby tradeoff and unchanged timeout are now explicit. Public run 34255090446 is successful at this head (3m59s–4m43s); I also checked its Ruby 4.0 log: 1,868 tests, zero failures/errors/skips. Withdrawn pairwise timings are not evidence for this revision.

Earlier diagnostic-mutation and interrupt checks remain applicable to unchanged code. I did not rerun the full local suite, older Ruby versions, or other platforms; the earlier broader-launcher readiness-timeout failure remains a validation limit. One minor contributor-documentation correction remains inline.

matrix:
ruby-version: ['3.3', '3.4', '4.0']
shard: [1, 2, 3]
shard: [1]

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.

[P3] Align contributor instructions with the intentional one-shard workflow

The one-shard tradeoff is now explicit and the configured inventory is complete, but CONTRIBUTING.md:152–156 still says CI partitions each Ruby suite into three groups and presents TEST_SHARD=1/3, 2/3, and 3/3 as reproducing CI. Please describe the complete-suite CI job there and label those commands as optional local sharding. The helper can remain available without documenting it as the current CI configuration.

@apcha-oai
apcha-oai added this pull request to the merge queue Sep 8, 2026
Merged via the queue into main with commit 107973f Sep 8, 2026
24 checks passed
@apcha-oai
apcha-oai deleted the apcha/ruby-ci-test-performance branch September 8, 2026 17:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants