Skip to content

Instantly share code, notes, and snippets.

@Grohden
Last active January 13, 2025 14:19
Show Gist options
  • Save Grohden/c64cadd32cfb0c819f3d6c0591a9f2c7 to your computer and use it in GitHub Desktop.
Save Grohden/c64cadd32cfb0c819f3d6c0591a9f2c7 to your computer and use it in GitHub Desktop.
A rb script to sync app.json (expo) version into native project files
require 'json'
class BaseFileManager
attr_reader :file_path
def initialize(file_path)
@file_path = file_path
end
def content
@content ||= File.open(@file_path, "r").read
end
def commit
file = File.open(@file_path, "w")
file.write(content)
file.close
end
end
class PBXManager < BaseFileManager
MARKETING_VERSION_RGX = /MARKETING_VERSION = (.*);/
def set_version_name(version)
current_version_name = MARKETING_VERSION_RGX.match(content).to_s
new_version_name = "MARKETING_VERSION = #{version};"
@content.gsub!(current_version_name, new_version_name)
{ current_version: current_version_name, new_version: new_version_name }
end
end
class BuildGradleManager < BaseFileManager
QUOTES_RGX = /(["'])(.*)(["'])/
NAME_RGX = /versionName ('.*'|".*")/
def set_version_name(version)
current_version_name = NAME_RGX.match(content).to_s
new_version_name = current_version_name.gsub(QUOTES_RGX, "\\1#{version}\\3")
@content.gsub!(current_version_name, new_version_name)
{ current_version: current_version_name, new_version: new_version_name }
end
end
class VersionSynchronizer
def self.on_self_dir
# Its expected that you put this in a subfolder, usually ./scripts
new(root_dir: File.expand_path('..', __dir__))
end
def initialize(root_dir:)
@root_dir = root_dir
@version = JSON.parse(File.read("#{@root_dir}/app.json"))["version"]
# FIXME: replace PROJECT_NAME with your own project name
@pbx_manager = PBXManager.new(
"#{@root_dir}/ios/PROJECT_NAME.xcodeproj/project.pbxproj"
)
@build_gradle_manager = BuildGradleManager.new(
"#{@root_dir}/android/app/build.gradle"
)
end
def sync
dry_sync
@pbx_manager.commit
@build_gradle_manager.commit
end
def dry_sync
pbx_changes = @pbx_manager.set_version_name(@version)
build_gradle_changes = @build_gradle_manager.set_version_name(@version)
puts <<~MSG
Changes for #{@pbx_manager.file_path}:
#{pbx_changes.values.join(' -> ')}
MSG
puts <<~MSG
Changes for #{@build_gradle_manager.file_path}:
#{build_gradle_changes.values.join(' -> ')}
MSG
end
def sync_check
pbx_changes = @pbx_manager.set_version_name(@version)
build_gradle_changes = @build_gradle_manager.set_version_name(@version)
if pbx_changes.values.uniq.size > 1 || build_gradle_changes.values.uniq.size > 1
puts "Version in files not synchronized"
puts "Please run `yarn version-sync` to sync versions & commit that"
puts <<~MSG
#{@pbx_manager.file_path}:
expected #{pbx_changes[:new_version]}
got #{pbx_changes[:current_version]}
MSG
puts <<~MSG
#{@build_gradle_manager.file_path}:
expected #{build_gradle_changes[:new_version]}
got #{build_gradle_changes[:current_version]}
MSG
raise "Version strings mismatch"
end
end
end
@Grohden
Copy link
Author

Grohden commented Jan 13, 2025

then just call VersionSynchronizer.on_self_dir.sync to sync or VersionSynchronizer.on_self_dir.sync_check to check

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment