fastlane 0.1.14 → 0.1.15
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 +4 -4
- data/README.md +50 -11
- data/bin/fastlane +3 -1
- data/lib/assets/AppfileTemplate +2 -2
- data/lib/assets/s3_html_template.erb +95 -0
- data/lib/assets/s3_plist_template.erb +31 -0
- data/lib/fastlane/actions/actions_helper.rb +1 -0
- data/lib/fastlane/actions/ipa.rb +4 -3
- data/lib/fastlane/actions/s3.rb +253 -0
- data/lib/fastlane/actions/xcode_select.rb +36 -0
- data/lib/fastlane/lane_manager.rb +16 -1
- data/lib/fastlane/runner.rb +8 -4
- data/lib/fastlane/version.rb +1 -1
- metadata +23 -5
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 4cf49747a65532a0365929aac350ddc4d83fb3ef
|
|
4
|
+
data.tar.gz: bc014b7a2ee5efcc065badd01ba5dce623865c58
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: f66ed5624c0586988e3a4fadf11d23f964533e814174dae6409802a1eaa9e4169fb9ddff13e1a25842db1f6753fa1ead933bcd7fddea866d58b19ca7a52f50a7
|
|
7
|
+
data.tar.gz: dcb38d4d4b7d383ceb34c64d0238fa9d21671e397f286b4e4fdd0493c19ca4cf621de12d5ba8e342e0560b85cfd468c341863fd6b5f9dc27d5dddf24cf8acd24
|
data/README.md
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
<a href="https://github.com/KrauseFx/frameit">frameit</a> •
|
|
8
8
|
<a href="https://github.com/KrauseFx/PEM">PEM</a> •
|
|
9
9
|
<a href="https://github.com/KrauseFx/sigh">sigh</a> •
|
|
10
|
-
<a href="https://github.com/KrauseFx/produce">produce</a> •
|
|
10
|
+
<a href="https://github.com/KrauseFx/produce">produce</a> •
|
|
11
11
|
<a href="https://github.com/KrauseFx/cert">cert</a> •
|
|
12
12
|
<a href="https://github.com/KrauseFx/codes">codes</a>
|
|
13
13
|
</p>
|
|
@@ -121,6 +121,20 @@ fastlane appstore
|
|
|
121
121
|
|
|
122
122
|
When one command fails, the execution will be aborted.
|
|
123
123
|
|
|
124
|
+
### Environment Variables
|
|
125
|
+
You can define environment variables in a `.env` or `.env.default` file in the same directory as your `Fastfile`. Environment variables are loading used [dotenv](https://github.com/bkeepers/dotenv)
|
|
126
|
+
|
|
127
|
+
#### Example using `dotenv`
|
|
128
|
+
**Filename:** .env
|
|
129
|
+
```
|
|
130
|
+
WORKSPACE=YourApp.xcworkspace
|
|
131
|
+
HOCKEYAPP_API_TOKEN=your-hockey-api-token
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
#### Environment specific `dotenv` variables
|
|
135
|
+
`fastlane` also has a `--env` option that allows loading of environment specific `dotenv` files. `.env` and `.env.default` will be loaded before environment specific `dotenv` files are loaded. The naming convention for environment specific `dotenv` files is `.env.<environment>`
|
|
136
|
+
|
|
137
|
+
**Example:** `fastlane <lane-name> --env development` will load `.env`, `.env.default`, and `.env.development`
|
|
124
138
|
|
|
125
139
|
### Actions
|
|
126
140
|
There are some predefined actions you can use. If you have ideas for more, please let me know.
|
|
@@ -201,7 +215,7 @@ ipa({
|
|
|
201
215
|
})
|
|
202
216
|
```
|
|
203
217
|
|
|
204
|
-
The `ipa` action uses [shenzhen](https://github.com/nomad/shenzhen) under the hood.
|
|
218
|
+
The `ipa` action uses [shenzhen](https://github.com/nomad/shenzhen) under the hood.
|
|
205
219
|
|
|
206
220
|
The path to the `ipa` is automatically used by `Crashlytics`, `Hockey` and `DeployGate`. To also use it in `deliver` update your `Deliverfile`:
|
|
207
221
|
|
|
@@ -268,6 +282,29 @@ crashlytics({
|
|
|
268
282
|
```
|
|
269
283
|
Additionally you can specify `notes_path`, `emails` and `groups`.
|
|
270
284
|
|
|
285
|
+
#### AWS S3 Distribution
|
|
286
|
+
|
|
287
|
+
Add the `s3` action after the `ipa` step:
|
|
288
|
+
|
|
289
|
+
```ruby
|
|
290
|
+
s3
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
You can also customize a lot of options:
|
|
294
|
+
```ruby
|
|
295
|
+
s3({
|
|
296
|
+
# All of these are used to make Shenzhen's `ipa distribute:s3` command
|
|
297
|
+
access_key: ENV['S3_ACCESS_KEY'], # Required from user
|
|
298
|
+
secret_access_key: ENV['S3_SECRET_ACCESS_KEY'], # Required from user
|
|
299
|
+
bucket: ENV['S3_BUCKET'], # Required from user
|
|
300
|
+
file: 'AppName.ipa', # This would come from IpaAction
|
|
301
|
+
dsym: 'AppName.app.dSYM.zip', # This would come from IpaAction
|
|
302
|
+
path: 'v{CFBundleShortVersionString}_b{CFBundleVersion}/' # This is actually the default
|
|
303
|
+
})
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
It is recommended to **not** store the AWS access keys in the `Fastfile`.
|
|
307
|
+
|
|
271
308
|
#### [DeployGate](https://deploygate.com/)
|
|
272
309
|
|
|
273
310
|
You can retrieve your username and API token on [your settings page](https://deploygate.com/settings).
|
|
@@ -343,6 +380,13 @@ gcovr({
|
|
|
343
380
|
})
|
|
344
381
|
```
|
|
345
382
|
|
|
383
|
+
#### [xcode_select](https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man1/xcode-select.1.html)
|
|
384
|
+
Use this command if you are supporting multiple versions of Xcode
|
|
385
|
+
|
|
386
|
+
```ruby
|
|
387
|
+
xcode_select "/Applications/Xcode6.1.app"
|
|
388
|
+
```
|
|
389
|
+
|
|
346
390
|
#### Custom Shell Scripts
|
|
347
391
|
```ruby
|
|
348
392
|
sh "./your_bash_script.sh"
|
|
@@ -352,7 +396,7 @@ sh "./your_bash_script.sh"
|
|
|
352
396
|
This block will get executed *before* running the requested lane. It supports the same actions as lanes.
|
|
353
397
|
|
|
354
398
|
```ruby
|
|
355
|
-
before_all do
|
|
399
|
+
before_all do |lane|
|
|
356
400
|
cocoapods
|
|
357
401
|
end
|
|
358
402
|
```
|
|
@@ -476,6 +520,7 @@ Available variables (put that inside the square brackets of the above snippet)
|
|
|
476
520
|
```ruby
|
|
477
521
|
Actions::SharedValues::BUILD_NUMBER # generated by `increment_build_number`
|
|
478
522
|
Actions::SharedValues::SNAPSHOT_SCREENSHOTS_PATH # generated by `snapshot`
|
|
523
|
+
Actions::SharedValues::PRODUCE_APPLE_ID # the Apple ID of the newly created app
|
|
479
524
|
Actions::SharedValues::IPA_OUTPUT_PATH # generated by `ipa`
|
|
480
525
|
Actions::SharedValues::SIGH_PROFILE_PATH # generated by `sigh`
|
|
481
526
|
Actions::SharedValues::SIGH_UDID # the UDID of the generated provisioning profile
|
|
@@ -487,14 +532,14 @@ Actions::SharedValues::DEPLOYGATE_APP_INFO # Hash, generated by `deploygate`
|
|
|
487
532
|
|
|
488
533
|
#### Complex Fastfile Example
|
|
489
534
|
```ruby
|
|
490
|
-
before_all do
|
|
535
|
+
before_all do |lane|
|
|
491
536
|
ENV["SLACK_URL"] = "https://hooks.slack.com/services/..."
|
|
492
537
|
team_id "Q2CBPK58CA"
|
|
493
538
|
|
|
494
539
|
increment_build_number
|
|
495
540
|
cocoapods
|
|
496
541
|
xctool :test
|
|
497
|
-
|
|
542
|
+
|
|
498
543
|
ipa({
|
|
499
544
|
workspace: "MyApp.xcworkspace"
|
|
500
545
|
})
|
|
@@ -565,12 +610,6 @@ Keep in mind the ```before_all``` and ```after_all``` block will be executed for
|
|
|
565
610
|
#### Hide the `fastlane` folder
|
|
566
611
|
Just rename the folder to `.fastlane` in case you don't want it to be visible in the Finder.
|
|
567
612
|
|
|
568
|
-
#### Select Xcode version (e.g. Beta Version)
|
|
569
|
-
If you want to use a Beta Xcode installation, you can add this to your `before_all` block.
|
|
570
|
-
```
|
|
571
|
-
ENV['DEVELOPER_DIR'] = '/Applications/Xcode-Beta6.3.app/Contents/Developer'
|
|
572
|
-
```
|
|
573
|
-
|
|
574
613
|
#### Load own actions from external folder
|
|
575
614
|
Add this to the top of your `Fastfile` (*.* is the `fastlane` folder)
|
|
576
615
|
```ruby
|
data/bin/fastlane
CHANGED
|
@@ -4,6 +4,7 @@ $LOAD_PATH.push File.expand_path('../../lib', __FILE__)
|
|
|
4
4
|
|
|
5
5
|
require 'fastlane'
|
|
6
6
|
require 'commander'
|
|
7
|
+
require 'dotenv'
|
|
7
8
|
require 'fastlane/new_action'
|
|
8
9
|
|
|
9
10
|
HighLine.track_eof = false
|
|
@@ -24,10 +25,11 @@ class FastlaneApplication
|
|
|
24
25
|
command :run do |c|
|
|
25
26
|
c.syntax = 'fastlane run [lane]'
|
|
26
27
|
c.description = 'Drive the fastlane for a specific environment.'
|
|
28
|
+
c.option '--env STRING', String, 'Add environment to use with `dotenv`'
|
|
27
29
|
|
|
28
30
|
c.action do |args, _options|
|
|
29
31
|
if Fastlane::FastlaneFolder.path
|
|
30
|
-
Fastlane::LaneManager.cruise_lanes(args)
|
|
32
|
+
Fastlane::LaneManager.cruise_lanes(args, _options.env)
|
|
31
33
|
else
|
|
32
34
|
create = agree('Could not find fastlane in current directory. Would you like to set it up? (y/n)'.yellow, true)
|
|
33
35
|
Fastlane::Setup.new.run if create
|
data/lib/assets/AppfileTemplate
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
app_identifier "[[APP_IDENTIFIER]]"
|
|
2
|
-
apple_id "[[APPLE_ID]]"
|
|
1
|
+
app_identifier "[[APP_IDENTIFIER]]" # The bundle identifier of your app
|
|
2
|
+
apple_id "[[APPLE_ID]]" # Your Apple email address
|
|
3
3
|
|
|
4
4
|
# You can uncomment the lines below and add your own
|
|
5
5
|
# team selection in case you're in multiple teams
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
<html>
|
|
2
|
+
<head>
|
|
3
|
+
<meta charset="utf-8">
|
|
4
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
|
|
5
|
+
<title>Install <%= title %></title>
|
|
6
|
+
</head>
|
|
7
|
+
<body>
|
|
8
|
+
<style type="text/css">
|
|
9
|
+
* {
|
|
10
|
+
font-family: "Helvetica Neue",Helvetica,Arial,sans-serif;
|
|
11
|
+
text-align: center;
|
|
12
|
+
background-color: #f5f5f5;
|
|
13
|
+
}
|
|
14
|
+
.oneRow {
|
|
15
|
+
width: 100%;
|
|
16
|
+
overflow: auto;
|
|
17
|
+
overflow-y: hidden;
|
|
18
|
+
white-space: nowrap;
|
|
19
|
+
text-align: center;
|
|
20
|
+
}
|
|
21
|
+
.download {
|
|
22
|
+
margin: 30px;
|
|
23
|
+
font-size: 130%;
|
|
24
|
+
}
|
|
25
|
+
#appIcon {
|
|
26
|
+
-webkit-border-radius: 22.544%;
|
|
27
|
+
-moz-border-radius: 22.544%;
|
|
28
|
+
-ms-border-radius: 22.544%;
|
|
29
|
+
border-radius: 22.544%;
|
|
30
|
+
|
|
31
|
+
margin-bottom: 30px;
|
|
32
|
+
}
|
|
33
|
+
a {
|
|
34
|
+
text-decoration: none;
|
|
35
|
+
color: blue;
|
|
36
|
+
}
|
|
37
|
+
a:hover {
|
|
38
|
+
text-decoration: underline;
|
|
39
|
+
}
|
|
40
|
+
#footnote {
|
|
41
|
+
color: #737373;
|
|
42
|
+
font-size: 14px;
|
|
43
|
+
}
|
|
44
|
+
#finished { display: none; }
|
|
45
|
+
#fastlaneLogo {
|
|
46
|
+
text-align: center;
|
|
47
|
+
max-width: 150px;
|
|
48
|
+
margin-top: 10px;
|
|
49
|
+
}
|
|
50
|
+
</style>
|
|
51
|
+
|
|
52
|
+
<h1 style="text-align: center;"><%= title %></h1>
|
|
53
|
+
<!-- <img src="app_icon.png" id="appIcon"> -->
|
|
54
|
+
|
|
55
|
+
<div class="oneRow">
|
|
56
|
+
<span class="download" id="ios">
|
|
57
|
+
<a href="itms-services://?action=download-manifest&url=itms-services://?action=download-manifest&url=<%= url %>" id="text" class="btn btn-lg btn-default" onclick="document.getElementById('finished').id = '';">
|
|
58
|
+
Install <%= title %> <%= bundle_version %>
|
|
59
|
+
</a>
|
|
60
|
+
</span>
|
|
61
|
+
|
|
62
|
+
<!-- <span class="download" id="android">
|
|
63
|
+
</span> -->
|
|
64
|
+
</div>
|
|
65
|
+
|
|
66
|
+
<h3 id="desktop">Please open this page on your iPhone!</h3>
|
|
67
|
+
|
|
68
|
+
<p id="finished">
|
|
69
|
+
App is being installed. Close Safari using the home button.
|
|
70
|
+
</p>
|
|
71
|
+
|
|
72
|
+
<p id="footnote">
|
|
73
|
+
This is a beta version and is not meant to share with the public.
|
|
74
|
+
</p>
|
|
75
|
+
<img src="https://s3-eu-west-1.amazonaws.com/fastlane.tools/fastlane_medium.png" id="fastlaneLogo" />
|
|
76
|
+
</body>
|
|
77
|
+
|
|
78
|
+
<script type='text/javascript'>
|
|
79
|
+
// if (/Android/i.test(navigator.userAgent))
|
|
80
|
+
// {
|
|
81
|
+
// document.getElementById("ios").remove()
|
|
82
|
+
// document.getElementById("desktop").remove()
|
|
83
|
+
// }
|
|
84
|
+
if (/iPhone|iPad|iPod/i.test(navigator.userAgent))
|
|
85
|
+
{
|
|
86
|
+
// document.getElementById("android").remove()
|
|
87
|
+
document.getElementById("desktop").remove()
|
|
88
|
+
}
|
|
89
|
+
else
|
|
90
|
+
{
|
|
91
|
+
document.getElementById("ios").remove()
|
|
92
|
+
// document.getElementById("android").remove()
|
|
93
|
+
}
|
|
94
|
+
</script>
|
|
95
|
+
</html>
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
3
|
+
<plist version="1.0">
|
|
4
|
+
<dict>
|
|
5
|
+
<key>items</key>
|
|
6
|
+
<array>
|
|
7
|
+
<dict>
|
|
8
|
+
<key>assets</key>
|
|
9
|
+
<array>
|
|
10
|
+
<dict>
|
|
11
|
+
<key>kind</key>
|
|
12
|
+
<string>software-package</string>
|
|
13
|
+
<key>url</key>
|
|
14
|
+
<string><%= url %></string>
|
|
15
|
+
</dict>
|
|
16
|
+
</array>
|
|
17
|
+
<key>metadata</key>
|
|
18
|
+
<dict>
|
|
19
|
+
<key>bundle-identifier</key>
|
|
20
|
+
<string><%= bundle_id %></string>
|
|
21
|
+
<key>bundle-version</key>
|
|
22
|
+
<string><%= bundle_version %></string>
|
|
23
|
+
<key>kind</key>
|
|
24
|
+
<string>software</string>
|
|
25
|
+
<key>title</key>
|
|
26
|
+
<string><%= title %></string>
|
|
27
|
+
</dict>
|
|
28
|
+
</dict>
|
|
29
|
+
</array>
|
|
30
|
+
</dict>
|
|
31
|
+
</plist>
|
data/lib/fastlane/actions/ipa.rb
CHANGED
|
@@ -30,7 +30,8 @@ module Fastlane
|
|
|
30
30
|
embed: '-m',
|
|
31
31
|
identity: '-i',
|
|
32
32
|
sdk: '--sdk',
|
|
33
|
-
ipa: '--ipa'
|
|
33
|
+
ipa: '--ipa',
|
|
34
|
+
verbose: '--verbose'
|
|
34
35
|
}
|
|
35
36
|
|
|
36
37
|
class IpaAction
|
|
@@ -84,8 +85,8 @@ module Fastlane
|
|
|
84
85
|
end
|
|
85
86
|
|
|
86
87
|
def self.params_to_build_args(params)
|
|
87
|
-
# Remove nil value params unless :clean or :archive
|
|
88
|
-
params = params.delete_if { |k, v| (k != :clean && k != :archive) && v.nil? }
|
|
88
|
+
# Remove nil value params unless :clean or :archive or :verbose
|
|
89
|
+
params = params.delete_if { |k, v| (k != :clean && k != :archive && k != :verbose) && v.nil? }
|
|
89
90
|
|
|
90
91
|
# Maps nice developer param names to Shenzhen's `ipa build` arguments
|
|
91
92
|
params.collect do |k, v|
|
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
require 'erb'
|
|
2
|
+
require 'ostruct'
|
|
3
|
+
require 'shenzhen'
|
|
4
|
+
|
|
5
|
+
module Fastlane
|
|
6
|
+
module Actions
|
|
7
|
+
|
|
8
|
+
module SharedValues
|
|
9
|
+
S3_IPA_OUTPUT_PATH = :S3_IPA_OUTPUT_PATH
|
|
10
|
+
S3_DSYM_OUTPUT_PATH = :S3_DSYM_OUTPUT_PATH
|
|
11
|
+
S3_PLIST_OUTPUT_PATH = :S3_PLIST_OUTPUT_PATH
|
|
12
|
+
S3_HTML_OUTPUT_PATH = :S3_HTML_OUTPUT_PATH
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
# -f, --file FILE .ipa file for the build
|
|
16
|
+
# -d, --dsym FILE zipped .dsym package for the build
|
|
17
|
+
# -a, --access-key-id ACCESS_KEY_ID AWS Access Key ID
|
|
18
|
+
# -s, --secret-access-key SECRET_ACCESS_KEY AWS Secret Access Key
|
|
19
|
+
# -b, --bucket BUCKET S3 bucket
|
|
20
|
+
# --[no-]create Create bucket if it doesn't already exist
|
|
21
|
+
# -r, --region REGION Optional AWS region (for bucket creation)
|
|
22
|
+
# --acl ACL Uploaded object permissions e.g public_read (default), private, public_read_write, authenticated_read
|
|
23
|
+
# --source-dir SOURCE Optional source directory e.g. ./build
|
|
24
|
+
# -P, --path PATH S3 'path'. Values from Info.plist will be substituded for keys wrapped in {}
|
|
25
|
+
# eg. "/path/to/folder/{CFBundleVersion}/" could be evaluated as "/path/to/folder/1.0.0/"
|
|
26
|
+
|
|
27
|
+
S3_ARGS_MAP = {
|
|
28
|
+
ipa: '-f',
|
|
29
|
+
dsym: '-d',
|
|
30
|
+
access_key: '-a',
|
|
31
|
+
secret_access_key: '-s',
|
|
32
|
+
bucket: '-b',
|
|
33
|
+
region: '-r',
|
|
34
|
+
acl: '--acl',
|
|
35
|
+
source: '--source-dir',
|
|
36
|
+
path: '-P',
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
class S3Action
|
|
40
|
+
def self.run(params)
|
|
41
|
+
|
|
42
|
+
params[0] ||= {}
|
|
43
|
+
unless params.first.is_a?Hash
|
|
44
|
+
raise "Please pass the required information to the s3 action."
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Other things that we need
|
|
48
|
+
params = params.first
|
|
49
|
+
|
|
50
|
+
params[:access_key] ||= ENV['S3_ACCESS_KEY'] || ENV['AWS_ACCESS_KEY_ID']
|
|
51
|
+
params[:secret_access_key] ||= ENV['S3_SECRET_ACCESS_KEY'] || ENV['AWS_SECRET_ACCESS_KEY']
|
|
52
|
+
params[:bucket] ||= ENV['S3_BUCKET'] || ENV['AWS_BUCKET_NAME']
|
|
53
|
+
params[:region] ||= ENV['S3_REGION'] || ENV['AWS_REGION']
|
|
54
|
+
params[:ipa] ||= Actions.lane_context[SharedValues::IPA_OUTPUT_PATH]
|
|
55
|
+
params[:dsym] ||= Actions.lane_context[SharedValues::DSYM_OUTPUT_PATH]
|
|
56
|
+
params[:path] ||= 'v{CFBundleShortVersionString}_b{CFBundleVersion}/'
|
|
57
|
+
|
|
58
|
+
# Maps nice developer build parameters to Shenzhen args
|
|
59
|
+
build_args = params_to_build_args(params)
|
|
60
|
+
|
|
61
|
+
# Pulling parameters for other uses
|
|
62
|
+
s3_subdomain = params[:region] ? "s3-#{params[:region]}" : "s3"
|
|
63
|
+
s3_access_key = params[:access_key]
|
|
64
|
+
s3_secret_access_key = params[:secret_access_key]
|
|
65
|
+
s3_bucket = params[:bucket]
|
|
66
|
+
ipa_file = params[:ipa]
|
|
67
|
+
dsym_file = params[:dsym]
|
|
68
|
+
s3_path = params[:path]
|
|
69
|
+
|
|
70
|
+
raise "No S3 access key given, pass using `access_key: 'key'`".red unless s3_access_key.to_s.length > 0
|
|
71
|
+
raise "No S3 secret access key given, pass using `secret_access_key: 'secret key'`".red unless s3_secret_access_key.to_s.length > 0
|
|
72
|
+
raise "No S3 bucket given, pass using `bucket: 'bucket'`".red unless s3_bucket.to_s.length > 0
|
|
73
|
+
raise "No IPA file path given, pass using `ipa: 'ipa path'`".red unless ipa_file.to_s.length > 0
|
|
74
|
+
|
|
75
|
+
plist_template_path = params[:plist_template_path]
|
|
76
|
+
html_template_path = params[:html_template_path]
|
|
77
|
+
html_file_name = params[:html_file_name]
|
|
78
|
+
|
|
79
|
+
if Helper.is_test?
|
|
80
|
+
return build_args
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
# Joins args into space delimited string
|
|
84
|
+
build_args = build_args.join(' ')
|
|
85
|
+
|
|
86
|
+
command = "ipa distribute:s3 #{build_args}"
|
|
87
|
+
Helper.log.debug command
|
|
88
|
+
Actions.sh command
|
|
89
|
+
|
|
90
|
+
#####################################
|
|
91
|
+
#
|
|
92
|
+
# html and plist building
|
|
93
|
+
#
|
|
94
|
+
#####################################
|
|
95
|
+
|
|
96
|
+
# Gets info used for the plist
|
|
97
|
+
bundle_id, bundle_version, title = get_ipa_info( ipa_file )
|
|
98
|
+
|
|
99
|
+
# Gets URL for IPA file
|
|
100
|
+
url_part = expand_path_with_substitutions_from_ipa_plist( ipa_file, s3_path )
|
|
101
|
+
ipa_file_name = File.basename(ipa_file)
|
|
102
|
+
ipa_url = "https://#{s3_subdomain}.amazonaws.com/#{s3_bucket}/#{url_part}#{ipa_file_name}"
|
|
103
|
+
dsym_url = "https://#{s3_subdomain}.amazonaws.com/#{s3_bucket}/#{url_part}#{dsym_file}" if dsym_file
|
|
104
|
+
|
|
105
|
+
# Setting action and environment variables
|
|
106
|
+
Actions.lane_context[SharedValues::S3_IPA_OUTPUT_PATH] = ipa_url
|
|
107
|
+
ENV[SharedValues::S3_IPA_OUTPUT_PATH.to_s] = ipa_url
|
|
108
|
+
|
|
109
|
+
if dsym_file
|
|
110
|
+
Actions.lane_context[SharedValues::S3_DSYM_OUTPUT_PATH] = dsym_url
|
|
111
|
+
ENV[SharedValues::S3_DSYM_OUTPUT_PATH.to_s] = dsym_url
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
# Creating plist and html names
|
|
115
|
+
plist_file_name = "#{url_part}#{title}.plist"
|
|
116
|
+
plist_url = "https://#{s3_subdomain}.amazonaws.com/#{s3_bucket}/#{plist_file_name}"
|
|
117
|
+
|
|
118
|
+
html_file_name ||= "index.html"
|
|
119
|
+
html_url = "https://#{s3_subdomain}.amazonaws.com/#{s3_bucket}/#{html_file_name}"
|
|
120
|
+
|
|
121
|
+
# Creates plist from template
|
|
122
|
+
plist_template_path ||= "#{Helper.gem_path('fastlane')}/lib/assets/s3_plist_template.erb"
|
|
123
|
+
plist_template = File.read(plist_template_path)
|
|
124
|
+
|
|
125
|
+
et = ErbalT.new({
|
|
126
|
+
url: ipa_url,
|
|
127
|
+
bundle_id: bundle_id,
|
|
128
|
+
bundle_version: bundle_version,
|
|
129
|
+
title: title
|
|
130
|
+
})
|
|
131
|
+
plist_render = et.render(plist_template)
|
|
132
|
+
|
|
133
|
+
# Creates html from template
|
|
134
|
+
html_template_path ||= "#{Helper.gem_path('fastlane')}/lib/assets/s3_html_template.erb"
|
|
135
|
+
html_template = File.read(html_template_path)
|
|
136
|
+
|
|
137
|
+
et = ErbalT.new({
|
|
138
|
+
url: plist_url,
|
|
139
|
+
bundle_id: bundle_id,
|
|
140
|
+
bundle_version: bundle_version,
|
|
141
|
+
title: title
|
|
142
|
+
})
|
|
143
|
+
html_render = et.render(html_template)
|
|
144
|
+
|
|
145
|
+
#####################################
|
|
146
|
+
#
|
|
147
|
+
# html and plist uploading
|
|
148
|
+
#
|
|
149
|
+
#####################################
|
|
150
|
+
|
|
151
|
+
upload_plist_and_html_to_s3(
|
|
152
|
+
s3_access_key,
|
|
153
|
+
s3_secret_access_key,
|
|
154
|
+
s3_bucket,
|
|
155
|
+
plist_file_name,
|
|
156
|
+
plist_render,
|
|
157
|
+
html_file_name,
|
|
158
|
+
html_render
|
|
159
|
+
)
|
|
160
|
+
|
|
161
|
+
return true
|
|
162
|
+
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
def self.params_to_build_args(params)
|
|
166
|
+
# Remove nil value params unless :clean or :archive
|
|
167
|
+
params = params.delete_if { |k, v| (k != :clean && k != :archive ) && v.nil? }
|
|
168
|
+
|
|
169
|
+
# Maps nice developer param names to Shenzhen's `ipa build` arguments
|
|
170
|
+
params.collect do |k,v|
|
|
171
|
+
v ||= ''
|
|
172
|
+
if args = S3_ARGS_MAP[k]
|
|
173
|
+
value = (v.to_s.length > 0 ? "\"#{v}\"" : "")
|
|
174
|
+
"#{S3_ARGS_MAP[k]} #{value}".strip
|
|
175
|
+
end
|
|
176
|
+
end.compact
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
def self.upload_plist_and_html_to_s3(s3_access_key, s3_secret_access_key, s3_bucket, plist_file_name, plist_render, html_file_name, html_render)
|
|
180
|
+
require 'aws-sdk'
|
|
181
|
+
s3_client = AWS::S3.new(
|
|
182
|
+
access_key_id: s3_access_key,
|
|
183
|
+
secret_access_key: s3_secret_access_key
|
|
184
|
+
)
|
|
185
|
+
bucket = s3_client.buckets[s3_bucket]
|
|
186
|
+
|
|
187
|
+
plist_obj = bucket.objects.create(plist_file_name, plist_render.to_s, :acl => :public_read)
|
|
188
|
+
html_obj = bucket.objects.create(html_file_name, html_render.to_s, :acl => :public_read)
|
|
189
|
+
|
|
190
|
+
# Setting actionand environment variables
|
|
191
|
+
Actions.lane_context[SharedValues::S3_PLIST_OUTPUT_PATH] = plist_obj.public_url.to_s
|
|
192
|
+
ENV[SharedValues::S3_PLIST_OUTPUT_PATH.to_s] = plist_obj.public_url.to_s
|
|
193
|
+
|
|
194
|
+
Actions.lane_context[SharedValues::S3_HTML_OUTPUT_PATH] = html_obj.public_url.to_s
|
|
195
|
+
ENV[SharedValues::S3_HTML_OUTPUT_PATH.to_s] = html_obj.public_url.to_s
|
|
196
|
+
|
|
197
|
+
Helper.log.info "Successfully uploaded ipa file to '#{html_obj.public_url.to_s}'".green
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
#
|
|
201
|
+
# NOT a fan of this as this was taken straight from Shenzhen
|
|
202
|
+
# https://github.com/nomad/shenzhen/blob/986792db5d4d16a80c865a2748ee96ba63644821/lib/shenzhen/plugins/s3.rb#L32
|
|
203
|
+
#
|
|
204
|
+
# Need to find a way to not use this copied method
|
|
205
|
+
#
|
|
206
|
+
# AGAIN, I am not happy about this right now.
|
|
207
|
+
# Using this for prototype reasons.
|
|
208
|
+
#
|
|
209
|
+
def self.expand_path_with_substitutions_from_ipa_plist(ipa, path)
|
|
210
|
+
substitutions = path.scan(/\{CFBundle[^}]+\}/)
|
|
211
|
+
return path if substitutions.empty?
|
|
212
|
+
|
|
213
|
+
Dir.mktmpdir do |dir|
|
|
214
|
+
system "unzip -q #{ipa} -d #{dir} 2> /dev/null"
|
|
215
|
+
|
|
216
|
+
plist = Dir["#{dir}/**/*.app/Info.plist"].last
|
|
217
|
+
|
|
218
|
+
substitutions.uniq.each do |substitution|
|
|
219
|
+
key = substitution[1...-1]
|
|
220
|
+
value = Shenzhen::PlistBuddy.print(plist, key)
|
|
221
|
+
|
|
222
|
+
path.gsub!(Regexp.new(substitution), value) if value
|
|
223
|
+
end
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
return path
|
|
227
|
+
end
|
|
228
|
+
|
|
229
|
+
def self.get_ipa_info(ipa_file)
|
|
230
|
+
bundle_id, bundle_version, title = nil
|
|
231
|
+
Dir.mktmpdir do |dir|
|
|
232
|
+
|
|
233
|
+
system "unzip -q #{ipa_file} -d #{dir} 2> /dev/null"
|
|
234
|
+
plist = Dir["#{dir}/**/*.app/Info.plist"].last
|
|
235
|
+
|
|
236
|
+
bundle_id = Shenzhen::PlistBuddy.print(plist, 'CFBundleIdentifier')
|
|
237
|
+
bundle_version = Shenzhen::PlistBuddy.print(plist, 'CFBundleShortVersionString')
|
|
238
|
+
title = Shenzhen::PlistBuddy.print(plist, 'CFBundleName')
|
|
239
|
+
|
|
240
|
+
end
|
|
241
|
+
return bundle_id, bundle_version, title
|
|
242
|
+
end
|
|
243
|
+
|
|
244
|
+
end
|
|
245
|
+
|
|
246
|
+
end
|
|
247
|
+
end
|
|
248
|
+
|
|
249
|
+
class ErbalT < OpenStruct
|
|
250
|
+
def render(template)
|
|
251
|
+
ERB.new(template).result(binding)
|
|
252
|
+
end
|
|
253
|
+
end
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
module Fastlane
|
|
2
|
+
module Actions
|
|
3
|
+
# See: https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man1/xcode-select.1.html
|
|
4
|
+
#
|
|
5
|
+
# DESCRIPTION
|
|
6
|
+
# xcode-select controls the location of the developer directory used by xcrun(1), xcodebuild(1), cc(1),
|
|
7
|
+
# and other Xcode and BSD development tools. This also controls the locations that are searched for by
|
|
8
|
+
# man(1) for developer tool manpages.
|
|
9
|
+
#
|
|
10
|
+
# DEVELOPER_DIR
|
|
11
|
+
# Overrides the active developer directory. When DEVELOPER_DIR is set, its value will be used
|
|
12
|
+
# instead of the system-wide active developer directory.
|
|
13
|
+
#
|
|
14
|
+
# Note that for historical reason, the developer directory is considered to be the Developer content
|
|
15
|
+
# directory inside the Xcode application (for example /Applications/Xcode.app/Contents/Developer).
|
|
16
|
+
# You can set the environment variable to either the actual Developer contents directory, or the
|
|
17
|
+
# Xcode application directory -- the xcode-select provided shims will automatically convert the
|
|
18
|
+
# environment variable into the full Developer content path.
|
|
19
|
+
#
|
|
20
|
+
class XcodeSelectAction
|
|
21
|
+
def self.run(params)
|
|
22
|
+
xcode_path = params.first
|
|
23
|
+
|
|
24
|
+
# Verify that a param was passed in
|
|
25
|
+
raise "Path to Xcode application required (e.x. \"/Applications/Xcode.app\")".red unless xcode_path.to_s.length > 0
|
|
26
|
+
|
|
27
|
+
# Verify that a path to a directory was passed in
|
|
28
|
+
raise "Nonexistent path provided".red unless Dir.exists? xcode_path
|
|
29
|
+
|
|
30
|
+
Helper.log.info "Setting Xcode version to #{xcode_path} for all build steps"
|
|
31
|
+
|
|
32
|
+
ENV["DEVELOPER_DIR"] = xcode_path + "/Contents/Developer"
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
@@ -1,13 +1,27 @@
|
|
|
1
1
|
module Fastlane
|
|
2
2
|
class LaneManager
|
|
3
|
-
def self.cruise_lanes(lanes)
|
|
3
|
+
def self.cruise_lanes(lanes, env=nil)
|
|
4
|
+
Actions.lane_context[Actions::SharedValues::ENVIRONMENT] = env
|
|
4
5
|
raise 'lanes must be an array' unless lanes.is_a?(Array)
|
|
6
|
+
|
|
5
7
|
ff = Fastlane::FastFile.new(File.join(Fastlane::FastlaneFolder.path, 'Fastfile'))
|
|
6
8
|
|
|
7
9
|
if lanes.count == 0
|
|
8
10
|
raise "Please pass the name of the lane you want to drive. Available lanes: #{ff.runner.available_lanes.join(', ')}".red
|
|
9
11
|
end
|
|
10
12
|
|
|
13
|
+
# Making sure the default '.env' and '.env.default' get loaded
|
|
14
|
+
env_file = File.join(Fastlane::FastlaneFolder.path || "", '.env')
|
|
15
|
+
env_default_file = File.join(Fastlane::FastlaneFolder.path || "", '.env.default')
|
|
16
|
+
Dotenv.load(env_file, env_default_file)
|
|
17
|
+
|
|
18
|
+
# Loads .env file for the environment passed in through options
|
|
19
|
+
if env
|
|
20
|
+
env_file = File.join(Fastlane::FastlaneFolder.path || "", ".env.#{env}")
|
|
21
|
+
Helper.log.info "Loading from '#{env_file}'".green
|
|
22
|
+
Dotenv.overload(env_file)
|
|
23
|
+
end
|
|
24
|
+
|
|
11
25
|
start = Time.now
|
|
12
26
|
e = nil
|
|
13
27
|
begin
|
|
@@ -39,5 +53,6 @@ module Fastlane
|
|
|
39
53
|
raise e
|
|
40
54
|
end
|
|
41
55
|
end
|
|
56
|
+
|
|
42
57
|
end
|
|
43
58
|
end
|
data/lib/fastlane/runner.rb
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
module Fastlane
|
|
2
2
|
class Runner
|
|
3
|
+
|
|
3
4
|
def execute(key)
|
|
4
5
|
key = key.to_sym
|
|
5
6
|
Helper.log.info "Driving the lane '#{key}'".green
|
|
@@ -7,9 +8,10 @@ module Fastlane
|
|
|
7
8
|
|
|
8
9
|
return_val = nil
|
|
9
10
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
path_to_use = Fastlane::FastlaneFolder.path || Dir.pwd
|
|
12
|
+
Dir.chdir(path_to_use) do # the file is located in the fastlane folder
|
|
13
|
+
@before_all.call(key) if @before_all
|
|
14
|
+
|
|
13
15
|
return_val = nil
|
|
14
16
|
|
|
15
17
|
if blocks[key]
|
|
@@ -23,7 +25,9 @@ module Fastlane
|
|
|
23
25
|
|
|
24
26
|
return return_val
|
|
25
27
|
rescue => ex
|
|
26
|
-
|
|
28
|
+
Dir.chdir(path_to_use) do
|
|
29
|
+
@error.call(key, ex) if @error # notify the block
|
|
30
|
+
end
|
|
27
31
|
raise ex
|
|
28
32
|
end
|
|
29
33
|
|
data/lib/fastlane/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: fastlane
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.15
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Felix Krause
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2015-
|
|
11
|
+
date: 2015-03-05 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: nokogiri
|
|
@@ -53,19 +53,33 @@ dependencies:
|
|
|
53
53
|
- !ruby/object:Gem::Version
|
|
54
54
|
version: '1.0'
|
|
55
55
|
- !ruby/object:Gem::Dependency
|
|
56
|
-
name:
|
|
56
|
+
name: aws-sdk
|
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
|
58
58
|
requirements:
|
|
59
59
|
- - ~>
|
|
60
60
|
- !ruby/object:Gem::Version
|
|
61
|
-
version:
|
|
61
|
+
version: '1.0'
|
|
62
62
|
type: :runtime
|
|
63
63
|
prerelease: false
|
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
|
65
65
|
requirements:
|
|
66
66
|
- - ~>
|
|
67
67
|
- !ruby/object:Gem::Version
|
|
68
|
-
version:
|
|
68
|
+
version: '1.0'
|
|
69
|
+
- !ruby/object:Gem::Dependency
|
|
70
|
+
name: fastlane_core
|
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
|
72
|
+
requirements:
|
|
73
|
+
- - '>='
|
|
74
|
+
- !ruby/object:Gem::Version
|
|
75
|
+
version: 0.2.1
|
|
76
|
+
type: :runtime
|
|
77
|
+
prerelease: false
|
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
79
|
+
requirements:
|
|
80
|
+
- - '>='
|
|
81
|
+
- !ruby/object:Gem::Version
|
|
82
|
+
version: 0.2.1
|
|
69
83
|
- !ruby/object:Gem::Dependency
|
|
70
84
|
name: deliver
|
|
71
85
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -290,6 +304,8 @@ files:
|
|
|
290
304
|
- lib/assets/AppfileTemplate
|
|
291
305
|
- lib/assets/FastfileTemplate
|
|
292
306
|
- lib/assets/custom_action_template.rb
|
|
307
|
+
- lib/assets/s3_html_template.erb
|
|
308
|
+
- lib/assets/s3_plist_template.erb
|
|
293
309
|
- lib/fastlane.rb
|
|
294
310
|
- lib/fastlane/actions/README
|
|
295
311
|
- lib/fastlane/actions/actions_helper.rb
|
|
@@ -305,6 +321,7 @@ files:
|
|
|
305
321
|
- lib/fastlane/actions/install_cocapods.rb
|
|
306
322
|
- lib/fastlane/actions/ipa.rb
|
|
307
323
|
- lib/fastlane/actions/produce.rb
|
|
324
|
+
- lib/fastlane/actions/s3.rb
|
|
308
325
|
- lib/fastlane/actions/say.rb
|
|
309
326
|
- lib/fastlane/actions/sigh.rb
|
|
310
327
|
- lib/fastlane/actions/slack.rb
|
|
@@ -314,6 +331,7 @@ files:
|
|
|
314
331
|
- lib/fastlane/actions/testmunk.rb
|
|
315
332
|
- lib/fastlane/actions/typetalk.rb
|
|
316
333
|
- lib/fastlane/actions/update_project_code_signing.rb
|
|
334
|
+
- lib/fastlane/actions/xcode_select.rb
|
|
317
335
|
- lib/fastlane/actions/xctool.rb
|
|
318
336
|
- lib/fastlane/core_ext/string.rb
|
|
319
337
|
- lib/fastlane/dependency_checker.rb
|