fastlane 0.0.1 → 0.1.0
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/LICENSE +21 -0
- data/README.md +418 -0
- data/bin/fastlane +63 -0
- data/lib/assets/AppfileTemplate +2 -0
- data/lib/assets/FastfileTemplate +56 -0
- data/lib/assets/custom_action_template.rb +17 -0
- data/lib/fastlane.rb +28 -0
- data/lib/fastlane/actions/README +3 -0
- data/lib/fastlane/actions/actions_helper.rb +113 -0
- data/lib/fastlane/actions/deliver.rb +28 -0
- data/lib/fastlane/actions/frameit.rb +23 -0
- data/lib/fastlane/actions/hockey.rb +47 -0
- data/lib/fastlane/actions/increment_build_number.rb +40 -0
- data/lib/fastlane/actions/install_cocapods.rb +9 -0
- data/lib/fastlane/actions/say.rb +10 -0
- data/lib/fastlane/actions/sigh.rb +31 -0
- data/lib/fastlane/actions/slack.rb +56 -0
- data/lib/fastlane/actions/snapshot.rb +30 -0
- data/lib/fastlane/actions/testmunk.rb +42 -0
- data/lib/fastlane/actions/xctool.rb +10 -0
- data/lib/fastlane/dependency_checker.rb +18 -0
- data/lib/fastlane/fast_file.rb +89 -0
- data/lib/fastlane/fastlane_folder.rb +24 -0
- data/lib/fastlane/helper.rb +66 -0
- data/lib/fastlane/junit_generator.rb +32 -0
- data/lib/fastlane/lane_manager.rb +39 -0
- data/lib/fastlane/new_action.rb +39 -0
- data/lib/fastlane/runner.rb +58 -0
- data/lib/fastlane/setup.rb +157 -0
- data/lib/fastlane/update_checker.rb +44 -0
- data/lib/fastlane/version.rb +3 -0
- metadata +121 -33
data/bin/fastlane
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
$:.push File.expand_path("../../lib", __FILE__)
|
4
|
+
|
5
|
+
require 'fastlane'
|
6
|
+
require 'commander'
|
7
|
+
require 'fastlane/new_action'
|
8
|
+
|
9
|
+
HighLine.track_eof = false
|
10
|
+
|
11
|
+
|
12
|
+
class FastlaneApplication
|
13
|
+
include Commander::Methods
|
14
|
+
|
15
|
+
def run
|
16
|
+
program :version, Fastlane::VERSION
|
17
|
+
program :description, 'CLI for \'fastlane\' - Connect all iOS deployment tools into one streamlined workflow'
|
18
|
+
program :help, 'Author', 'Felix Krause <fastlane@krausefx.com>'
|
19
|
+
program :help, 'Website', 'http://fastlane.tools'
|
20
|
+
program :help, 'GitHub', 'https://github.com/krausefx/fastlane'
|
21
|
+
program :help_formatter, :compact
|
22
|
+
|
23
|
+
global_option('--verbose') { $verbose = true }
|
24
|
+
|
25
|
+
command :run do |c|
|
26
|
+
c.syntax = 'fastlane run [lane]'
|
27
|
+
c.description = 'Drive the fastlane for a specific environment.'
|
28
|
+
|
29
|
+
c.action do |args, options|
|
30
|
+
if Fastlane::FastlaneFolder.path
|
31
|
+
Fastlane::LaneManager.cruise_lanes(args)
|
32
|
+
else
|
33
|
+
create = agree("Could not find fastlane in current directory. Would you like to set it up? (y/n)".yellow, true)
|
34
|
+
Fastlane::Setup.new.run if create
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
command :init do |c|
|
40
|
+
c.syntax = 'fastlane init'
|
41
|
+
c.description = 'Helps you setting up fastlane based on your existing tools.'
|
42
|
+
|
43
|
+
c.action do |args, options|
|
44
|
+
Fastlane::Setup.new.run
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
command :new_action do |c|
|
49
|
+
c.syntax = 'fastlane new_action'
|
50
|
+
c.description = 'Create a new custom action for fastlane.'
|
51
|
+
|
52
|
+
c.action do |args, options|
|
53
|
+
Fastlane::NewAction.run
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
default_command :run
|
58
|
+
|
59
|
+
run!
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
FastlaneApplication.new.run
|
@@ -0,0 +1,56 @@
|
|
1
|
+
# Customise this file, documentation can be found here:
|
2
|
+
# https://github.com/krausefx/fastlane#customise-the-fastfile
|
3
|
+
|
4
|
+
# Change the syntax highlighting to Ruby
|
5
|
+
|
6
|
+
# All lines starting with a # are ignored when running `fastlane`
|
7
|
+
|
8
|
+
before_all do
|
9
|
+
# ENV["SLACK_URL"] = "https://hooks.slack.com/services/..."
|
10
|
+
|
11
|
+
# sh "./customShellScript.sh"
|
12
|
+
|
13
|
+
# increment_build_number
|
14
|
+
|
15
|
+
cocoapods
|
16
|
+
|
17
|
+
xctool
|
18
|
+
end
|
19
|
+
|
20
|
+
lane :test do
|
21
|
+
snapshot
|
22
|
+
end
|
23
|
+
|
24
|
+
lane :beta do
|
25
|
+
snapshot
|
26
|
+
sigh
|
27
|
+
deliver :skip_deploy, :beta
|
28
|
+
# sh "your_script.sh"
|
29
|
+
end
|
30
|
+
|
31
|
+
lane :deploy do
|
32
|
+
snapshot
|
33
|
+
sigh
|
34
|
+
deliver :skip_deploy, :force
|
35
|
+
# frameit
|
36
|
+
end
|
37
|
+
|
38
|
+
lane :inhouse do
|
39
|
+
# insert your code here
|
40
|
+
end
|
41
|
+
|
42
|
+
# You can define as many lanes as you want
|
43
|
+
|
44
|
+
after_all do |lane|
|
45
|
+
# This block is called, only if the executed lane was successful
|
46
|
+
# slack({
|
47
|
+
# message: "Successfully deployed new App Update for [App](http://link.com).",
|
48
|
+
# success: true,
|
49
|
+
# channel: 'development'
|
50
|
+
# })
|
51
|
+
end
|
52
|
+
|
53
|
+
|
54
|
+
error do |lane, exception|
|
55
|
+
# Something bad happened
|
56
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Fastlane
|
2
|
+
module Actions
|
3
|
+
module SharedValues
|
4
|
+
[[NAME_UP]]_CUSTOM_VALUE = :[[NAME_UP]]_CUSTOM_VALUE
|
5
|
+
end
|
6
|
+
|
7
|
+
class [[NAME_CLASS]]
|
8
|
+
def self.run(params)
|
9
|
+
puts "My Ruby Code!"
|
10
|
+
# puts "Parameter: #{params.first}"
|
11
|
+
# sh "shellcommand ./path"
|
12
|
+
|
13
|
+
# Actions.lane_context[SharedValues::[[NAME_UP]]_CUSTOM_VALUE] = "my_val"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
data/lib/fastlane.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'fastlane/version'
|
3
|
+
require 'fastlane/fast_file'
|
4
|
+
require 'fastlane/helper'
|
5
|
+
require 'fastlane/dependency_checker'
|
6
|
+
require 'fastlane/runner'
|
7
|
+
require 'fastlane/setup'
|
8
|
+
require 'fastlane/fastlane_folder'
|
9
|
+
require 'fastlane/update_checker'
|
10
|
+
require 'fastlane/junit_generator'
|
11
|
+
require 'fastlane/lane_manager'
|
12
|
+
require 'fastlane/actions/actions_helper'
|
13
|
+
|
14
|
+
# Third Party code
|
15
|
+
require 'colored'
|
16
|
+
|
17
|
+
module Fastlane
|
18
|
+
TMP_FOLDER = "/tmp/fastlane/"
|
19
|
+
|
20
|
+
UpdateChecker.verify_latest_version
|
21
|
+
|
22
|
+
Fastlane::Actions.load_default_actions
|
23
|
+
|
24
|
+
if Fastlane::FastlaneFolder.path
|
25
|
+
actions_path = File.join(Fastlane::FastlaneFolder.path, "actions")
|
26
|
+
Fastlane::Actions.load_external_actions(actions_path) if File.directory?actions_path
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,113 @@
|
|
1
|
+
require 'pty'
|
2
|
+
|
3
|
+
module Fastlane
|
4
|
+
module Actions
|
5
|
+
module SharedValues
|
6
|
+
LANE_NAME = :LANE_NAME
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.executed_actions
|
10
|
+
@@executed_actions ||= []
|
11
|
+
end
|
12
|
+
|
13
|
+
# The shared hash can be accessed by any action and contains information like the screenshots path or beta URL
|
14
|
+
def self.lane_context
|
15
|
+
@@lane_context ||= {}
|
16
|
+
end
|
17
|
+
|
18
|
+
# Pass a block which should be tracked. One block = one testcase
|
19
|
+
# @param step_name (String) the name of the currently built code (e.g. snapshot, sigh, ...)
|
20
|
+
def self.execute_action(step_name)
|
21
|
+
raise "No block given".red unless block_given?
|
22
|
+
|
23
|
+
start = Time.now
|
24
|
+
error = nil
|
25
|
+
exc = nil
|
26
|
+
|
27
|
+
begin
|
28
|
+
yield
|
29
|
+
rescue => ex
|
30
|
+
exc = ex
|
31
|
+
error = caller.join("\n") + "\n\n" + ex.to_s
|
32
|
+
end
|
33
|
+
ensure
|
34
|
+
# This is also called, when the block has a return statement
|
35
|
+
duration = Time.now - start
|
36
|
+
|
37
|
+
self.executed_actions << {
|
38
|
+
name: step_name,
|
39
|
+
error: error,
|
40
|
+
time: duration
|
41
|
+
# output: captured_output
|
42
|
+
}
|
43
|
+
raise exc if exc
|
44
|
+
end
|
45
|
+
|
46
|
+
# Execute a shell command
|
47
|
+
# This method will output the string and execute it
|
48
|
+
def self.sh(command)
|
49
|
+
return sh_no_action(command)
|
50
|
+
end
|
51
|
+
|
52
|
+
def self.sh_no_action(command)
|
53
|
+
command = command.join(" ") if command.kind_of?Array # since it's an array of one element when running from the Fastfile
|
54
|
+
Helper.log.info ["[SHELL COMMAND]", command.yellow].join(': ')
|
55
|
+
|
56
|
+
result = ""
|
57
|
+
unless Helper.is_test?
|
58
|
+
|
59
|
+
PTY.spawn(command) do |stdin, stdout, pid|
|
60
|
+
stdin.each do |line|
|
61
|
+
Helper.log.info ["[SHELL OUTPUT]", line.strip].join(': ')
|
62
|
+
result << line
|
63
|
+
end
|
64
|
+
|
65
|
+
Process.wait(pid)
|
66
|
+
end
|
67
|
+
|
68
|
+
if $?.exitstatus.to_i != 0
|
69
|
+
raise "Exit status of command '#{command}' was #{$?.exitstatus.to_s} instead of 0. Build failed."
|
70
|
+
end
|
71
|
+
else
|
72
|
+
result << command # only when running tests
|
73
|
+
end
|
74
|
+
|
75
|
+
return result
|
76
|
+
end
|
77
|
+
|
78
|
+
def self.load_default_actions
|
79
|
+
Dir[File.expand_path '*.rb', File.dirname(__FILE__)].each do |file|
|
80
|
+
require file
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def self.load_external_actions(path)
|
85
|
+
raise "You need to pass a valid path" unless File.exists?path
|
86
|
+
|
87
|
+
Dir[File.expand_path '*.rb', path].each do |file|
|
88
|
+
require file
|
89
|
+
|
90
|
+
file_name = File.basename(file).gsub(".rb", "")
|
91
|
+
|
92
|
+
class_name = file_name.classify + "Action"
|
93
|
+
class_ref = nil
|
94
|
+
begin
|
95
|
+
class_ref = Fastlane::Actions.const_get(class_name)
|
96
|
+
|
97
|
+
if class_ref.respond_to?(:run)
|
98
|
+
Helper.log.info "Successfully loaded custom action '#{file}'.".green
|
99
|
+
else
|
100
|
+
Helper.log.error "Could not find method 'run' in class #{class_name}.".red
|
101
|
+
Helper.log.error "For more information, check out the docs: https://github.com/KrauseFx/fastlane"
|
102
|
+
raise "Plugin '#{file_name}' is damaged!"
|
103
|
+
end
|
104
|
+
rescue NameError => ex
|
105
|
+
# Action not found
|
106
|
+
Helper.log.error "Could not find '#{class_name}' class defined.".red
|
107
|
+
Helper.log.error "For more information, check out the docs: https://github.com/KrauseFx/fastlane"
|
108
|
+
raise "Plugin '#{file_name}' is damaged!"
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Fastlane
|
2
|
+
module Actions
|
3
|
+
module SharedValues
|
4
|
+
DELIVER_IPA_PATH = :DELIVER_IPA_PATH
|
5
|
+
end
|
6
|
+
|
7
|
+
class DeliverAction
|
8
|
+
def self.run(params)
|
9
|
+
require 'deliver'
|
10
|
+
|
11
|
+
ENV["DELIVER_SCREENSHOTS_PATH"] = Actions.lane_context[SharedValues::SNAPSHOT_SCREENSHOTS_PATH]
|
12
|
+
|
13
|
+
force = params.include?(:force)
|
14
|
+
beta = params.include?(:beta)
|
15
|
+
skip_deploy = params.include?(:skip_deploy)
|
16
|
+
|
17
|
+
Dir.chdir(FastlaneFolder.path || Dir.pwd) do
|
18
|
+
# This should be executed in the fastlane folder
|
19
|
+
Deliver::Deliverer.new(nil, force: force,
|
20
|
+
is_beta_ipa: beta,
|
21
|
+
skip_deploy: skip_deploy)
|
22
|
+
|
23
|
+
ENV[Actions::SharedValues::DELIVER_IPA_PATH.to_s] = ENV["DELIVER_IPA_PATH"] # deliver will store it in the environment
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Fastlane
|
2
|
+
module Actions
|
3
|
+
module SharedValues
|
4
|
+
|
5
|
+
end
|
6
|
+
|
7
|
+
class FrameitAction
|
8
|
+
def self.run(params)
|
9
|
+
require 'frameit'
|
10
|
+
|
11
|
+
color = Frameit::Editor::Color::BLACK
|
12
|
+
color = Frameit::Editor::Color::SILVER if [:silver, :white].include?params.first
|
13
|
+
|
14
|
+
screenshots_folder = Actions.lane_context[SharedValues::SNAPSHOT_SCREENSHOTS_PATH]
|
15
|
+
screenshots_folder ||= FastlaneFolder.path
|
16
|
+
|
17
|
+
Dir.chdir(screenshots_folder) do
|
18
|
+
Frameit::Editor.new.run('.', color)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# TODO: Workaround, since hockeyapp.rb from shenzhen includes the code for commander
|
2
|
+
def command(param)
|
3
|
+
end
|
4
|
+
|
5
|
+
module Fastlane
|
6
|
+
module Actions
|
7
|
+
module SharedValues
|
8
|
+
HOCKEY_DOWNLOAD_LINK = :HOCKEY_DOWNLOAD_LINK
|
9
|
+
HOCKEY_BUILD_INFORMATION = :HOCKEY_BUILD_INFORMATION # contains all keys/values from the HockeyApp API, like :title, :bundle_identifier
|
10
|
+
end
|
11
|
+
|
12
|
+
class HockeyAction
|
13
|
+
def self.run(params)
|
14
|
+
# Available options: http://support.hockeyapp.net/kb/api/api-versions#upload-version
|
15
|
+
options = {
|
16
|
+
notes: "No changelog given",
|
17
|
+
status: 2,
|
18
|
+
notify: 1
|
19
|
+
}.merge(params.first)
|
20
|
+
|
21
|
+
require 'shenzhen'
|
22
|
+
require 'shenzhen/plugins/hockeyapp'
|
23
|
+
|
24
|
+
raise "No API Token for Hockey given, pass using `api_token: 'token'`".red unless options[:api_token].to_s.length > 0
|
25
|
+
raise "No IPA file given or found, pass using `ipa: 'path.ipa'`".red unless File.exists?(options[:ipa])
|
26
|
+
|
27
|
+
Helper.log.info "Starting with ipa upload to HockeyApp... this could take some time.".green
|
28
|
+
|
29
|
+
client = Shenzhen::Plugins::HockeyApp::Client.new(options[:api_token])
|
30
|
+
response = client.upload_build(options[:ipa], options)
|
31
|
+
case response.status
|
32
|
+
when 200...300
|
33
|
+
url = response.body['public_url']
|
34
|
+
|
35
|
+
Actions.lane_context[SharedValues::HOCKEY_DOWNLOAD_LINK] = url
|
36
|
+
Actions.lane_context[SharedValues::HOCKEY_BUILD_INFORMATION] = response.body
|
37
|
+
|
38
|
+
Helper.log.info "Public Download URL: #{url}" if url
|
39
|
+
Helper.log.info "Build successfully uploaded to HockeyApp!".green
|
40
|
+
else
|
41
|
+
Helper.log.fatal "Error uploading to HockeyApp: #{response.body}"
|
42
|
+
raise "Error when trying to upload ipa to HockeyApp".red
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module Fastlane
|
2
|
+
module Actions
|
3
|
+
module SharedValues
|
4
|
+
BUILD_NUMBER = :BUILD_NUMBER
|
5
|
+
end
|
6
|
+
|
7
|
+
class IncrementBuildNumberAction
|
8
|
+
def self.run(params)
|
9
|
+
# More information about how to set up your project and how it works:
|
10
|
+
# https://developer.apple.com/library/ios/qa/qa1827/_index.html
|
11
|
+
# Attention: This is NOT the version number - but the build number
|
12
|
+
|
13
|
+
begin
|
14
|
+
custom_number = (params.first rescue nil)
|
15
|
+
|
16
|
+
command = nil
|
17
|
+
if custom_number
|
18
|
+
command = "agvtool new-version -all #{custom_number}"
|
19
|
+
else
|
20
|
+
command = "agvtool next-version -all"
|
21
|
+
end
|
22
|
+
|
23
|
+
Actions.sh command
|
24
|
+
|
25
|
+
# Store the new number in the shared hash
|
26
|
+
build_number = `agvtool what-version`.split("\n").last.to_i
|
27
|
+
|
28
|
+
if Helper.is_test?
|
29
|
+
build_number = command
|
30
|
+
end
|
31
|
+
|
32
|
+
Actions.lane_context[SharedValues::BUILD_NUMBER] = build_number
|
33
|
+
rescue => ex
|
34
|
+
Helper.log.error "Make sure to to follow the steps to setup your Xcode project: https://developer.apple.com/library/ios/qa/qa1827/_index.html".yellow
|
35
|
+
raise ex
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|