Repository navigation
Conversation
The `module` validation pattern `^([A-Z][a-z0-9]+)+$` requires a lowercase letter or digit after every capital, so PascalCase names containing acronyms such as `MySDK` or `OpenAPI` fail gen.yaml validation even though the generator renders them correctly. Accept any name starting with an uppercase letter followed by letters or digits.
There was a problem hiding this comment.
All reported issues were addressed across 3 files
Shadow auto-approve: would not auto-approve because issues were found.
View guided diff | Turn on auto-fix | Re-trigger cubic
There was a problem hiding this comment.
0 issues found across 1 file (changes from recent commits).
Confidence score: 5/5
- Automated review surfaced no issues in the provided summaries.
- No files require special attention.
Shadow auto-approve: would not auto-approve. Auto-approval blocked by 1 unresolved issue from previous reviews.
View guided diff | Turn on auto-fix | Re-trigger cubic
Generator Snapshot Testing
Snapshot results: https://github.com/speakeasy-api/openapi-generation-snapshots/issues/137#issuecomment-6427253168 Snapshot results are summarized above. Additional run context is linked for maintainers with access. |
Every target's gen.yaml config fields may declare a ValidationRegex in config.ts. The patterns are authored as JavaScript regular expressions but the Speakeasy CLI compiles them with Go's regexp.MustCompile, so a JavaScript-only construct would panic the CLI, and a default value that fails its own pattern would reject a freshly initialised gen.yaml. Add a test over all available templates that compiles each pattern the way the CLI does and checks each default value against it.
There was a problem hiding this comment.
0 issues found across 1 file (changes from recent commits).
Confidence score: 5/5
- Automated review surfaced no issues in the provided summaries.
- No files require special attention.
Shadow auto-approve: would not auto-approve. Auto-approval blocked by 1 unresolved issue from previous reviews.
View guided diff | Turn on auto-fix | Re-trigger cubic
There was a problem hiding this comment.
0 issues found across 2 files (changes from recent commits).
Confidence score: 5/5
- Automated review surfaced no issues in the provided summaries.
- No files require special attention.
Shadow auto-approve: would not auto-approve. Auto-approval blocked by 1 unresolved issue from previous reviews.
View guided diff | Turn on auto-fix | Re-trigger cubic
Config fields in config.ts can now list ValidationExamples with valid and invalid values next to their ValidationRegex. The key is test-only: GetLanguageConfigFields decodes into SDKGenConfigField, which drops it, so the CLI and the gen.yaml JSON schema never see it. TestValidationRegexes reads the raw config.ts output of every template and of the common config fields, compiles each pattern the way the CLI does, and checks the default value and every example against it. The Ruby module name cases move from their own test into ruby/config.ts.
There was a problem hiding this comment.
0 issues found across 4 files (changes from recent commits).
Confidence score: 5/5
- Automated review surfaced no issues in the provided summaries.
- No files require special attention.
Shadow auto-approve: would not auto-approve. Auto-approval blocked by 1 unresolved issue from previous reviews.
View guided diff | Turn on auto-fix | Re-trigger cubic
Decode each raw config.ts field into SDKGenConfigField plus ValidationExamples with ErrorUnused, so a misspelled ValidationExamples key or example list fails the test instead of being silently dropped. config.ts files are not covered by the templates' tsconfig, so the TypeScript type does not catch these. ValidationFunc is accepted because two fields already declare it. Also match the CLI's raw string for the escaped slash, and drop the Ruby module example that repeats the default value.
There was a problem hiding this comment.
0 issues found across 2 files (changes from recent commits).
Confidence score: 5/5
- Automated review surfaced no issues in the provided summaries.
- No files require special attention.
Shadow auto-approve: would not auto-approve. Auto-approval blocked by 1 unresolved issue from previous reviews.
View guided diff | Turn on auto-fix | Re-trigger cubic
Removing a field's ValidationRegex while keeping its examples skipped all of them, so the test stayed green after validation was dropped. Assert that fields without a pattern declare no examples. Also add the single-letter Ruby module name A as a valid example, the shortest name the pattern accepts.
There was a problem hiding this comment.
0 issues found across 2 files (changes from recent commits).
Confidence score: 5/5
- Automated review surfaced no issues in the provided summaries.
- No files require special attention.
Shadow auto-approve: would require human review. Relaxes Ruby module-name validation to accept acronyms and adds cross-target regex tests, but the new pattern also accepts T while the generator silently renames it to TT; the dismissed finding is unresolved and needs human sign-off.
View guided diff | Turn on auto-fix | Re-trigger cubic
TristanSpeakEasy
left a comment
There was a problem hiding this comment.
Looks good, accepting acronyms matches the Ruby naming behaviour and the regex examples should help keep this from regressing.
Why
The Ruby
modulegen.yaml field is validated againstValidationRegexintemplates/templates/ruby/config.ts. ItsValidationMessagereads "Module names should be PascalCase and have no special chars", but the current pattern^([A-Z][a-z0-9]+)+$is stricter than that message: every capital must be followed by a lowercase letter or digit, so acronyms are rejected.MySDK,OpenAPI, andSDKall fail.PascalCase allows acronyms; Ruby's own standard library uses them (
JSON,URI,OpenSSL,Net::HTTP). The generator already handles them as well:sanitizeModuleName(templates/templates/ruby/includes/sanitization.ts), which appliescaser().ToPascal. It keeps acronyms inside mixed-case names (MySDK,OpenAPI,HTTPClientare unchanged) and always keepsSDK. A name that is only an uppercase run other thanSDK, or that ends in an acronym followed by a digit, is rewritten (API→Api,OpenAPIV3→OpenApiv3); the result is still a valid Ruby constant.caser().ToSnake(getSDKFolderName,templateAuxPath):MySDK→lib/my_sdk/.OpenApiSdkalready renders asmodule OpenApiSDKin the review and primary Ruby SDKs, so acronym constants are already normal output.The pattern is the only thing blocking these names. The Speakeasy CLI enforces it during
speakeasy run, so an SDK whose module contains an acronym fails gen.yaml validation on every generator release that includes the current pattern. WhenspeakeasyVersionislatest, the CLI then reruns with the last version that succeeded, so the SDK quietly stops receiving generator updates and the run can still report success.No coverage for
ValidationRegexin any targetNothing in this repository exercises
ValidationRegex. The generator never reads it; onlycmd/jsonschemacopies it into a JSON Schemapattern. Generation and SDK tests therefore pass whatever the pattern says, which is how the Ruby regression went unnoticed. The same gap exists for every target:RegExp.source, but the CLI rewrites the\u002fescape that goja'sRegExp.sourceemits for an unescaped/and compiles the result with Go'sregexp.MustCompile. A JavaScript-only construct such as lookahead, lookbehind, or a backreference is valid inconfig.tsbut panics the CLI for every user of that target.DefaultValuethat fails its own pattern makes a freshly initialised gen.yaml fail validation.Today all 241 patterns across the available templates (3 common, 238 target-specific, the same count for
newSDKfalse and true) compile in Go and accept their defaults, so the check below is a guard against regressions.What changed
templates/templates/ruby/config.ts:modulepattern^([A-Z][a-z0-9]+)+$→^[A-Z][A-Za-z0-9]*$. This is exactly what the existing message says: an uppercase first letter, then letters and digits only. Names that passed before still pass;_,::,-, a lowercase first letter, and a leading digit are still rejected.templates/templates/common/common/typeDefs.d.ts:SDKGenConfigFieldgains an optionalValidationExamples: { valid?: string[]; invalid?: string[] }. It is test-only:GetLanguageConfigFieldsdecodes into sdk-gen-config'sSDKGenConfigField, which drops unknown keys, so the CLI,speakeasy configure, andcmd/jsonschemanever see it and sdk-gen-config needs no change. The templates'tsconfig.jsonfiles do not includeconfig.ts, so the type documents the key but does not check it; the test below does.templates/templates/ruby/config.ts: themodulefield declares its accepted (AcmeRubySDK,OpenAPI,SDK,Acme2, and the single letterA) and rejected (openApiSdk,Open_Api,Open::Api,Open-Api,2Acme, empty) names asValidationExamples.pkg/templates/validation_regex_test.go:TestValidationRegexesruns acommonsubtest overcommon/common/config.tsand one subtest per template fromGetAvailableTemplates(), each withnewSDKbothfalseandtrue. It reads the rawconfig.tsoutput (soValidationExamplessurvive) and decodes each field intoSDKGenConfigFieldplusValidationExampleswith mapstructure'sErrorUnused, so a misspelled key fails instead of being silently dropped.ValidationFuncis also accepted, because two existing fields (mcp-typescriptadvancedFlags,typescriptv2usageSDKInitImports) declare it even though neither the generator nor the CLI reads it. It then compiles everyValidationRegexafter applying the CLI's slash rewrite, and asserts that theDefaultValueand everyvalidexample match and everyinvalidexample does not. A field that declares examples without aValidationRegexfails, so removing a pattern cannot silently skip its examples. Common fields that a target passes through unchanged are checked once in thecommonsubtest. Each template subtest also assertsGetLanguageConfigFieldsstill succeeds. A default-value check alone cannot catch a pattern that is too strict while the default still passes; examples next to the pattern cover that without a test file per target.core/rubypatch.Generated output does not change, so no review SDKs are regenerated.
Testing
module: AcmeRubySDKandtypingStrategy: sorbetviacmd/generate: emitsmodule AcmeRubySDKunderlib/acme_ruby_sdk/.go test ./pkg/templates -run TestValidationRegexes -count=1 -race: passes. Mutation checks, each reverted afterwards:modulepattern (^(?=O)[A-Za-z]+$): fails with a compile error naming the field;moduledefaultopenApiSdk: fails naming the field, default, and pattern;modulepattern^([A-Z][a-z0-9]+)+$: fails on valid examplesAcmeRubySDK,OpenAPI,SDK;Open_Apiadded tovalid,Acmeadded toinvalid: each fails naming the example;validexamplemaybeon a common^(true|false)$field: fails in thecommonsubtest;ValidationExample, orvalidmisspelled inside it: each fails with an unknown-key error naming the field;modulepattern removed while its examples stay: fails naming the field;*changed to+in the Rubymodulepattern: fails on the valid exampleA;clitarget'spackageName, whose pattern contains/.make lint: passes.speakeasy run, which needs a CLI build bundling this generator.Public-safety check
.claude/skills/public-repo-communication/SKILL.md).git diff --check.