Introduction
First, I want to thank you for creating and maintaining such an exceptional Swift client for the GitHub REST API. As a Swift developer who has benefited greatly from this library, I'm excited to contribute back to the project. While I'm not a regular contributor, I believe this change could significantly enhance the developer experience by making the generated code feel more natural and idiomatic to Swift developers.
Summary
This PR modifies the OpenAPI generation configuration to use theidiomatic Swift naming strategy instead of the default defensive one. This change transforms generated symbol names to follow Swift's conventional naming patterns rather than preserving special characters with descriptive words (e.g.,users_sol_list →usersList), significantly enhancing the developer experience.
Scope Impact: This change affects virtually all non-trivial Swift symbols throughout the codebase. Due to the comprehensive impact, I recommend this as a breaking change for a v3.0.0 release, making it opt-in for developers who use semantic versioning best practices.
Examples of Name Changes
Function Names
- Before:
copilot_sol_get_hyphen_copilot_hyphen_organization_hyphen_details - After:
copilotGetCopilotOrganizationDetails
Type Names
- Before:
copilot_hyphen_organization_hyphen_details - After:
CopilotOrganizationDetails
Enum Case Names
- Before:
text_x_hyphen_markdown - After:
textXMarkdown
Property Names
- Before:
total_engaged_users - After:
totalEngagedUsers
Parameter Names
- Before:
team_slug - After:
teamSlug
Rationale & Motivation
Improved Accessibility & Developer Experience
The primary goal of this change is to significantly enhance the usability of the generated Swift client library. The idiomatic naming strategy aligns perfectly with standard Swift practices, making the API feel more natural and intuitive for Swift developers.
Maybe it's just me, but I've found the defensive naming difficult to work with in practice. Methods likereactions_sol_list_hyphen_for_hyphen_team_hyphen_discussion_hyphen_comment_hyphen_in_hyphen_org become much more readable asreactionsListForTeamDiscussionCommentInOrg. This transformation dramatically improves readability and understanding for developers at all experience levels, making the API more intuitive and reducing cognitive overhead.
This change represents a significant accessibility improvement, making the API feel like idiomatic Swift rather than an awkward translation from another language.
Changes Made
- Upgraded Swift OpenAPI Generator dependency from 1.2.1 to 1.7.2
- Updated the generation configuration in
Scripts/GeneratorConfigBuilder.swift to use the idiomatic naming strategy - Added specific name overrides for handling edge cases like "+1" and "-1" (i.e., thumbs up and thumbs down) reactions
- Regenerated the Swift source code with the new configuration, resulting in more Swift-like
public symbol names - Fixed the test to use the new naming patterns and non-deprecated
Servers.Server1.url() API - Updated example code in the
README.md file similarly
Proposed Migration Strategy
As this change introduces significant, albeit beneficial, breaking changes across the API surface, thoughtful consideration of migration options would be valuable. Semantic versioning principles provide helpful guidance here.
One potential approach could be:
- Maintain the current v2.x releases with the existingdefensive naming strategy, possibly on a dedicated
2.x branch. - Introduce theidiomatic naming strategy proposed in this PR into the
main branch for a future v3.0.0 release as a breaking change.
The existing automated build system that monitors GitHub's OpenAPI specification for changes could be leveraged in this scenario - continuing to update and publish v2.x releases with the defensive naming convention from a maintenance branch, while themain branch would generate idiomatic naming for v3.0.0 and beyond. This would provide support for both existing users and those wanting the improved Swift-native experience.
That said, maintaining parallel release streams does involve additional overhead, and the maintainers might reasonably prefer to focus solely on the new idiomatic version. There may also be other migration approaches not outlined here that would better fit the project's needs.Ultimately, the decision on versioning strategy rests entirely with the project maintainers.
This pull request focuses solely on implementing the switch to the idiomatic naming convention and regenerating the code accordingly. Any branching strategy or infrastructure changes to support versioning would need to be addressed separately if desired.
Also, supporting both naming conventions simultaneously within thesame module would likely introduce significant complexity to the build system and codebase. A one-convention-per-major-version approach provides a cleaner migration path, allowing users to opt-in to the improved naming when ready.
I hope this suggestion contributes constructively to the discussion of how to balance improved developer experience with a smooth transition for existing users.
Swift OpenAPI Generator Upgrade
This PR includes an upgrade from Swift OpenAPI Generator 1.2.1 to 1.7.2. Upgrading to at least version 1.6.0 was a requirement for this PR, as that's when the idiomatic naming strategy was first introduced. The decision to go all the way to 1.7.2 provides additional benefits including improved naming configuration options, Windows support, and Swift 6.1+ compatibility.
Click to see detailed version highlights from 1.2.1 to 1.7.2
Version Highlights
Version 1.3.0 (July 2024):
- Added CaseIterable conformance for string and int enums
- Correctly handled path params with hyphens in names
- Fixed multipart + additionalProperties + string support
Version 1.4.0 (October 2024):
- Generated enums for server variables
- Added static property to create responses without parameters
- Introduced TranslatorContext for better code organization
Version 1.5.0-1.5.1 (November-December 2024):
- Added support for OpenAPI 3.0.4 and 3.1.1
- Improved parameter handling of MIME types
- Enabled strict concurrency
- Implemented explicit self in encoder/decoder methods
Version 1.6.0 (December 2024):
- Introduced idiomatic naming strategy as opt-in feature
- Improved member access/assignment in initializers, decoders, and encoders
Version 1.7.0 (January 2025):
- Added a CLI option for selecting the naming strategy
- Updated Examples and IntegrationTest to use idiomatic naming
- Fixed Swift 6.1+ compatibility issues
Version 1.7.1-1.7.2 (March-April 2025):
- Added Windows support
- Improved CI workflows
- Added streaming ChatGPT proxy example from FOSDEM 2025
Verification & Potential Drawbacks
Verification
All tests pass successfully whenswift build andswift test are run locally. The generated code compiles properly and all functionality remains intact with the new naming convention.
NOTE: The followingmake install warnings are present on both themain branch and this feature branch. They are related to issues in the OpenAPI specification interpretation and are not introduced by this PR.
Click to see themake install warnings
warning: A property name only appears in the required list, but not in the properties map - this is likely a typo; skipping this property. [context: foundIn=Components.Schemas.PackageVersion.MetadataPayload.DockerPayload (#/components/schemas/package-version/metadata/docker)/tags]warning: A property name only appears in the required list, but not in the properties map - this is likely a typo; skipping this property. [context: foundIn=Operations.PullsRequestReviewers.Input.Body.JsonPayload.Value1Payload (#/paths/repos/{owner}/{repo}/pulls/{pull_number}/requested_reviewers/POST/requestBody/json/value1)/reviewers]warning: A property name only appears in the required list, but not in the properties map - this is likely a typo; skipping this property. [context: foundIn=Operations.PullsRequestReviewers.Input.Body.JsonPayload.Value2Payload (#/paths/repos/{owner}/{repo}/pulls/{pull_number}/requested_reviewers/POST/requestBody/json/value2)/team_reviewers]warning: A property name only appears in the required list, but not in the properties map - this is likely a typo; skipping this property. [context: foundIn=Operations.PullsRequestReviewers.Input.Body.JsonPayload.Value1Payload (#/paths/repos/{owner}/{repo}/pulls/{pull_number}/requested_reviewers/POST/requestBody/json/value1)/reviewers]warning: A property name only appears in the required list, but not in the properties map - this is likely a typo; skipping this property. [context: foundIn=Operations.PullsRequestReviewers.Input.Body.JsonPayload.Value2Payload (#/paths/repos/{owner}/{repo}/pulls/{pull_number}/requested_reviewers/POST/requestBody/json/value2)/team_reviewers]warning: Schema "array ()" is not supported, reason: "not an object-ish schema (object, ref, allOf)", skipping [context: foundIn=Operations.ReposGetContent.Output.Ok.Body]warning: A property name only appears in the required list, but not in the properties map - this is likely a typo; skipping this property. [context: foundIn=Operations.ReposCreatePagesSite.Input.Body.JsonPayload.Value1Payload (#/paths/repos/{owner}/{repo}/pages/POST/requestBody/json/value1)/source]warning: A property name only appears in the required list, but not in the properties map - this is likely a typo; skipping this property. [context: foundIn=Operations.ReposCreatePagesSite.Input.Body.JsonPayload.Value2Payload (#/paths/repos/{owner}/{repo}/pages/POST/requestBody/json/value2)/build_type]warning: A property name only appears in the required list, but not in the properties map - this is likely a typo; skipping this property. [context: foundIn=Operations.ReposUpdateInformationAboutPagesSite.Input.Body.JsonPayload.Value1Payload (#/paths/repos/{owner}/{repo}/pages/PUT/requestBody/json/value1)/build_type]warning: A property name only appears in the required list, but not in the properties map - this is likely a typo; skipping this property. [context: foundIn=Operations.ReposUpdateInformationAboutPagesSite.Input.Body.JsonPayload.Value2Payload (#/paths/repos/{owner}/{repo}/pages/PUT/requestBody/json/value2)/source]warning: A property name only appears in the required list, but not in the properties map - this is likely a typo; skipping this property. [context: foundIn=Operations.ReposUpdateInformationAboutPagesSite.Input.Body.JsonPayload.Value3Payload (#/paths/repos/{owner}/{repo}/pages/PUT/requestBody/json/value3)/cname]warning: A property name only appears in the required list, but not in the properties map - this is likely a typo; skipping this property. [context: foundIn=Operations.ReposUpdateInformationAboutPagesSite.Input.Body.JsonPayload.Value4Payload (#/paths/repos/{owner}/{repo}/pages/PUT/requestBody/json/value4)/public]warning: A property name only appears in the required list, but not in the properties map - this is likely a typo; skipping this property. [context: foundIn=Operations.ReposUpdateInformationAboutPagesSite.Input.Body.JsonPayload.Value5Payload (#/paths/repos/{owner}/{repo}/pages/PUT/requestBody/json/value5)/https_enforced]warning: Schema "array ()" is not supported, reason: "not an object-ish schema (object, ref, allOf)", skipping [context: foundIn=Operations.ReposGetContent.Output.Ok.Body (#/paths/repos/{owner}/{repo}/contents/{path}/GET/responses/200/content)]warning: A property name only appears in the required list, but not in the properties map - this is likely a typo; skipping this property. [context: foundIn=Operations.ReposCreatePagesSite.Input.Body.JsonPayload.Value1Payload (#/paths/repos/{owner}/{repo}/pages/POST/requestBody/json/value1)/source]warning: A property name only appears in the required list, but not in the properties map - this is likely a typo; skipping this property. [context: foundIn=Operations.ReposCreatePagesSite.Input.Body.JsonPayload.Value2Payload (#/paths/repos/{owner}/{repo}/pages/POST/requestBody/json/value2)/build_type]warning: A property name only appears in the required list, but not in the properties map - this is likely a typo; skipping this property. [context: foundIn=Operations.ReposUpdateInformationAboutPagesSite.Input.Body.JsonPayload.Value1Payload (#/paths/repos/{owner}/{repo}/pages/PUT/requestBody/json/value1)/build_type]warning: A property name only appears in the required list, but not in the properties map - this is likely a typo; skipping this property. [context: foundIn=Operations.ReposUpdateInformationAboutPagesSite.Input.Body.JsonPayload.Value2Payload (#/paths/repos/{owner}/{repo}/pages/PUT/requestBody/json/value2)/source]warning: A property name only appears in the required list, but not in the properties map - this is likely a typo; skipping this property. [context: foundIn=Operations.ReposUpdateInformationAboutPagesSite.Input.Body.JsonPayload.Value3Payload (#/paths/repos/{owner}/{repo}/pages/PUT/requestBody/json/value3)/cname]warning: A property name only appears in the required list, but not in the properties map - this is likely a typo; skipping this property. [context: foundIn=Operations.ReposUpdateInformationAboutPagesSite.Input.Body.JsonPayload.Value4Payload (#/paths/repos/{owner}/{repo}/pages/PUT/requestBody/json/value4)/public]warning: A property name only appears in the required list, but not in the properties map - this is likely a typo; skipping this property. [context: foundIn=Operations.ReposUpdateInformationAboutPagesSite.Input.Body.JsonPayload.Value5Payload (#/paths/repos/{owner}/{repo}/pages/PUT/requestBody/json/value5)/https_enforced]
NOTE: The followingswift build warnings are present on both themain branch and feature branch. The only difference is the naming conventions (camel case vs snake case). These warnings don't affect functionality and are not introduced by this PR.
Click to see theswift build warnings
Sources/meta/Types.swift:295:22: warning: 'hubUrl' is deprecatedSources/migrations/Types.swift:1894:22: warning: 'hasDownloads' is deprecatedSources/migrations/Types.swift:1908:22: warning: 'useSquashPrTitleAsDefault' is deprecatedSources/search/Types.swift:1521:22: warning: 'hasDownloads' is deprecatedSources/search/Types.swift:1535:22: warning: 'useSquashPrTitleAsDefault' is deprecatedSources/search/Types.swift:5234:26: warning: 'sort' is deprecatedSources/search/Types.swift:5235:26: warning: 'order' is deprecatedSources/search/Client.swift:92:40: warning: 'sort' is deprecatedSources/search/Client.swift:99:40: warning: 'order' is deprecatedSources/copilot/Types.swift:1407:22: warning: 'updatedAt' is deprecatedSources/copilot/Types.swift:1451:22: warning: 'updatedAt' is deprecatedSources/security-advisories/Types.swift:2190:22: warning: 'hasDownloads' is deprecatedSources/security-advisories/Types.swift:2204:22: warning: 'useSquashPrTitleAsDefault' is deprecatedSources/security-advisories/Types.swift:3755:22: warning: 'hasDownloads' is deprecatedSources/security-advisories/Types.swift:3769:22: warning: 'useSquashPrTitleAsDefault' is deprecatedSources/gists/Types.swift:2242:22: warning: 'forks' is deprecatedSources/gists/Types.swift:2243:22: warning: 'history' is deprecatedSources/dependabot/Client.swift:1217:40: warning: 'page' is deprecatedSources/dependabot/Client.swift:1224:40: warning: 'perPage' is deprecatedSources/dependabot/Types.swift:6399:26: warning: 'page' is deprecatedSources/dependabot/Types.swift:6400:26: warning: 'perPage' is deprecatedSources/pulls/Types.swift:2215:22: warning: 'hasDownloads' is deprecatedSources/pulls/Types.swift:2229:22: warning: 'useSquashPrTitleAsDefault' is deprecatedSources/pulls/Types.swift:7720:30: warning: 'position' is deprecatedSources/orgs/Types.swift:5878:22: warning: 'advancedSecurityEnabledForNewRepositories' is deprecatedSources/orgs/Types.swift:5879:22: warning: 'dependabotAlertsEnabledForNewRepositories' is deprecatedSources/orgs/Types.swift:5880:22: warning: 'dependabotSecurityUpdatesEnabledForNewRepositories' is deprecatedSources/orgs/Types.swift:5881:22: warning: 'dependencyGraphEnabledForNewRepositories' is deprecatedSources/orgs/Types.swift:5882:22: warning: 'secretScanningEnabledForNewRepositories' is deprecatedSources/orgs/Types.swift:5883:22: warning: 'secretScanningPushProtectionEnabledForNewRepositories' is deprecatedSources/orgs/Types.swift:9399:30: warning: 'advancedSecurityEnabledForNewRepositories' is deprecatedSources/orgs/Types.swift:9400:30: warning: 'dependabotAlertsEnabledForNewRepositories' is deprecatedSources/orgs/Types.swift:9401:30: warning: 'dependabotSecurityUpdatesEnabledForNewRepositories' is deprecatedSources/orgs/Types.swift:9402:30: warning: 'dependencyGraphEnabledForNewRepositories' is deprecatedSources/orgs/Types.swift:9403:30: warning: 'secretScanningEnabledForNewRepositories' is deprecatedSources/orgs/Types.swift:9404:30: warning: 'secretScanningPushProtectionEnabledForNewRepositories' is deprecatedSources/activity/Types.swift:2053:22: warning: 'hasDownloads' is deprecatedSources/activity/Types.swift:2067:22: warning: 'useSquashPrTitleAsDefault' is deprecatedSources/apps/Types.swift:3981:22: warning: 'hasDownloads' is deprecatedSources/apps/Types.swift:3995:22: warning: 'useSquashPrTitleAsDefault' is deprecatedSources/codespaces/Types.swift:2575:22: warning: 'hasDownloads' is deprecatedSources/codespaces/Types.swift:2589:22: warning: 'useSquashPrTitleAsDefault' is deprecatedSources/codespaces/Types.swift:4731:22: warning: 'hasDownloads' is deprecatedSources/codespaces/Types.swift:4745:22: warning: 'useSquashPrTitleAsDefault' is deprecatedSources/issues/Types.swift:2907:22: warning: 'hasDownloads' is deprecatedSources/issues/Types.swift:2921:22: warning: 'useSquashPrTitleAsDefault' is deprecatedSources/actions/Types.swift:5494:22: warning: 'hasDownloads' is deprecatedSources/actions/Types.swift:5508:22: warning: 'useSquashPrTitleAsDefault' is deprecatedSources/repos/Types.swift:7921:22: warning: 'hasDownloads' is deprecatedSources/repos/Types.swift:7935:22: warning: 'useSquashPrTitleAsDefault' is deprecatedSources/repos/Types.swift:10315:22: warning: 'hasDownloads' is deprecatedSources/repos/Types.swift:10329:22: warning: 'useSquashPrTitleAsDefault' is deprecatedSources/repos/Types.swift:23836:30: warning: 'useSquashPrTitleAsDefault' is deprecatedSources/repos/Types.swift:26272:30: warning: 'useSquashPrTitleAsDefault' is deprecatedSources/repos/Types.swift:29399:34: warning: 'contexts' is deprecatedSources/repos/Types.swift:31871:30: warning: 'contexts' is deprecated
Potential Drawbacks & Mitigation
There is a risk that future GitHub API elements with names that conflict with Swift keywords or conventions might break the automated generation process. However, the significant improvement in API accessibility and developer experience far outweighs the occasional inconvenience of needing to manually configure name overrides when such edge cases arise.
These edge cases are likely to be rare, and the provided override mechanism gives us a straightforward way to handle them when they appear. For example, necessary overrides for the "+1" and "-1" reactions have been included in this PR, and serve as a model for any future scenarios that may arise.
IMHO, the benefit to developer productivity and code readability makes this trade-off well worth it, especially for a team working with this API on a daily basis.
Uh oh!
There was an error while loading.Please reload this page.
Introduction
First, I want to thank you for creating and maintaining such an exceptional Swift client for the GitHub REST API. As a Swift developer who has benefited greatly from this library, I'm excited to contribute back to the project. While I'm not a regular contributor, I believe this change could significantly enhance the developer experience by making the generated code feel more natural and idiomatic to Swift developers.
Summary
This PR modifies the OpenAPI generation configuration to use theidiomatic Swift naming strategy instead of the default defensive one. This change transforms generated symbol names to follow Swift's conventional naming patterns rather than preserving special characters with descriptive words (e.g.,
users_sol_list→usersList), significantly enhancing the developer experience.Scope Impact: This change affects virtually all non-trivial Swift symbols throughout the codebase. Due to the comprehensive impact, I recommend this as a breaking change for a v3.0.0 release, making it opt-in for developers who use semantic versioning best practices.
Examples of Name Changes
Function Names
copilot_sol_get_hyphen_copilot_hyphen_organization_hyphen_detailscopilotGetCopilotOrganizationDetailsType Names
copilot_hyphen_organization_hyphen_detailsCopilotOrganizationDetailsEnum Case Names
text_x_hyphen_markdowntextXMarkdownProperty Names
total_engaged_userstotalEngagedUsersParameter Names
team_slugteamSlugRationale & Motivation
Improved Accessibility & Developer Experience
The primary goal of this change is to significantly enhance the usability of the generated Swift client library. The idiomatic naming strategy aligns perfectly with standard Swift practices, making the API feel more natural and intuitive for Swift developers.
Maybe it's just me, but I've found the defensive naming difficult to work with in practice. Methods like
reactions_sol_list_hyphen_for_hyphen_team_hyphen_discussion_hyphen_comment_hyphen_in_hyphen_orgbecome much more readable asreactionsListForTeamDiscussionCommentInOrg. This transformation dramatically improves readability and understanding for developers at all experience levels, making the API more intuitive and reducing cognitive overhead.This change represents a significant accessibility improvement, making the API feel like idiomatic Swift rather than an awkward translation from another language.
Changes Made
Scripts/GeneratorConfigBuilder.swiftto use the idiomatic naming strategypublicsymbol namesServers.Server1.url()APIREADME.mdfile similarlyProposed Migration Strategy
As this change introduces significant, albeit beneficial, breaking changes across the API surface, thoughtful consideration of migration options would be valuable. Semantic versioning principles provide helpful guidance here.
One potential approach could be:
2.xbranch.mainbranch for a future v3.0.0 release as a breaking change.The existing automated build system that monitors GitHub's OpenAPI specification for changes could be leveraged in this scenario - continuing to update and publish v2.x releases with the defensive naming convention from a maintenance branch, while the
mainbranch would generate idiomatic naming for v3.0.0 and beyond. This would provide support for both existing users and those wanting the improved Swift-native experience.That said, maintaining parallel release streams does involve additional overhead, and the maintainers might reasonably prefer to focus solely on the new idiomatic version. There may also be other migration approaches not outlined here that would better fit the project's needs.Ultimately, the decision on versioning strategy rests entirely with the project maintainers.
This pull request focuses solely on implementing the switch to the idiomatic naming convention and regenerating the code accordingly. Any branching strategy or infrastructure changes to support versioning would need to be addressed separately if desired.
Also, supporting both naming conventions simultaneously within thesame module would likely introduce significant complexity to the build system and codebase. A one-convention-per-major-version approach provides a cleaner migration path, allowing users to opt-in to the improved naming when ready.
I hope this suggestion contributes constructively to the discussion of how to balance improved developer experience with a smooth transition for existing users.
Swift OpenAPI Generator Upgrade
This PR includes an upgrade from Swift OpenAPI Generator 1.2.1 to 1.7.2. Upgrading to at least version 1.6.0 was a requirement for this PR, as that's when the idiomatic naming strategy was first introduced. The decision to go all the way to 1.7.2 provides additional benefits including improved naming configuration options, Windows support, and Swift 6.1+ compatibility.
Click to see detailed version highlights from 1.2.1 to 1.7.2
Version Highlights
Version 1.3.0 (July 2024):
Version 1.4.0 (October 2024):
Version 1.5.0-1.5.1 (November-December 2024):
Version 1.6.0 (December 2024):
Version 1.7.0 (January 2025):
Version 1.7.1-1.7.2 (March-April 2025):
Verification & Potential Drawbacks
Verification
All tests pass successfully when
swift buildandswift testare run locally. The generated code compiles properly and all functionality remains intact with the new naming convention.NOTE: The following
make installwarnings are present on both themainbranch and this feature branch. They are related to issues in the OpenAPI specification interpretation and are not introduced by this PR.Click to see themake install warnings
NOTE: The following
swift buildwarnings are present on both themainbranch and feature branch. The only difference is the naming conventions (camel case vs snake case). These warnings don't affect functionality and are not introduced by this PR.Click to see theswift build warnings
Potential Drawbacks & Mitigation
There is a risk that future GitHub API elements with names that conflict with Swift keywords or conventions might break the automated generation process. However, the significant improvement in API accessibility and developer experience far outweighs the occasional inconvenience of needing to manually configure name overrides when such edge cases arise.
These edge cases are likely to be rare, and the provided override mechanism gives us a straightforward way to handle them when they appear. For example, necessary overrides for the "+1" and "-1" reactions have been included in this PR, and serve as a model for any future scenarios that may arise.
IMHO, the benefit to developer productivity and code readability makes this trade-off well worth it, especially for a team working with this API on a daily basis.