tug 0.0.4 → 0.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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