Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Update all connected devices and running emulators with the latest version of your app(s) from HockeyApp (install Ruby & bundler first)
#!/usr/bin/ruby
require "bundler/inline"
gemfile(ARGV.any? {|arg| arg == "--install"}) do
source "https://rubygems.org"
gem "http", "~> 2.2"
gem "ADB", "~> 0.5.6"
gem "slop", "~> 4.5"
end
module ADB
extend self
end
module HockeyApp
API_BASE = "https://rink.hockeyapp.net/api/2/"
API_TOKEN = ENV["HOCKEYAPP_API_TOKEN"]
module_function
def apps
get("apps")["apps"]
.select {|app| app["platform"] == "Android" }
.map {|app| App.new app }
end
def versions(app)
get("apps/#{app.app_id}/app_versions?include_build_urls=true")["app_versions"]
.select {|version| version["build_url"] }
.map {|version| Version.new app, version }
end
def get(endpoint)
HTTP.follow.headers("X-HockeyAppToken" => API_TOKEN).get(URI.join(API_BASE, endpoint)).parse
end
def download(url, local_path)
File.open(local_path, "w") do |file|
HTTP.follow.headers("X-HockeyAppToken" => API_TOKEN).get(url).body.each do |chunk|
file.write chunk
end
end
end
end
class App
attr_reader :app_id, :package
def self.all
HockeyApp.apps
end
def initialize(data)
@app_id = data["public_identifier"]
@package = data["bundle_identifier"]
end
def latest_version
versions.sort_by(&:code).last
end
def find_version(code)
version = versions.find {|version| version.code == code }
abort "#{@package} has no version #{code}" unless version
version
end
def versions
versions = HockeyApp.versions(self)
abort "No versions for #{@package}!" if versions.empty?
versions
end
end
class Version
attr_reader :app, :code
def initialize(app, data)
@app = app
@code = data["version"]
@download_url = data["build_url"]
end
def download_to(path)
local_path = File.join(path, "#{@app.package}-#{@code}.apk")
HockeyApp.download(@download_url, local_path)
local_path
end
end
class Device
attr_reader :serial
def self.all
ADB.devices.map {|serial| new serial }
end
def initialize(serial)
@serial = serial
end
def install(local_path)
ADB.install local_path, nil, serial: @serial
end
def uninstall(package)
ADB.uninstall package, serial: @serial
end
end
abort "Please set HOCKEYAPP_API_TOKEN" if HockeyApp::API_TOKEN.nil? || HockeyApp::API_TOKEN.empty?
opts = Slop.parse do |o|
o.bool "--install", "Install script dependencies"
o.array "-d", "--devices", "Limit actions to given devices instead of all"
o.array "-p", "--packages", "Limit actions to given apps (given by their package names)"
o.string "-v", "--version", "Install specific version instead of latest"
o.on "--help" do
puts o
exit
end
end
puts "Fetching devices"
devices = Device.all
abort "No devices connected!" if devices.empty?
unless opts[:devices].empty?
opts[:devices].each do |serial|
abort "Device #{serial} not connected!" if devices.none? {|device| device.serial == serial }
end
devices.select! {|device| opts[:device].include? device.serial }
end
puts "Fetching apps"
apps = App.all
abort "No apps configured in your HockeyApp account!" if apps.empty?
unless opts[:packages].empty?
opts[:packages].each do |package|
abort "App #{package} not found in HockeyApp!" if apps.none? {|app| app.package == package }
end
apps.select! {|app| opts[:packages].include? app.package }
end
puts "Fetching app versions"
if opts[:version]
versions = apps.map {|app| app.find_version(opts[:version]) }
else
versions = apps.map(&:latest_version)
end
Dir.mktmpdir do |download_folder|
versions.each do |version|
puts "Downloading #{version.app.package} #{version.code}"
local_path = version.download_to download_folder
devices.each do |device|
puts "Installing #{version.app.package} #{version.code} to #{device.serial}"
begin
device.install local_path
rescue ADB::ADBError => e # Failed retry with trying to uninstall first
begin
device.uninstall version.app.package
device.install local_path
rescue ADB::ADBError
raise e
end
end
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.