Last active
December 30, 2023 06:35
-
-
Save oinariman/d63566eda7a8c7d8ce0c323e8b3a023d to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'json' | |
require 'jwt' | |
require 'net/http' | |
APP_ID = ARGV[0] | |
KEY_ID = ARGV[1] | |
ISSUER_ID = ARGV[2] | |
AUTH_KEY_PATH = ARGV[3] | |
FETCH_LOCALES = ARGV.length == 4 | |
VERSION = ARGV[4] | |
TOKEN_LIFETIME = 600 # 10 minutes (up to 20 minutes allowed by Apple) | |
HTTP_METHODS = { | |
get: Net::HTTP::Get, | |
post: Net::HTTP::Post, | |
patch: Net::HTTP::Patch, | |
} | |
$token = nil | |
def make_token | |
header = { | |
"alg": "ES256", | |
"kid": KEY_ID, | |
"typ": "JWT" | |
} | |
now = Time.now.to_i | |
payload = { | |
"iss": ISSUER_ID, | |
"iat": now, | |
"exp": now + TOKEN_LIFETIME, | |
"aud": "appstoreconnect-v1" | |
} | |
ecdsa_key = OpenSSL::PKey::EC.new IO.read AUTH_KEY_PATH | |
return JWT.encode payload, ecdsa_key, "ES256", header | |
end | |
def request_api(method, uri_string, request_body = nil) | |
uri = URI(uri_string) | |
http = Net::HTTP.new(uri.host, uri.port) | |
http.use_ssl = true | |
headers = { "Content-Type" => "application/json", "Authorization" => "Bearer #{$token}" } | |
request = HTTP_METHODS[method].new(uri.path, headers) | |
if request_body != nil then | |
request.body = request_body.to_json | |
end | |
response = http.request(request) | |
case response | |
when Net::HTTPSuccess | |
return JSON.parse(response.body) | |
else | |
return nil | |
end | |
end | |
def make_new_version(version) | |
request_body = { | |
"data": { | |
"type": "appStoreVersions", | |
"attributes": { | |
"platform": "IOS", | |
"versionString": version, | |
"releaseType": "MANUAL" | |
}, | |
"relationships": { | |
"app": { | |
"data": { | |
"type": "apps", | |
"id": APP_ID | |
} | |
} | |
} | |
} | |
} | |
result = request_api(:post, "https://api.appstoreconnect.apple.com/v1/appStoreVersions", request_body) | |
if result == nil then | |
puts "Failed to create new version: #{VERSION}" | |
return nil | |
else | |
puts "Created new version: #{VERSION}" | |
return result['data']['id'] | |
end | |
end | |
def fetch_latest_version_id() | |
result = request_api(:get, "https://api.appstoreconnect.apple.com/v1/apps/#{APP_ID}/appStoreVersions") | |
version_id = result == nil ? nil : result['data'][0]['id'] | |
if version_id == nil then | |
puts "Failed to fetch latest version id" | |
else | |
version_string = result['data'][0]['attributes']['versionString'] | |
puts "Fetched latest version id: #{version_id} (#{version_string})" | |
end | |
return version_id | |
end | |
def fetch_localizations(version_id) | |
result = request_api(:get, "https://api.appstoreconnect.apple.com/v1/appStoreVersions/#{version_id}/appStoreVersionLocalizations") | |
if result == nil then | |
puts "Failed to fetch localizations" | |
return nil | |
end | |
puts "Fetched localizations" | |
return result['data'].map do |localization| | |
{ 'id' => localization['id'], 'locale' => localization['attributes']['locale'] } | |
end | |
end | |
def read_whats_new_files | |
files = Dir.glob("./whats_new/**/*") | |
contents = {} | |
return files.map {|file| | |
{ File.basename(file, ".*") => File.read(file) } | |
}.reduce({}, :merge) | |
end | |
def update_localization(localization_id, whats_new, locale) | |
request_body = { | |
"data": { | |
"id": localization_id, | |
"type": "appStoreVersionLocalizations", | |
"attributes": { | |
"whatsNew": whats_new | |
} | |
} | |
} | |
result = request_api(:patch, "https://api.appstoreconnect.apple.com/v1/appStoreVersionLocalizations/#{localization_id}", request_body) | |
if result == nil then | |
puts "Failed to update localization: #{locale}" | |
else | |
puts "Updated localization: #{locale}" | |
end | |
return result | |
end | |
# make token | |
$token = make_token | |
# make new version | |
# (don't exit if failed, because version may already be created and we can continue to update localizations) | |
version_id = nil | |
if not FETCH_LOCALES then | |
version_id = make_new_version(VERSION) | |
end | |
# fetch latest version id | |
if version_id == nil then | |
version_id = fetch_latest_version_id() | |
end | |
exit if version_id == nil | |
# fetch localizations | |
localizations = fetch_localizations(version_id) | |
exit if localizations == nil | |
if FETCH_LOCALES then | |
# print locales | |
puts "Locales:" | |
puts localizations.map { |localization| localization['locale'] } | |
exit | |
else | |
# update localizations | |
read_whats_new_files().each do |locale, whats_new| | |
localization = localizations.find { |localization| localization['locale'] == locale } | |
if localization != nil then | |
update_localization(localization['id'], whats_new, locale) | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment