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 +4 -4
- data/README.md +30 -1
- data/lib/tug/command/command.rb +4 -1
- data/lib/tug/command/ipa_command.rb +3 -3
- data/lib/tug/command/provision_command.rb +15 -0
- data/lib/tug/config/.tug.yml +6 -1
- data/lib/tug/config/config_file.rb +2 -0
- data/lib/tug/interface/interface.rb +19 -9
- data/lib/tug/keychain/keychain.rb +69 -0
- data/lib/tug/version.rb +1 -1
- data/lib/tug.rb +4 -1
- data/spec/build_command_spec.rb +4 -1
- data/spec/command_spec.rb +5 -0
- data/spec/config_file_spec.rb +7 -2
- data/spec/ipa_command_spec.rb +6 -3
- data/spec/keychain_spec.rb +113 -0
- data/spec/output.txt +2 -0
- metadata +6 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a3a19cbd80c7658c71fc5354c84c7703b52b33d6
|
4
|
+
data.tar.gz: 5669abeb191d05076e9a98b6429f7f3462ce887a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
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
|
data/lib/tug/command/command.rb
CHANGED
@@ -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(
|
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)
|
@@ -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
|
data/lib/tug/config/.tug.yml
CHANGED
@@ -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
|
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 =
|
17
|
-
|
18
|
-
|
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,
|
32
|
+
def execute(command, config_file)
|
23
33
|
command = Tug::Command.command_for_string(command)
|
24
|
-
command.execute(
|
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
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"
|
data/spec/build_command_spec.rb
CHANGED
@@ -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(@
|
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
|
data/spec/config_file_spec.rb
CHANGED
@@ -2,8 +2,9 @@ require "spec_helper"
|
|
2
2
|
|
3
3
|
describe Tug::ConfigFile do
|
4
4
|
|
5
|
-
before(:each) do
|
6
|
-
|
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
|
data/spec/ipa_command_spec.rb
CHANGED
@@ -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(@
|
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(@
|
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(@
|
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
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
|
+
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-
|
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
|