Repository navigation
Conversation
Add ValidationExamples to every config field whose ValidationRegex describes a structured value (names, identifiers, paths, versions, URLs, durations, numbers) across the common fields and all targets. Fields whose pattern only lists fixed values, such as ^(true|false)$, are left without examples. TestValidationRegexes checks each example against its pattern, so a future change that rejects a listed valid value or accepts a listed invalid one fails the test. No pattern changes.
The retractions field is a list of {version, comment} objects, but its
ValidationRegex matched a single semantic version. The Speakeasy CLI
checks a field's pattern against the value formatted with %v, so any
configured list, such as [map[version:v1.0.0]], failed gen.yaml
validation and could not be used.
Drop the pattern from the field and check each retraction's version in
the Go target's validateConfig instead, which receives the list itself.
The cli config validation tests' helper becomes newLanguageTestConfig
so the Go tests can share it.
The mcpName pattern only allowed lowercase letters and digits in each namespace segment and lowercase letters, digits and hyphens in the server name. The MCP registry's server.json schema accepts ^[a-zA-Z0-9.-]+/[a-zA-Z0-9._-]+$, so valid registry names such as io.github.acme-labs/petstore (a GitHub owner with a hyphen) or io.github.Acme/petstore_mcp.v2 failed gen.yaml validation. Use the registry's pattern. The value is only written to server.json and package.json.
There was a problem hiding this comment.
All reported issues were addressed across 17 files
Shadow auto-approve: would not auto-approve because issues were found.
View guided diff | Turn on auto-fix | Re-trigger cubic
The validateConfig check added for retractions runs whenever the generator loads gen.yaml, not only in the CLI. It rejected inputs that templateRetractions renders correctly: version ranges such as [v1.0.0, v1.9.9], items keyed Version, and items without a version, which the template skips. It also accepted build metadata such as v2.0.0+build.5, which Go module versions do not allow. Remove the check and its tests. With the field's ValidationRegex already gone, retractions are no longer pattern-checked by the CLI, and the generator accepts what it accepted before; an invalid version still fails when the go command loads go.mod.
The mcpName message still said "reverse-DNS format" although the pattern now follows the MCP registry and also accepts names such as acme/petstore. State the accepted shape instead. Also replace a non-generic httpClientPrefix example in the C# config.
There was a problem hiding this comment.
All reported issues were addressed across 5 files (changes from recent commits).
Shadow auto-approve: would not auto-approve because issues were found.
View guided diff | Turn on auto-fix | Re-trigger cubic
Generator Snapshot Testing
Snapshot results: https://github.com/speakeasy-api/openapi-generation-snapshots/issues/138#issuecomment-6427754866 Snapshot results are summarized above. Additional run context is linked for maintainers with access. |
The packageName pattern had no closing $, so any value that started with a valid Composer name passed, such as acme/petstoreSDK or acme/petstore sdk. The value is written unchanged to the name field of the generated composer.json, and Composer rejects such names when the SDK is installed. Use Composer's own name pattern from its JSON schema, which matches the same names and is anchored.
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
The githubURL pattern is unanchored, so values such as https://github.com/acme/acme-java, www.github.com/acme/acme-java or github.com/acme/acme-java.git pass validation. publishing.gradle prepends https:// and appends .git to the value, which turned them into POM links such as https://https://github.com/... and scm:git:ssh://git@github.com/acme/acme-java.git.git. Strip a leading http(s):// and www. and a trailing slash and .git before writing the links. The pattern is unchanged, so every value that passes validation today still passes; the canonical github.com/owner/repo form renders exactly as before.
The field description still said the name is in reverse-DNS format, while the pattern follows the MCP registry and also accepts names such as acme/petstore. Describe the namespace/server-name shape and keep reverse-DNS as the usual namespace form.
There was a problem hiding this comment.
All reported issues were addressed across 4 files (changes from recent commits).
Shadow auto-approve: would not auto-approve because issues were found.
Tip: Review your code locally with the cubic CLI to iterate faster.
View guided diff | Turn on auto-fix | Re-trigger cubic
The githubURL pattern is case-sensitive only for github.com, so values such as HTTPS://WWW.github.com/acme/acme-java.GIT pass validation; strip the scheme, www. and .git regardless of case. A non-string githubURL, such as a YAML number, made the normalization throw and abort generation, where the template previously rendered it as is. Convert the value to a string before normalizing.
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
Generate a published Java SDK for canonical, scheme/www/.git/trailing slash, uppercase and non-string githubURL values and assert the three links written to publishing.gradle. The githubURL examples only check the unchanged pattern, so they do not cover the normalization.
…examples The CLI matches a field's ValidationRegex against its value formatted with %v, so a pattern on a list field rejects every list. List fields with a default are already caught by the default value check; add a test for those without one, starting with Go retractions. Also add valid examples for the two-hyphen Composer package name boundary and an MCP server name that starts with a digit.
TristanSpeakEasy
left a comment
There was a problem hiding this comment.
Looks good, the examples cover the pattern fixes well and normalising githubURL before building the publishing links makes sense.
Stacked on #152, which adds
ValidationExamplesandTestValidationRegexes. Review after #152; this PR will be retargeted tomainonce #152 merges.Why
#152 lets a config field in
config.tslist accepted and rejected values next to itsValidationRegex, and checks them inTestValidationRegexes. Only the Rubymodulefield uses it so far. A default-value check cannot catch a pattern that rejects valid input, which is how the Ruby regression went unnoticed, and the same gap exists for every other target.Writing examples for the remaining fields surfaced two patterns that reject every or many valid values:
retractionsis a list of{version, comment}objects, but itsValidationRegexmatches a single semantic version. The Speakeasy CLI checks a field's pattern against the value formatted with%v, so a configured list arrives as[map[comment:Published accidentally version:v1.0.0]]and always fails. The field cannot be used through the CLI, although the generator renders it into theretractblock ofgo.mod.mcpNameonly allowed lowercase letters and digits per namespace segment, and lowercase letters, digits and hyphens in the server name. The MCP registry'sserver.jsonschema (the2025-12-11version the generatedserver.jsondeclares) accepts^[a-zA-Z0-9.-]+/[a-zA-Z0-9._-]+$, so registry names such asio.github.acme-labs/petstore(a GitHub owner with a hyphen) were rejected.What changed
Examples (test-only, no pattern changes):
ValidationExampleson 69 fields acrosscommon/commonand every target with structured patterns (cli, csharp, go, javav2, mcp-typescript, php, postman, pythonv2, ruby, terraform, typescriptv2, unity): names, identifiers, package and module paths, versions, URLs, durations, and numbers. Fields whose pattern only lists fixed values, such as^(true|false)$or^(net8\.0|net10\.0)$, have no examples; the pattern already is the list. Values are generic (acme,example.com). Fields that share a pattern use the same examples (for example everyversion,maxMethodParams, anddefaultErrorName);config.tsfiles run as standalone scripts and cannot import shared constants.Go
retractions: theValidationRegexandValidationMessageare removed from the field. No generator-side check replaces them:Generator.validateConfigruns whenever the generator loads gen.yaml, andtemplateRetractionsalready accepts single versions, ranges such as[v1.0.0, v1.9.9], and items keyedVersion, and skips items without a version. A stricter check there would stop generation for configurations that render a validgo.modtoday. An invalid version still fails when thegocommand loads the generatedgo.mod. Changeset:core/gopatch.MCP
mcpName: pattern replaced with the registry's, and the message and description now describe the accepted shape (a namespace and a server name separated by one slash, the namespace usually reverse-DNS), since names such asacme/petstoreare valid. The registry's 3 to 200 character length limit is not enforced: Go'sregexphas no lookahead to combine it with the pattern. The value is only written topackage.jsonandserver.json. Changeset:core/mcp-typescriptpatch.PHP
packageName: the pattern had no closing$, so any value starting with a valid Composer name passed, such asacme/petstoreSDKoracme/petstore sdk. The value is written unchanged tonamein the generatedcomposer.json, andcomposer installfails on such names. The pattern is now Composer's own name pattern from its JSON schema (^[a-z0-9]([_.-]?[a-z0-9]+)*/[a-z0-9](([_.]|-{1,2})?[a-z0-9]+)*$), which matches the same names as before and is anchored. Changeset:core/phppatch.Java
githubURLlinks:publishing.gradleprependshttps://to the value and appends.gitfor the SCM connection. Values the unanchored pattern already accepts, such ashttps://github.com/acme/acme-java,www.github.com/acme/acme-javaorgithub.com/acme/acme-java.git, rendered ashttps://https://github.com/...orscm:git:ssh://git@github.com/acme/acme-java.git.git. A leadinghttp(s)://andwww.and a trailing/and.gitare now stripped, ignoring case, before the links are written; a non-string value is converted to a string first, so it renders as before instead of failing. The pattern is unchanged, andgithub.com/owner/reporenders exactly as before, so the review SDK does not change. Changeset:core/javav2patch.The Go, MCP and Java fixes only widen what is accepted or correct the rendered output. The generator's own
validateConfigis unchanged, so no configuration that passes CLI validation or generates today stops doing so. The PHP fix narrows it, but only by names that Composer already rejects.Not changed here
Writing examples also showed patterns that accept values they should reject. Tightening a pattern makes existing gen.yaml files that rely on the looser behaviour fail validation, and when
speakeasyVersionislatestthe CLI then reruns with the last version that succeeded, so those SDKs stop receiving generator updates. Each of these needs its own decision, so the examples above avoid the affected values:githubURL(github\.com\/[a-zA-z\d_-]+?\/.+) has no anchors, andA-zalso matches[,\,],^,_and a backtick, so values such asssh://git@github.com/acme/acme-javaorsee github.com/acme/acme-javapass. The rendered POM links are now normalized (see above); tightening the pattern would reject values that generate today.templateVersion(v2) has no anchors, so any value containingv2passes. The gen.yaml value does not select the template (the field's default does) and the generator overwrites it with the template's version, so a value such asv2.0generates normally today; tightening would only reject it.scm.urlis written without a scheme (github.com/owner/repo) for every value. Fixing it changes the generatedpublishing.gradleof every published Java SDK, so it is left for a separate change.packageName(^[\w\d.\-_/]+$) accepts a leading or trailing slash, such as/acmeoracme/, which is not a valid Go module path.packageName(^[\w\d._@\/-]+$) accept values npm rejects, such as@acme(scope without a name) oracme@sdk.baseErrorName("Must start with a capital letter") and gosdkPackageName("Must start with letter") accept a leading digit or underscore. The generator sanitizes both names (a leading digit is spelled out), so generated code is not affected.groupID("Must start with a letter") accepts a leading digit or underscore, and terraformpackageNameandproviderTypeNameOverride("Letters, numbers, or - only") accept_.packageNamereject-although NuGet package IDs allow it; the value is also used as the root namespace, where-is invalid, so the examples listAcme-Sdkas invalid.Testing
go test ./pkg/templates -run TestValidationRegexes -count=1: passes; examples are read for all 70 fields (69 here plus Rubymodulefrom fix(ruby): accept acronyms in module name validation #152).packageNamepattern, the new invalid examplesacme/petstoreSDK,acme/petstore sdkandacme/petstore---sdkmatch. A rootcomposer.jsonnamedacme/petstoreSDK,acme/petstore sdkoracme/petstore!failscomposer validateandcomposer install(Composer 2.10.3) withname : Does not match the regex pattern.cmd/generate -l java -pwithgithubURL: github.com/owner/repowrites the same three POM links as before; withhttps://www.github.com/acme/acme-java.git/orHTTPS://WWW.github.com/acme/acme-java.GITit writeshttps://github.com/acme/acme-java,github.com/acme/acme-javaandscm:git:ssh://git@github.com/acme/acme-java.git.githubURL: 123rendershttps://123as before.mcpNamepattern, the new valid examplesio.github.acme-labs/petstoreandio.github.Acme/petstore_mcp.v2fail.cmd/generateforgowithretractionsset to{version: v1.0.0, comment: Published accidentally},{version: "[v1.1.0, v1.1.5]"}, and{Version: v1.2.0}generates aretractblock with all three, whichgo mod edit -jsonparses. Ago.modretracting1.0.0orv2.0.0+build.5failsgo list -m.pkg/generate/java_publishing_links_test.gogenerates a published Java SDK for canonical, scheme/www./.git/trailing-slash, uppercase and numericgithubURLvalues and asserts the three rendered links. With the normalization removed, made case-sensitive, or without the string conversion, the matching cases fail.TestListFieldsHaveNoValidationRegexasserts that Goretractionshas noValidationRegex; restoring a version pattern on it fails. List fields with a default are already caught by the default value check.acme/petstore--sdk(two hyphens) is valid, and MCPio.github.acme/2petstore(server name starting with a digit) is valid.go test ./pkg/generate -count=1,go test ./pkg/templates -count=1,make lint(includes TypeScript checks for every template): pass.speakeasy run, which needs a CLI build bundling this generator.Public-safety check
.claude/skills/public-repo-communication/SKILL.md).git diff --check.