Skip to content

Commit

Permalink
Merge pull request #4 from DeployGate/feature/ios_build
Browse files Browse the repository at this point in the history
[WIP] Support ios build
  • Loading branch information
henteko committed Oct 28, 2015
2 parents d4f0ff0 + 76066d1 commit 1b7749c
Show file tree
Hide file tree
Showing 18 changed files with 845 additions and 9 deletions.
9 changes: 8 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,19 @@ $ gem install deploygate
```

## Usage
Upload an application:

### Upload apps

```
$ dg deploy [package file path]
```

### iOS build and upload

```
$ dg deploy [ios project path]
```

## License

Copyright (C) 2015 DeployGate All rights reserved.
Expand Down
11 changes: 10 additions & 1 deletion deploygate.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ Gem::Specification.new do |spec|
dg installed! To get started fast:
$ dg deploy [app_file_path]
$ dg deploy
Or see the docs at:
Expand All @@ -28,6 +28,15 @@ POST_INSTALL_MESSAGE
spec.add_dependency 'httpclient', '~> 2.2.5'
spec.add_dependency 'commander', '~> 4.3.5'
spec.add_dependency 'color_echo', '~> 2.0.1'
spec.add_dependency 'plist', '~> 3.1.0'
spec.add_dependency 'xcodeproj', '~> 0.28.2'
spec.add_dependency 'github_issue_request', '~> 0.0.2'
spec.add_dependency 'highline', '~> 1.7.8'

# ios build
spec.add_dependency 'gym', '~> 1.0.0'
spec.add_dependency 'spaceship', '~> 0.12.3'
spec.add_dependency 'sigh', '~> 1.1.0'

spec.add_development_dependency "bundler", "~> 1.3"
spec.add_development_dependency "rake"
Expand Down
17 changes: 17 additions & 0 deletions lib/deploygate.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,17 @@
require "io/console"
require "rbconfig"
require "color_echo"
require "openssl"
require "plist"
require "find"
require "github_issue_request"
require "highline"

# ios build
require "gym"
require "spaceship"
require "sigh"
require "xcodeproj"

module DeployGate
end
Expand All @@ -16,9 +27,15 @@ module DeployGate
require "deploygate/commands/logout"
require "deploygate/commands/deploy"
require "deploygate/commands/deploy/push"
require "deploygate/commands/deploy/build"
require "deploygate/config"
require "deploygate/session"
require "deploygate/deploy"
require "deploygate/build"
require "deploygate/builds/ios"
require "deploygate/builds/ios/export"
require "deploygate/builds/ios/analyze"
require "deploygate/builds/ios/set_profile"
require "deploygate/message/error"
require "deploygate/message/success"
require "deploygate/version"
18 changes: 18 additions & 0 deletions lib/deploygate/build.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
module DeployGate
class Build
class << self

# @param [String] path
# @return [Boolean]
def ios?(path)
DeployGate::Builds::Ios.workspace?(path) || DeployGate::Builds::Ios.project?(path) || DeployGate::Builds::Ios.ios_root?(path)
end

# @param [String] path
# @return [Boolean]
def android?(path)
false # TODO: support android build
end
end
end
end
81 changes: 81 additions & 0 deletions lib/deploygate/builds/ios.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
module DeployGate
module Builds
module Ios
WORK_DIR_EXTNAME = '.xcworkspace'
PROJECT_DIR_EXTNAME = '.xcodeproj'

class NotSupportExportMethodError < StandardError
end

class << self
# @param [Analyze] ios_analyze
# @param [String] target_scheme
# @param [String] codesigning_identity
# @param [String] export_method
# @return [String]
def build(ios_analyze, target_scheme, codesigning_identity, export_method = Export::AD_HOC)
raise NotSupportExportMethodError, 'Not support export' unless Export::SUPPORT_EXPORT_METHOD.include?(export_method)

values = {
:export_method => export_method,
:workspace => ios_analyze.build_workspace,
:configuration => Analyze::BUILD_CONFIGRATION,
:scheme => target_scheme,
:codesigning_identity => codesigning_identity
}
v = FastlaneCore::Configuration.create(Gym::Options.available_options, values)
absolute_ipa_path = File.expand_path(Gym::Manager.new.work(v))
absolute_dsym_path = absolute_ipa_path.gsub(".ipa", ".app.dSYM.zip") # TODO: upload to deploygate

absolute_ipa_path
end

# @param [String] path
# @return [Boolean]
def workspace?(path)
WORK_DIR_EXTNAME == File.extname(path)
end

# @param [String] path
# @return [Boolean]
def project?(path)
PROJECT_DIR_EXTNAME == File.extname(path)
end

def ios_root?(base_path)
Find.find(base_path) do |path|
next if path == base_path
return true if workspace?(path) || project?(path)
Find.prune if FileTest.directory?(path)
end
false
end

# @param [String] base_path
# @param [Boolean] current_only
# @return [Array]
def find_workspaces(base_path)
projects = []
Find.find(base_path) do |path|
next if path == base_path
if File.extname(path) == WORK_DIR_EXTNAME
projects.push(path)
end
end

projects
end

# @param [String] path
# @return [String]
def project_root_path(path)
result = path
if workspace?(path) || project?(path)
result = project_root_path(File.dirname(path))
end
result
end
end
end
end
end
94 changes: 94 additions & 0 deletions lib/deploygate/builds/ios/analyze.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
module DeployGate
module Builds
module Ios
class Analyze
attr_reader :workspaces, :scheme_workspace, :build_workspace, :scheme

class NotLocalProvisioningProfileError < StandardError
end

BASE_WORK_DIR_NAME = 'project.xcworkspace'
BUILD_CONFIGRATION = 'Release'

# @param [Array] workspaces
# @return [DeployGate::Builds::Ios::Analyze]
def initialize(workspaces)
@workspaces = workspaces
@scheme_workspace = find_scheme_workspace(workspaces)
@build_workspace = find_build_workspace(workspaces)
@xcodeproj = File.dirname(@scheme_workspace)

config = FastlaneCore::Configuration.create(Gym::Options.available_options, {:workspace => @scheme_workspace})
project = FastlaneCore::Project.new(config)
if project.schemes.empty?
config = FastlaneCore::Configuration.create(Gym::Options.available_options, {:workspace => @build_workspace})
project = FastlaneCore::Project.new(config)
end
project.select_scheme
@scheme = project.options[:scheme]
end

# @return [String]
def target_bundle_identifier
scheme_file = find_xcschemes
xs = Xcodeproj::XCScheme.new(scheme_file)
target_name = xs.profile_action.buildable_product_runnable.buildable_reference.target_name

project = Xcodeproj::Project.open(@xcodeproj)
target = project.native_targets.reject{|target| target.name != target_name}.first
product_name = target.product_name
conf = target.build_configuration_list.build_configurations.reject{|conf| conf.name != BUILD_CONFIGRATION}.first
identifier = conf.build_settings['PRODUCT_BUNDLE_IDENTIFIER']
identifier.gsub!(/\$\(PRODUCT_NAME:.+\)/, product_name)

identifier
end

private

def find_xcschemes
shared_schemes = Dir[File.join(@xcodeproj, 'xcshareddata', 'xcschemes', '*.xcscheme')].reject do |scheme|
@scheme != File.basename(scheme, '.xcscheme')
end
user_schemes = Dir[File.join(@xcodeproj, 'xcuserdata', '*.xcuserdatad', 'xcschemes', '*.xcscheme')].reject do |scheme|
@scheme != File.basename(scheme, '.xcscheme')
end

shared_schemes.concat(user_schemes).first
end

# @param [Array] workspaces
# @return [String]
def find_scheme_workspace(workspaces)
return nil if workspaces.empty?
return workspaces.first if workspaces.count == 1

select = nil
workspaces.each do |workspace|
if BASE_WORK_DIR_NAME == File.basename(workspace)
select = workspace
end
end

select
end

# @param [Array] workspaces
# @return [String]
def find_build_workspace(workspaces)
return nil if workspaces.empty?
return workspaces.first if workspaces.count == 1

select = nil
workspaces.each do |workspace|
if BASE_WORK_DIR_NAME != File.basename(workspace)
select = workspace
end
end

select
end
end
end
end
end
Loading

0 comments on commit 1b7749c

Please sign in to comment.