-
-
Notifications
You must be signed in to change notification settings - Fork 0
feat(dx): Add tools to bump version #85
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR adds developer tooling to bump version numbers (major, minor, or patch) for the Flinky iOS app. It introduces three new Fastlane lanes and corresponding Makefile targets to automate semantic versioning updates in the project.
Changes:
- Added three public Fastlane lanes (
bump_version_major,bump_version_minor,bump_version_patch) and a private helper lane (_bump_version) to handle version bumping - Added three Makefile targets (
bump-version-major,bump-version-minor,bump-version-patch) that invoke the corresponding Fastlane lanes - Implementation manually updates MARKETING_VERSION entries in project.pbxproj using regex replacement
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| fastlane/Fastfile | Adds version bumping lanes that parse current version, increment appropriate component, and update project.pbxproj via regex replacement |
| Makefile | Adds VERSION MANAGEMENT section with three targets that invoke the new Fastlane lanes after installing dependencies |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| # Parse version into components | ||
| version_parts = old_version.split(".").map(&:to_i) | ||
| major = version_parts[0] || 0 | ||
| minor = version_parts[1] || 0 | ||
| patch = version_parts[2] || 0 |
Copilot
AI
Jan 26, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The version parsing logic uses || 0 fallback for missing version components, but this could mask issues with malformed version numbers. For example, if the version is "1.2.3.4", the extra ".4" would be silently ignored.
Consider adding validation to ensure the version follows the expected format before parsing:
unless old_version.match?(/^\d+\.\d+\.\d+$/)
UI.user_error!("Invalid version format: #{old_version}. Expected format: major.minor.patch")
end| # Private lane: Bump version number in project.pbxproj | ||
| private_lane :_bump_version do |options| | ||
| bump_type = options[:bump_type] # "major", "minor", or "patch" | ||
|
|
||
| # Get current version | ||
| old_version = get_version_number( | ||
| xcodeproj: "Flinky.xcodeproj", | ||
| target: "Flinky" | ||
| ) | ||
|
|
||
| # Parse version into components | ||
| version_parts = old_version.split(".").map(&:to_i) | ||
| major = version_parts[0] || 0 | ||
| minor = version_parts[1] || 0 | ||
| patch = version_parts[2] || 0 | ||
|
|
||
| # Increment the appropriate part | ||
| case bump_type | ||
| when "major" | ||
| major += 1 | ||
| minor = 0 | ||
| patch = 0 | ||
| when "minor" | ||
| minor += 1 | ||
| patch = 0 | ||
| when "patch" | ||
| patch += 1 | ||
| else | ||
| UI.user_error!("Invalid bump_type: #{bump_type}. Must be 'major', 'minor', or 'patch'") | ||
| end | ||
|
|
||
| new_version = "#{major}.#{minor}.#{patch}" | ||
|
|
||
| # Update all MARKETING_VERSION entries in project.pbxproj | ||
| project_file = File.expand_path("../Flinky.xcodeproj/project.pbxproj") | ||
| project_content = File.read(project_file) | ||
|
|
||
| # Replace all MARKETING_VERSION entries | ||
| updated_content = project_content.gsub( | ||
| /MARKETING_VERSION = #{Regexp.escape(old_version)};/, | ||
| "MARKETING_VERSION = #{new_version};" | ||
| ) | ||
|
|
||
| # Write the updated content back | ||
| File.write(project_file, updated_content) | ||
|
|
Copilot
AI
Jan 26, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider using fastlane's built-in increment_version_number action instead of manually manipulating the project.pbxproj file. The built-in action is more robust, handles edge cases better, and is maintained by the fastlane team.
Example usage:
increment_version_number(
xcodeproj: "Flinky.xcodeproj",
bump_type: bump_type # "major", "minor", or "patch"
)This approach would:
- Be more maintainable and less prone to breaking with Xcode updates
- Handle all build configurations automatically
- Properly parse and validate version numbers
- Reduce the risk of file corruption from manual regex replacements
| # Private lane: Bump version number in project.pbxproj | |
| private_lane :_bump_version do |options| | |
| bump_type = options[:bump_type] # "major", "minor", or "patch" | |
| # Get current version | |
| old_version = get_version_number( | |
| xcodeproj: "Flinky.xcodeproj", | |
| target: "Flinky" | |
| ) | |
| # Parse version into components | |
| version_parts = old_version.split(".").map(&:to_i) | |
| major = version_parts[0] || 0 | |
| minor = version_parts[1] || 0 | |
| patch = version_parts[2] || 0 | |
| # Increment the appropriate part | |
| case bump_type | |
| when "major" | |
| major += 1 | |
| minor = 0 | |
| patch = 0 | |
| when "minor" | |
| minor += 1 | |
| patch = 0 | |
| when "patch" | |
| patch += 1 | |
| else | |
| UI.user_error!("Invalid bump_type: #{bump_type}. Must be 'major', 'minor', or 'patch'") | |
| end | |
| new_version = "#{major}.#{minor}.#{patch}" | |
| # Update all MARKETING_VERSION entries in project.pbxproj | |
| project_file = File.expand_path("../Flinky.xcodeproj/project.pbxproj") | |
| project_content = File.read(project_file) | |
| # Replace all MARKETING_VERSION entries | |
| updated_content = project_content.gsub( | |
| /MARKETING_VERSION = #{Regexp.escape(old_version)};/, | |
| "MARKETING_VERSION = #{new_version};" | |
| ) | |
| # Write the updated content back | |
| File.write(project_file, updated_content) | |
| # Private lane: Bump version number using Fastlane's built-in action | |
| private_lane :_bump_version do |options| | |
| bump_type = options[:bump_type] # "major", "minor", or "patch" | |
| # Validate bump_type | |
| unless ["major", "minor", "patch"].include?(bump_type) | |
| UI.user_error!("Invalid bump_type: #{bump_type}. Must be 'major', 'minor', or 'patch'") | |
| end | |
| # Get current version before bump | |
| old_version = get_version_number( | |
| xcodeproj: "Flinky.xcodeproj", | |
| target: "Flinky" | |
| ) | |
| # Use Fastlane's built-in increment_version_number to handle the bump | |
| increment_version_number( | |
| xcodeproj: "Flinky.xcodeproj", | |
| bump_type: bump_type | |
| ) | |
| # Read the new version after bump | |
| new_version = get_version_number( | |
| xcodeproj: "Flinky.xcodeproj", | |
| target: "Flinky" | |
| ) |
| /MARKETING_VERSION = #{Regexp.escape(old_version)};/, | ||
| "MARKETING_VERSION = #{new_version};" | ||
| ) | ||
|
|
Copilot
AI
Jan 26, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The implementation doesn't verify whether the regex replacement actually modified any content. If the old_version doesn't match any MARKETING_VERSION entries (e.g., if the version format is different), the function will silently succeed without making any changes.
Add validation to ensure the replacement was successful:
if updated_content == project_content
UI.user_error!("Failed to update version in project file. No MARKETING_VERSION entries matched '#{old_version}'")
end| # Ensure the replacement was successful | |
| if updated_content == project_content | |
| UI.user_error!("Failed to update version in project file. No MARKETING_VERSION entries matched '#{old_version}'") | |
| end | |
No description provided.