tug 0.0.4 → 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 08744a632238e996beb4a29db85fa89e7ee20faf
4
- data.tar.gz: bc0865da0127107943b503ae3fc0a47fd9dbc649
3
+ metadata.gz: a3a19cbd80c7658c71fc5354c84c7703b52b33d6
4
+ data.tar.gz: 5669abeb191d05076e9a98b6429f7f3462ce887a
5
5
  SHA512:
6
- metadata.gz: 5487f7da527020af59fbde33153f96fe9db0b0f7fe91c764ccb6ed590e3306c9c771916f60abcf460a7ad70d61bd86d46804b524535e6306f7d1fbb780d05b4d
7
- data.tar.gz: 55f6d92f1d195674df38b819a81220bf9881303b248572c4310467e277c43cee02888cd141c33c358f24549fc484275f8f34f028dbd326f124c88d30d08bf1f7
6
+ metadata.gz: 49cc50b509c9a4c45de9c77eb501af64c889a026aae9c4ab292f0c1be18249885e82f9dc6f8e52d7ec41d7d656ad2430881dec0888f498daafd9623b058bec10
7
+ data.tar.gz: 102358c25830e6457f3bd5cd91492429da44bee78445690579173829ffe56cd3ee4173cdbe45dbe96fc601b70eea017d82e0ba6ce7a4fdaf608787c5a1f11fe1
data/README.md CHANGED
@@ -33,7 +33,7 @@ Run `tug ipa` from your Xcode projects root directory, see the example config be
33
33
 
34
34
  ### Config
35
35
 
36
- tug will look in the currenty directory for a `.tug.yml` config file by default, use the `--config` option to pass a path to your config file if it's in a different folder.
36
+ tug will look in the current directory for a `.tug.yml` config file by default, use the `--config` option to pass a path to your config file if it's in a different folder.
37
37
 
38
38
  A sample config file:
39
39
 
@@ -45,6 +45,35 @@ project:
45
45
  ipa_config: Release # The configuration to use to build ipas
46
46
  ```
47
47
 
48
+ ### Provisioning
49
+
50
+ Provisioning requires you to export the following files from your keychain and place them within your project directory:
51
+
52
+ * Apple Worldwide Developer Relations Certificate
53
+ * iPhone Distribution Certificate
54
+ * iPhone Distribution Private Key
55
+ * Distribution Provisioning Profile
56
+
57
+ Run `tug provision` to provision a new machine ready for signing ipas, provisioning requires a `keychain` object in the config yaml file to specify the path to the provisioning certificates and profile:
58
+
59
+ ```
60
+ keychain:
61
+ apple_certificate: certs/apple.cer
62
+ distribution_certificate: certs/dist.cer
63
+ distribution_profile: certs/profile.mobileprovision
64
+ private_key: certs/dist.p12
65
+ ```
66
+
67
+ #### Private Key Password
68
+
69
+ If your `.p12` private key requires a password, you can either set the environment variable:
70
+
71
+ `$ export TUG_P12_PASSWORD=yourpassword`
72
+
73
+ or use the `--password` option when running the provision command:
74
+
75
+ `$ tug provision --password yourpassword`
76
+
48
77
  ## Contributing
49
78
 
50
79
  1. Fork it
@@ -8,13 +8,16 @@ module Tug
8
8
  Tug::BuildCommand.new
9
9
  when "ipa"
10
10
  Tug::IpaCommand.new
11
+ when "provision"
12
+ Tug::ProvisionCommand.new
11
13
  else
12
14
  Tug::Command.new
13
15
  end
14
16
  end
15
17
  end
16
18
 
17
- def execute(project)
19
+ def execute(config_file)
20
+ project = config_file.project
18
21
  @xctool = xctool(project.ipa_config)
19
22
  project.schemes.each do |scheme|
20
23
  @xctool.build(project.workspace, scheme)
@@ -1,10 +1,10 @@
1
1
  module Tug
2
2
  class IpaCommand < Command
3
3
 
4
- def execute(project)
4
+ def execute(config_file)
5
5
  super
6
- export_ipa(project)
7
- move_ipa(project)
6
+ export_ipa(config_file.project)
7
+ move_ipa(config_file.project)
8
8
  end
9
9
 
10
10
  private
@@ -0,0 +1,15 @@
1
+ module Tug
2
+ class ProvisionCommand < Command
3
+
4
+ def execute(config_file)
5
+ keychain = config_file.keychain
6
+
7
+ keychain.create_keychain
8
+ keychain.select_keychain(keychain.name)
9
+ keychain.import_apple_certificate
10
+ keychain.import_distribution_certificate
11
+ keychain.import_private_key
12
+ keychain.import_profile
13
+ end
14
+ end
15
+ end
@@ -2,4 +2,9 @@ project:
2
2
  workspace: tug.xcworkspace
3
3
  schemes:
4
4
  - tug
5
- ipa_config: InHouse
5
+ ipa_config: InHouse
6
+ keychain:
7
+ apple_certificate: apple.cer
8
+ distribution_certificate: dist.cer
9
+ distribution_profile: profile.mobileprovision
10
+ private_key: dist.p12
@@ -2,6 +2,7 @@ module Tug
2
2
  class ConfigFile
3
3
 
4
4
  attr_reader :project
5
+ attr_reader :keychain
5
6
 
6
7
  class << self
7
8
  def config_file(path=default_path)
@@ -16,6 +17,7 @@ module Tug
16
17
  def initialize(path)
17
18
  config = YAML::load_file(path)
18
19
  @project = Tug::Project.new(config['project'])
20
+ @keychain = Tug::Keychain.keychain(config['keychain'])
19
21
  end
20
22
 
21
23
  private
@@ -2,26 +2,36 @@ module Tug
2
2
  class Interface < Thor
3
3
 
4
4
  desc "build", "build a project"
5
- option :config, :default => "#{Dir.pwd}/.tug.yml"
5
+ option :config, :default => "#{Dir.pwd}/.tug.yml", :aliases => "-c"
6
6
  def build
7
7
  config_file = Tug::ConfigFile.config_file(options[:config])
8
- execute(__method__.to_s, config_file.project)
8
+ execute(__method__.to_s, config_file)
9
9
  end
10
10
 
11
11
  desc "ipa", "generate an ipa"
12
- option :config, :default => "#{Dir.pwd}/.tug.yml"
13
- option :export, :default => "#{Dir.pwd}"
12
+ option :config, :default => "#{Dir.pwd}/.tug.yml", :aliases => "-c"
13
+ option :export, :default => "#{Dir.pwd}", :aliases => "-e"
14
14
  def ipa
15
15
  config_file = Tug::ConfigFile.config_file(options[:config])
16
- project = config_file.project
17
- project.ipa_export_path = options[:export]
18
- execute(__method__.to_s, project)
16
+ config_file.project.ipa_export_path = options[:export]
17
+ execute(__method__.to_s, config_file)
18
+ end
19
+
20
+ desc "provision", "provision system distrubution certificates and provisioning profile"
21
+ option :config, :default => "#{Dir.pwd}/.tug.yml", :aliases => "-c"
22
+ option :keychain, :default => "tug", :aliases => "-k"
23
+ option :password, :aliases => "-p"
24
+ def provision
25
+ config_file = Tug::ConfigFile.config_file(options[:config])
26
+ config_file.keychain.name = options[:keychain]
27
+ config_file.keychain.private_key_password = options[:password]
28
+ execute(__method__.to_s, config_file)
19
29
  end
20
30
 
21
31
  no_commands do
22
- def execute(command, project)
32
+ def execute(command, config_file)
23
33
  command = Tug::Command.command_for_string(command)
24
- command.execute(project)
34
+ command.execute(config_file)
25
35
  end
26
36
  end
27
37
  end
@@ -0,0 +1,69 @@
1
+ module Tug
2
+ class Keychain
3
+
4
+ attr_reader :apple_certificate
5
+ attr_reader :distribution_certificate
6
+ attr_reader :distribution_profile
7
+ attr_reader :private_key
8
+ attr_accessor :private_key_password
9
+ attr_accessor :name
10
+
11
+ class << self
12
+ def keychain(keychain_yaml)
13
+ Tug::Keychain.new(keychain_yaml)
14
+ end
15
+ end
16
+
17
+ def initialize(keychain_yaml)
18
+ @apple_certificate = keychain_yaml["apple_certificate"]
19
+ @distribution_certificate = keychain_yaml["distribution_certificate"]
20
+ @distribution_profile = keychain_yaml["distribution_profile"]
21
+ @private_key = keychain_yaml["private_key"]
22
+ @private_key_password = ENV['TUG_P12_PASSWORD']
23
+ @name = "tug"
24
+ end
25
+
26
+ def create_keychain
27
+ system("security create-keychain -p tug #{name}.keychain")
28
+ end
29
+
30
+ def select_keychain(keychain_name=name)
31
+ system("security default-keychain -s #{keychain_name}.keychain")
32
+ end
33
+
34
+ def delete_keychain
35
+ system("security delete-keychain #{name}.keychain")
36
+ end
37
+
38
+ def import_apple_certificate
39
+ system(import_command(apple_certificate))
40
+ end
41
+
42
+ def import_distribution_certificate
43
+ system(import_command(distribution_certificate))
44
+ end
45
+
46
+ def import_private_key
47
+ system(import_command(private_key) + " -P '#{private_key_password}'")
48
+ end
49
+
50
+ def import_profile
51
+ FileUtils.mkdir_p "#{File.expand_path('~')}/Library/MobileDevice/Provisioning\ Profiles/"
52
+ system("cp #{distribution_profile} #{profile_export_path}")
53
+ end
54
+
55
+ private
56
+
57
+ def profile_export_path
58
+ "#{File.expand_path('~')}/Library/MobileDevice/Provisioning\\ Profiles/"
59
+ end
60
+
61
+ def import_command(file)
62
+ "security import #{file} -k #{keychain_path} -T /usr/bin/codesign"
63
+ end
64
+
65
+ def keychain_path
66
+ "#{File.expand_path('~')}/Library/Keychains/#{name}.keychain"
67
+ end
68
+ end
69
+ end
data/lib/tug/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Tug
2
- VERSION = "0.0.4"
2
+ VERSION = "0.0.5"
3
3
  end
data/lib/tug.rb CHANGED
@@ -7,6 +7,7 @@ require "tug/version"
7
7
  require "tug/command/command"
8
8
  require "tug/command/build_command"
9
9
  require "tug/command/ipa_command"
10
+ require "tug/command/provision_command"
10
11
 
11
12
  require "tug/interface/interface"
12
13
 
@@ -18,4 +19,6 @@ require "tug/project/project"
18
19
  require "tug/tool/xcode_build"
19
20
  require "tug/tool/xctool"
20
21
  require "tug/tool/xctool_build"
21
- require "tug/tool/xctool_archive"
22
+ require "tug/tool/xctool_archive"
23
+
24
+ require "tug/keychain/keychain"
@@ -8,11 +8,14 @@ describe Tug::BuildCommand do
8
8
  @command = Tug::BuildCommand.new
9
9
  allow(@command).to receive(:system)
10
10
  @project = Tug::Project.new(project_yaml)
11
+
12
+ @config = double(Tug::ConfigFile)
13
+ allow(@config).to receive(:project).and_return(@project)
11
14
  end
12
15
 
13
16
  it "should build using xctool" do
14
17
  expect_any_instance_of(Tug::XCTool).to receive(:system).with("xctool -workspace workspace -scheme scheme -configuration Debug -sdk iphonesimulator")
15
- @command.execute(@project)
18
+ @command.execute(@config)
16
19
  end
17
20
  end
18
21
  end
data/spec/command_spec.rb CHANGED
@@ -21,5 +21,10 @@ describe Tug::Command do
21
21
  command = Tug::Command.command_for_string("hello")
22
22
  expect(command).to be_kind_of(Tug::Command)
23
23
  end
24
+
25
+ it "should return a provision command" do
26
+ command = Tug::Command.command_for_string("provision")
27
+ expect(command).to be_kind_of(Tug::ProvisionCommand)
28
+ end
24
29
  end
25
30
  end
@@ -2,8 +2,9 @@ require "spec_helper"
2
2
 
3
3
  describe Tug::ConfigFile do
4
4
 
5
- before(:each) do
6
- config = {'project' => {'workspace' => 'hello', 'schemes' => ["world"], 'ipa_config' => 'config'}}
5
+ before(:each) do
6
+ file = File.expand_path(File.join(File.dirname(__FILE__), "../lib/tug/config/.tug.yml"))
7
+ config = YAML.load_file(file)
7
8
  allow(YAML).to receive(:load_file).and_return(config)
8
9
  @config_file = Tug::ConfigFile.new("path")
9
10
  end
@@ -27,5 +28,9 @@ describe Tug::ConfigFile do
27
28
  it "should load a project" do
28
29
  expect(@config_file.project).to be
29
30
  end
31
+
32
+ it "should load a keychain" do
33
+ expect(@config_file.keychain).to be
34
+ end
30
35
  end
31
36
  end
@@ -12,22 +12,25 @@ describe Tug::IpaCommand do
12
12
  yaml = project_yaml
13
13
  yaml["ipa_config"] = "InHouse"
14
14
  @project = Tug::Project.new(yaml)
15
+
16
+ @config = double(Tug::ConfigFile)
17
+ allow(@config).to receive(:project).and_return(@project)
15
18
  end
16
19
 
17
20
  it "should generate an archive using xctool" do
18
21
  expect_any_instance_of(Tug::XCTool).to receive(:system).with("xctool -workspace workspace -scheme scheme -configuration InHouse archive -archivePath /tmp/scheme.xcarchive")
19
- @command.execute(@project)
22
+ @command.execute(@config)
20
23
  end
21
24
 
22
25
  it "should export an ipa using xcode build" do
23
26
  expect_any_instance_of(Tug::XcodeBuild).to receive(:system).with("xcodebuild -archivePath /tmp/scheme.xcarchive -exportPath /tmp/scheme.ipa -exportFormat ipa -exportArchive -exportWithOriginalSigningIdentity")
24
- @command.execute(@project)
27
+ @command.execute(@config)
25
28
  end
26
29
 
27
30
  it "should move the ipa file into the export path location" do
28
31
  @project.ipa_export_path = "/hello/world"
29
32
  expect(FileUtils).to receive(:mv).with(anything, /hello\/world/)
30
- @command.execute(@project)
33
+ @command.execute(@config)
31
34
  end
32
35
  end
33
36
  end
@@ -0,0 +1,113 @@
1
+ require "spec_helper"
2
+
3
+ describe Tug::Keychain do
4
+
5
+ before(:each) do
6
+ @yaml = {"apple_certificate" => "apple",
7
+ "distribution_certificate" => "dist",
8
+ "distribution_profile" => "path/to/profile",
9
+ "private_key" => "private"}
10
+
11
+ @keychain = Tug::Keychain.keychain(@yaml)
12
+ allow(@keychain).to receive(:system)
13
+ end
14
+
15
+ describe "when returning keychains" do
16
+ it "should return a keychian" do
17
+ end
18
+
19
+ it "should return a protected keychain if password is missing" do
20
+ end
21
+ end
22
+
23
+ describe "when created" do
24
+ it "should have a apple certificate" do
25
+ expect(@keychain.apple_certificate).to be
26
+ end
27
+
28
+ it "should have a distribution certificate" do
29
+ expect(@keychain.distribution_certificate).to be
30
+ end
31
+
32
+ it "should have a distribution profile" do
33
+ expect(@keychain.distribution_profile).to be
34
+ end
35
+
36
+ it "should have a private key" do
37
+ expect(@keychain.private_key).to be
38
+ end
39
+
40
+ it "should have a default keychain name" do
41
+ expect(@keychain.name).to match("tug")
42
+ end
43
+ end
44
+
45
+ describe "when importing certificates" do
46
+
47
+ it "should select a keychain" do
48
+ expect(@keychain).to receive(:system).with("security default-keychain -s test.keychain")
49
+ @keychain.select_keychain("test")
50
+ end
51
+
52
+ it "should create a keychain" do
53
+ expect(@keychain).to receive(:system).with("security create-keychain -p tug tug.keychain")
54
+ @keychain.create_keychain
55
+ end
56
+
57
+ it "should delete a keychain" do
58
+ expect(@keychain).to receive(:system).with("security delete-keychain tug.keychain")
59
+ @keychain.delete_keychain
60
+ end
61
+
62
+ it "should import the apple certificate" do
63
+ expect(@keychain).to receive(:system).with("security import apple -k #{File.expand_path('~')}/Library/Keychains/tug.keychain -T /usr/bin/codesign")
64
+ @keychain.import_apple_certificate
65
+ end
66
+
67
+ it "should import the dist certificate" do
68
+ expect(@keychain).to receive(:system).with("security import dist -k #{File.expand_path('~')}/Library/Keychains/tug.keychain -T /usr/bin/codesign")
69
+ @keychain.import_distribution_certificate
70
+ end
71
+
72
+ it "should import the private key" do
73
+ ENV['TUG_P12_PASSWORD'] = nil
74
+ @keychain = Tug::Keychain.keychain(@yaml)
75
+
76
+ expect(@keychain).to receive(:system).with("security import private -k #{File.expand_path('~')}/Library/Keychains/tug.keychain -T /usr/bin/codesign -P ''")
77
+ @keychain.import_private_key
78
+ end
79
+
80
+ it "should import the private key with a password via env var" do
81
+ ENV['TUG_P12_PASSWORD'] = "password"
82
+ @keychain = Tug::Keychain.keychain(@yaml)
83
+
84
+ expect(@keychain).to receive(:system).with("security import private -k #{File.expand_path('~')}/Library/Keychains/tug.keychain -T /usr/bin/codesign -P 'password'")
85
+ @keychain.import_private_key
86
+ end
87
+
88
+ it "should import the private key with a password via setter" do
89
+ @keychain = Tug::Keychain.keychain(@yaml)
90
+ @keychain.private_key_password = "hello"
91
+
92
+ expect(@keychain).to receive(:system).with("security import private -k #{File.expand_path('~')}/Library/Keychains/tug.keychain -T /usr/bin/codesign -P 'hello'")
93
+ @keychain.import_private_key
94
+ end
95
+ end
96
+
97
+ describe "when importing profiles" do
98
+
99
+ before(:each) do
100
+ allow(FileUtils).to receive(:mkdir_p)
101
+ end
102
+
103
+ it "should create a profile folder" do
104
+ expect(FileUtils).to receive(:mkdir_p).with("#{File.expand_path('~')}/Library/MobileDevice/Provisioning\ Profiles/")
105
+ @keychain.import_profile
106
+ end
107
+
108
+ it "should import the dist profile" do
109
+ expect(@keychain).to receive(:system).with("cp path/to/profile #{File.expand_path('~')}/Library/MobileDevice/Provisioning\\ Profiles/")
110
+ @keychain.import_profile
111
+ end
112
+ end
113
+ end
data/spec/output.txt CHANGED
@@ -0,0 +1,2 @@
1
+ Config file missing:
2
+ Try specifying a path to your config file with the --config option
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tug
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.4
4
+ version: 0.0.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alex Fish
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-07-28 00:00:00.000000000 Z
11
+ date: 2014-07-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: thor
@@ -102,10 +102,12 @@ files:
102
102
  - lib/tug/command/build_command.rb
103
103
  - lib/tug/command/command.rb
104
104
  - lib/tug/command/ipa_command.rb
105
+ - lib/tug/command/provision_command.rb
105
106
  - lib/tug/config/.tug.yml
106
107
  - lib/tug/config/config_file.rb
107
108
  - lib/tug/config/missing_config_file.rb
108
109
  - lib/tug/interface/interface.rb
110
+ - lib/tug/keychain/keychain.rb
109
111
  - lib/tug/project/project.rb
110
112
  - lib/tug/tool/xcode_build.rb
111
113
  - lib/tug/tool/xctool.rb
@@ -116,6 +118,7 @@ files:
116
118
  - spec/command_spec.rb
117
119
  - spec/config_file_spec.rb
118
120
  - spec/ipa_command_spec.rb
121
+ - spec/keychain_spec.rb
119
122
  - spec/output.txt
120
123
  - spec/project_spec.rb
121
124
  - spec/spec_helper.rb
@@ -150,6 +153,7 @@ test_files:
150
153
  - spec/command_spec.rb
151
154
  - spec/config_file_spec.rb
152
155
  - spec/ipa_command_spec.rb
156
+ - spec/keychain_spec.rb
153
157
  - spec/output.txt
154
158
  - spec/project_spec.rb
155
159
  - spec/spec_helper.rb