fastlane 2.142.0 → 2.143.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +84 -84
  3. data/fastlane/lib/fastlane/actions/.hockey.rb.swp +0 -0
  4. data/fastlane/lib/fastlane/actions/.slack.rb.swp +0 -0
  5. data/fastlane/lib/fastlane/actions/.update_project_provisioning.rb.swp +0 -0
  6. data/fastlane/lib/fastlane/actions/docs/frame_screenshots.md +22 -6
  7. data/fastlane/lib/fastlane/actions/docs/sync_code_signing.md +20 -4
  8. data/fastlane/lib/fastlane/actions/frame_screenshots.rb +2 -1
  9. data/fastlane/lib/fastlane/actions/s3.rb +3 -289
  10. data/fastlane/lib/fastlane/helper/s3_client_helper.rb +56 -0
  11. data/fastlane/lib/fastlane/version.rb +1 -1
  12. data/fastlane/swift/Deliverfile.swift +1 -1
  13. data/fastlane/swift/Fastlane.swift +59 -5
  14. data/fastlane/swift/FastlaneSwiftRunner/FastlaneSwiftRunner.xcodeproj/project.xcworkspace/xcuserdata/josh.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
  15. data/fastlane/swift/Gymfile.swift +1 -1
  16. data/fastlane/swift/Matchfile.swift +1 -1
  17. data/fastlane/swift/MatchfileProtocol.swift +17 -1
  18. data/fastlane/swift/Precheckfile.swift +1 -1
  19. data/fastlane/swift/Scanfile.swift +1 -1
  20. data/fastlane/swift/Screengrabfile.swift +1 -1
  21. data/fastlane/swift/Snapshotfile.swift +1 -1
  22. data/fastlane_core/lib/fastlane_core/ipa_file_analyser.rb +1 -0
  23. data/frameit/lib/frameit/commands_generator.rb +25 -0
  24. data/frameit/lib/frameit/config_parser.rb +31 -9
  25. data/frameit/lib/frameit/device.rb +90 -0
  26. data/frameit/lib/frameit/device_types.rb +121 -5
  27. data/frameit/lib/frameit/editor.rb +28 -40
  28. data/frameit/lib/frameit/offsets.rb +8 -1
  29. data/frameit/lib/frameit/options.rb +81 -54
  30. data/frameit/lib/frameit/runner.rb +17 -7
  31. data/frameit/lib/frameit/screenshot.rb +35 -47
  32. data/frameit/lib/frameit/template_finder.rb +15 -12
  33. data/match/lib/match/change_password.rb +1 -1
  34. data/match/lib/match/encryption.rb +4 -0
  35. data/match/lib/match/importer.rb +2 -2
  36. data/match/lib/match/module.rb +1 -1
  37. data/match/lib/match/nuke.rb +5 -1
  38. data/match/lib/match/options.rb +18 -0
  39. data/match/lib/match/runner.rb +4 -0
  40. data/match/lib/match/setup.rb +1 -1
  41. data/match/lib/match/storage.rb +4 -0
  42. data/match/lib/match/storage/s3_storage.rb +162 -0
  43. data/pilot/lib/pilot/.manager.rb.swp +0 -0
  44. data/scan/lib/scan/test_command_generator.rb +2 -1
  45. data/screengrab/lib/screengrab/runner.rb +11 -3
  46. data/spaceship/lib/spaceship/connect_api/.DS_Store +0 -0
  47. data/spaceship/lib/spaceship/connect_api/models/build.rb +1 -2
  48. data/spaceship/lib/spaceship/connect_api/models/certificate.rb +2 -0
  49. data/spaceship/lib/spaceship/portal/.certificate.rb.swp +0 -0
  50. metadata +42 -19
  51. data/gym/lib/gym/.code_signing_mapping.rb.swp +0 -0
@@ -14,9 +14,8 @@ module Frameit
14
14
  end
15
15
  end
16
16
 
17
- def run(path, color = nil)
17
+ def run(path, color = nil, platform = nil)
18
18
  unless color
19
- color = Frameit::Color::BLACK
20
19
  color = Frameit::Color::SILVER if Frameit.config[:white] || Frameit.config[:silver]
21
20
  color = Frameit::Color::GOLD if Frameit.config[:gold]
22
21
  color = Frameit::Color::ROSE_GOLD if Frameit.config[:rose_gold]
@@ -29,11 +28,12 @@ module Frameit
29
28
  next if skip_path?(full_path)
30
29
 
31
30
  begin
32
- screenshot = Screenshot.new(full_path, color)
31
+ config = create_config(full_path)
32
+ screenshot = Screenshot.new(full_path, color, config, platform)
33
33
 
34
34
  next if skip_up_to_date?(screenshot)
35
35
 
36
- editor = editor(screenshot)
36
+ editor = editor(screenshot, config)
37
37
 
38
38
  if editor.should_skip?
39
39
  UI.message("Skipping framing of screenshot #{screenshot.path}. No title provided in your Framefile.json or title.strings.")
@@ -71,12 +71,22 @@ module Frameit
71
71
  false
72
72
  end
73
73
 
74
- def editor(screenshot)
74
+ def editor(screenshot, config)
75
75
  if screenshot.mac?
76
- return MacEditor.new(screenshot)
76
+ return MacEditor.new(screenshot, config)
77
77
  else
78
- return Editor.new(screenshot, Frameit.config[:debug_mode])
78
+ return Editor.new(screenshot, config, Frameit.config[:debug_mode])
79
79
  end
80
80
  end
81
+
82
+ # Loads the config (colors, background, texts, etc.)
83
+ # Don't use this method to access the actual text and use `fetch_texts` instead
84
+ def create_config(screenshot_path)
85
+ config_path = File.join(File.expand_path("..", screenshot_path), "Framefile.json")
86
+ config_path = File.join(File.expand_path("../..", screenshot_path), "Framefile.json") unless File.exist?(config_path)
87
+ file = ConfigParser.new.load(config_path)
88
+ return {} unless file # no config file at all
89
+ file.fetch_value(screenshot_path)
90
+ end
81
91
  end
82
92
  end
@@ -1,87 +1,75 @@
1
- require 'deliver/app_screenshot'
2
-
3
1
  require_relative 'editor'
4
2
  require_relative 'mac_editor'
5
3
  require_relative 'device_types'
6
4
  require_relative 'module'
5
+ require_relative 'device'
7
6
 
8
7
  module Frameit
9
8
  # Represents one screenshot
10
9
  class Screenshot
11
10
  attr_accessor :path # path to the screenshot
12
11
  attr_accessor :size # size in px array of 2 elements: height and width
13
- attr_accessor :screen_size # deliver screen size type, is unique per device type, used in device_name
12
+ attr_accessor :device # device detected according to resolution, priority and settings
14
13
  attr_accessor :color # the color to use for the frame (from Frameit::Color)
15
14
 
16
15
  # path: Path to screenshot
17
16
  # color: Color to use for the frame
18
- def initialize(path, color)
17
+ def initialize(path, color, config, platform_command)
19
18
  UI.user_error!("Couldn't find file at path '#{path}'") unless File.exist?(path)
20
19
  @color = color
21
20
  @path = path
22
21
  @size = FastImage.size(path)
23
22
 
24
- @screen_size = ENV["FRAMEIT_FORCE_DEVICE_TYPE"] || Deliver::AppScreenshot.calculate_screen_size(path)
23
+ # There are three ways how we can get settings to Frameit:
24
+ # - options.rb
25
+ # - gets parameters via CLI (e. g. fastlane run frameit use_platform:"android") or fastfile (Fastlane's global
26
+ # settings for a given project)
27
+ # - see Parameters in the doc
28
+ # - contains default values and validates values
29
+ # - accessed via Frameit.config[:key]
30
+ # - lowest priority
31
+ # - commands_generator.rb
32
+ # - commands entered directly to CLI (e. g. fastlane frameit android)
33
+ # - they are passed via constructors to other classes
34
+ # - higher priority than options.rb (user may enter a command to override fastfile's global setting)
35
+ # - config_parser.rb
36
+ # - gets key / values from Framefile.json
37
+ # - see Advanced usage in the doc
38
+ # - both default and specific values can be entered in the file (filtered by file name)
39
+ # - accessed via ConfigParser.fetch_value(screenshot.path)[key] (the ConfigParser's instance is passed
40
+ # to Screenshot's constructor as config, i.e. we call config[key])
41
+ # - should have the highest priority, because user might set a specific value for a specific screenshot which
42
+ # should override CLI parameters and fastfile global setting
43
+ platform = config['use_platform'] || platform_command || Frameit.config[:use_platform]
44
+ @device = Device.find_device_by_id_or_name(config['force_device_type'] || Frameit.config[:force_device_type]) || Device.detect_device(path, platform)
25
45
  end
26
46
 
27
47
  # Device name for a given screen size. Used to use the correct template
28
48
  def device_name
29
- # rubocop:disable Require/MissingRequireStatement
30
- sizes = Deliver::AppScreenshot::ScreenSize
31
- case @screen_size
32
- when sizes::IOS_65
33
- return 'iPhone XS Max'
34
- when sizes::IOS_61
35
- return 'iPhone XR'
36
- when sizes::IOS_58
37
- return Frameit.config[:use_legacy_iphonex] ? 'iPhone X' : 'iPhone XS'
38
- when sizes::IOS_55
39
- return Frameit.config[:use_legacy_iphone6s] ? 'iPhone 6s Plus' : 'iPhone 7 Plus'
40
- when sizes::IOS_47
41
- return Frameit.config[:use_legacy_iphone6s] ? 'iPhone 6s' : 'iPhone 7'
42
- when sizes::IOS_40
43
- return Frameit.config[:use_legacy_iphone5s] ? 'iPhone 5s' : 'iPhone SE'
44
- when sizes::IOS_35
45
- return 'iPhone 4'
46
- when sizes::IOS_IPAD
47
- return 'iPad Air 2'
48
- when sizes::IOS_IPAD_10_5
49
- return 'iPad Pro (10.5-inch)'
50
- when sizes::IOS_IPAD_11
51
- return 'iPad Pro (11-inch)'
52
- when sizes::IOS_IPAD_PRO
53
- return 'iPad Pro'
54
- when sizes::IOS_IPAD_PRO_12_9
55
- return 'iPad Pro (12.9-inch) (3rd generation)'
56
- when sizes::MAC
57
- return 'MacBook'
58
- else
59
- UI.error("Unknown device type for size #{@screen_size} for path '#{path}'")
60
- end
49
+ @device.formatted_name
61
50
  # rubocop:enable Require/MissingRequireStatement
62
51
  end
63
52
 
64
- def color
65
- if !Frameit.config[:use_legacy_iphone6s] && @color == Frameit::Color::BLACK
66
- if @screen_size == Deliver::AppScreenshot::ScreenSize::IOS_55 || @screen_size == Deliver::AppScreenshot::ScreenSize::IOS_47
67
- return "Matte Black" # RIP space gray
68
- end
69
- end
70
- return @color
53
+ def default_color
54
+ @device.default_color
55
+ end
56
+
57
+ def deliver_screen_id
58
+ @device.deliver_screen_id
71
59
  end
72
60
 
73
61
  # Is the device a 3x device? (e.g. iPhone 6 Plus, iPhone X)
74
62
  def triple_density?
75
- (screen_size == Deliver::AppScreenshot::ScreenSize::IOS_55 || screen_size == Deliver::AppScreenshot::ScreenSize::IOS_58 || screen_size == Deliver::AppScreenshot::ScreenSize::IOS_65)
63
+ !device.density_ppi.nil? && device.density_ppi > 400
76
64
  end
77
65
 
78
66
  # Super old devices (iPhone 4)
79
67
  def mini?
80
- (screen_size == Deliver::AppScreenshot::ScreenSize::IOS_35)
68
+ !device.density_ppi.nil? && device.density_ppi < 300
81
69
  end
82
70
 
83
71
  def mac?
84
- return device_name == 'MacBook'
72
+ device_name == 'MacBook'
85
73
  end
86
74
 
87
75
  # The name of the orientation of a screenshot. Used to find the correct template
@@ -1,5 +1,4 @@
1
1
  require 'deliver/app_screenshot'
2
-
3
2
  require_relative 'module'
4
3
  require_relative 'device_types'
5
4
  require_relative 'frame_downloader'
@@ -11,32 +10,36 @@ module Frameit
11
10
  def self.get_template(screenshot)
12
11
  return nil if screenshot.mac?
13
12
 
14
- filename = "Apple #{screenshot.device_name} #{screenshot.color}"
15
-
13
+ filename = create_file_name(screenshot.device_name, screenshot.color.nil? ? screenshot.default_color : screenshot.color)
16
14
  templates = Dir["#{FrameDownloader.templates_path}/#{filename}.{png,jpg}"] # ~/.frameit folder
17
15
 
18
16
  UI.verbose("Looking for #{filename} and found #{templates.count} template(s)")
19
17
 
18
+ return filename if Helper.test?
19
+ if templates.count == 0 && !screenshot.color.nil? && screenshot.color != screenshot.default_color
20
+ filename = create_file_name(screenshot.device_name, screenshot.default_color)
21
+ UI.important("Unfortunately device type '#{screenshot.device_name}' is not available in #{screenshot.color}, falling back to " + (screenshot.default_color.nil? ? "default" : screenshot.default_color) + "...")
22
+ templates = Dir["#{FrameDownloader.templates_path}/#{filename}.{png,jpg}"] # ~/.frameit folder
23
+ UI.verbose("Looking for #{filename} and found #{templates.count} template(s)")
24
+ end
25
+
20
26
  if templates.count == 0
21
- if screenshot.screen_size == Deliver::AppScreenshot::ScreenSize::IOS_35
27
+ if screenshot.deliver_screen_id == Deliver::AppScreenshot::ScreenSize::IOS_35
22
28
  UI.important("Unfortunately 3.5\" device frames were discontinued. Skipping screen '#{screenshot.path}'")
23
29
  UI.error("Looked for: '#{filename}.png'")
24
- elsif screenshot.color == Frameit::Color::ROSE_GOLD || screenshot.color == Frameit::Color::GOLD
25
- # Unfortunately not every device type is available in rose gold or gold
26
- # This is why we can't have nice things #yatusabes
27
- # fallback to a white iPhone, which looks similar
28
- UI.important("Unfortunately device type '#{screenshot.device_name}' is not available in #{screenshot.color}, falling back to silver...")
29
- screenshot.color = Frameit::Color::SILVER
30
- return self.get_template(screenshot)
31
30
  else
32
31
  UI.error("Couldn't find template for screenshot type '#{filename}'")
33
32
  UI.error("Please run `fastlane frameit download_frames` to download the latest frames")
34
33
  end
35
- return filename if Helper.test?
36
34
  return nil
37
35
  else
38
36
  return templates.first.tr(" ", "\ ")
39
37
  end
40
38
  end
39
+
40
+ def self.create_file_name(device_name, color)
41
+ return "#{device_name} #{color}" unless color.nil?
42
+ return device_name
43
+ end
41
44
  end
42
45
  end
@@ -45,7 +45,7 @@ module Match
45
45
  end
46
46
 
47
47
  # This method is called from both here, and from `openssl.rb`
48
- def self.ask_password(message: "Passphrase for Git Repo: ", confirm: nil)
48
+ def self.ask_password(message: "Passphrase for Match storage: ", confirm: nil)
49
49
  ensure_ui_interactive
50
50
  loop do
51
51
  password = UI.password(message)
@@ -14,6 +14,10 @@ module Match
14
14
  },
15
15
  "google_cloud" => lambda { |params|
16
16
  return nil
17
+ },
18
+ "s3" => lambda { |params|
19
+ params[:keychain_name] = params[:s3_bucket]
20
+ return Encryption::OpenSSL.configure(params)
17
21
  }
18
22
  }
19
23
  end
@@ -54,9 +54,9 @@ module Match
54
54
 
55
55
  case cert_type
56
56
  when :development
57
- certificate_type = Spaceship::ConnectAPI::Certificate::CertificateType::IOS_DEVELOPMENT
57
+ certificate_type = Spaceship::ConnectAPI::Certificate::CertificateType::IOS_DEVELOPMENT + "," + Spaceship::ConnectAPI::Certificate::CertificateType::DEVELOPMENT
58
58
  when :distribution, :enterprise
59
- certificate_type = Spaceship::ConnectAPI::Certificate::CertificateType::IOS_DISTRIBUTION
59
+ certificate_type = Spaceship::ConnectAPI::Certificate::CertificateType::IOS_DISTRIBUTION + "," + Spaceship::ConnectAPI::Certificate::CertificateType::DISTRIBUTION
60
60
  else
61
61
  UI.user_error!("Cert type '#{cert_type}' is not supported")
62
62
  end
@@ -13,7 +13,7 @@ module Match
13
13
  end
14
14
 
15
15
  def self.storage_modes
16
- return %w(git google_cloud)
16
+ return %w(git google_cloud s3)
17
17
  end
18
18
 
19
19
  def self.profile_type_sym(type)
@@ -37,7 +37,11 @@ module Match
37
37
  clone_branch_directly: params[:clone_branch_directly],
38
38
  google_cloud_bucket_name: params[:google_cloud_bucket_name].to_s,
39
39
  google_cloud_keys_file: params[:google_cloud_keys_file].to_s,
40
- google_cloud_project_id: params[:google_cloud_project_id].to_s
40
+ google_cloud_project_id: params[:google_cloud_project_id].to_s,
41
+ s3_region: params[:s3_region].to_s,
42
+ s3_access_key: params[:s3_access_key].to_s,
43
+ s3_secret_access_key: params[:s3_secret_access_key].to_s,
44
+ s3_bucket: params[:s3_bucket].to_s
41
45
  })
42
46
  self.storage.download
43
47
 
@@ -159,6 +159,24 @@ module Match
159
159
  description: "ID of the Google Cloud project to use for authentication",
160
160
  optional: true),
161
161
 
162
+ # Storage: S3
163
+ FastlaneCore::ConfigItem.new(key: :s3_region,
164
+ env_name: "MATCH_S3_REGION",
165
+ description: "Name of the S3 region",
166
+ optional: true),
167
+ FastlaneCore::ConfigItem.new(key: :s3_access_key,
168
+ env_name: "MATCH_S3_ACCESS_KEY",
169
+ description: "S3 access key",
170
+ optional: true),
171
+ FastlaneCore::ConfigItem.new(key: :s3_secret_access_key,
172
+ env_name: "MATCH_S3_SECRET_ACCESS_KEY",
173
+ description: "S3 secret secret access key",
174
+ optional: true),
175
+ FastlaneCore::ConfigItem.new(key: :s3_bucket,
176
+ env_name: "MATCH_S3_BUCKET",
177
+ description: "Name of the S3 bucket",
178
+ optional: true),
179
+
162
180
  # Keychain
163
181
  FastlaneCore::ConfigItem.new(key: :keychain_name,
164
182
  short_option: "-s",
@@ -46,6 +46,10 @@ module Match
46
46
  google_cloud_bucket_name: params[:google_cloud_bucket_name].to_s,
47
47
  google_cloud_keys_file: params[:google_cloud_keys_file].to_s,
48
48
  google_cloud_project_id: params[:google_cloud_project_id].to_s,
49
+ s3_region: params[:s3_region].to_s,
50
+ s3_access_key: params[:s3_access_key].to_s,
51
+ s3_secret_access_key: params[:s3_secret_access_key].to_s,
52
+ s3_bucket: params[:s3_bucket].to_s,
49
53
  readonly: params[:readonly],
50
54
  username: params[:readonly] ? nil : params[:username], # only pass username if not readonly
51
55
  team_id: params[:team_id],
@@ -34,7 +34,7 @@ module Match
34
34
  end
35
35
 
36
36
  def storage_options
37
- return ["git", "google_cloud"]
37
+ return ["git", "google_cloud", "s3"]
38
38
  end
39
39
  end
40
40
  end
@@ -1,6 +1,7 @@
1
1
  require_relative 'storage/interface'
2
2
  require_relative 'storage/git_storage'
3
3
  require_relative 'storage/google_cloud_storage'
4
+ require_relative 'storage/s3_storage'
4
5
 
5
6
  module Match
6
7
  module Storage
@@ -12,6 +13,9 @@ module Match
12
13
  },
13
14
  "google_cloud" => lambda { |params|
14
15
  return Storage::GoogleCloudStorage.configure(params)
16
+ },
17
+ "s3" => lambda { |params|
18
+ return Storage::S3Storage.configure(params)
15
19
  }
16
20
  }
17
21
  end
@@ -0,0 +1,162 @@
1
+ require 'fastlane_core/command_executor'
2
+ require 'fastlane_core/configuration/configuration'
3
+ require 'fastlane/helper/s3_client_helper'
4
+
5
+ require_relative '../options'
6
+ require_relative '../module'
7
+ require_relative '../spaceship_ensure'
8
+ require_relative './interface'
9
+
10
+ module Match
11
+ module Storage
12
+ # Store the code signing identities on AWS S3
13
+ class S3Storage < Interface
14
+ attr_reader :s3_bucket
15
+ attr_reader :s3_region
16
+ attr_reader :s3_client
17
+ attr_reader :readonly
18
+ attr_reader :username
19
+ attr_reader :team_id
20
+ attr_reader :team_name
21
+
22
+ def self.configure(params)
23
+ s3_region = params[:s3_region]
24
+ s3_access_key = params[:s3_access_key]
25
+ s3_secret_access_key = params[:s3_secret_access_key]
26
+ s3_bucket = params[:s3_bucket]
27
+
28
+ if params[:git_url].to_s.length > 0
29
+ UI.important("Looks like you still define a `git_url` somewhere, even though")
30
+ UI.important("you use S3 Storage. You can remove the `git_url`")
31
+ UI.important("from your Matchfile and Fastfile")
32
+ UI.message("The above is just a warning, fastlane will continue as usual now...")
33
+ end
34
+
35
+ return self.new(
36
+ s3_region: s3_region,
37
+ s3_access_key: s3_access_key,
38
+ s3_secret_access_key: s3_secret_access_key,
39
+ s3_bucket: s3_bucket,
40
+ readonly: params[:readonly],
41
+ username: params[:username],
42
+ team_id: params[:team_id],
43
+ team_name: params[:team_name]
44
+ )
45
+ end
46
+
47
+ def initialize(s3_region: nil,
48
+ s3_access_key: nil,
49
+ s3_secret_access_key: nil,
50
+ s3_bucket: nil,
51
+ readonly: nil,
52
+ username: nil,
53
+ team_id: nil,
54
+ team_name: nil)
55
+ @s3_bucket = s3_bucket
56
+ @s3_region = s3_region
57
+ @s3_client = Fastlane::Helper::S3ClientHelper.new(access_key: s3_access_key, secret_access_key: s3_secret_access_key, region: s3_region)
58
+ @readonly = readonly
59
+ @username = username
60
+ @team_id = team_id
61
+ @team_name = team_name
62
+ end
63
+
64
+ # To make debugging easier, we have a custom exception here
65
+ def prefixed_working_directory
66
+ # We fall back to "*", which means certificates and profiles
67
+ # from all teams that use this bucket would be installed. This is not ideal, but
68
+ # unless the user provides a `team_id`, we can't know which one to use
69
+ # This only happens if `readonly` is activated, and no `team_id` was provided
70
+ @_folder_prefix ||= currently_used_team_id
71
+ if @_folder_prefix.nil?
72
+ # We use a `@_folder_prefix` variable, to keep state between multiple calls of this
73
+ # method, as the value won't change. This way the warning is only printed once
74
+ UI.important("Looks like you run `match` in `readonly` mode, and didn't provide a `team_id`. This will still work, however it is recommended to provide a `team_id` in your Appfile or Matchfile")
75
+ @_folder_prefix = "*"
76
+ end
77
+ return File.join(working_directory, @_folder_prefix)
78
+ end
79
+
80
+ # Call this method for the initial clone/download of the
81
+ # user's certificates & profiles
82
+ # As part of this method, the `self.working_directory` attribute
83
+ # will be set
84
+ def download
85
+ # Check if we already have a functional working_directory
86
+ return if @working_directory && Dir.exist?(@working_directory)
87
+
88
+ # No existing working directory, creating a new one now
89
+ self.working_directory = Dir.mktmpdir
90
+
91
+ s3_client.find_bucket!(s3_bucket).objects.each do |object|
92
+ file_path = object.public_url.to_s.split("s3.amazonaws.com/").last
93
+ download_path = File.join(self.working_directory, file_path)
94
+
95
+ FileUtils.mkdir_p(File.expand_path("..", download_path))
96
+ UI.verbose("Downloading file from S3 '#{file_path}' on bucket #{self.s3_bucket}")
97
+
98
+ object.download_file(download_path)
99
+ end
100
+ UI.verbose("Successfully downloaded files from S3 to #{self.working_directory}")
101
+ end
102
+
103
+ # Returns a short string describing + identifing the current
104
+ # storage backend. This will be printed when nuking a storage
105
+ def human_readable_description
106
+ return "S3 Bucket [#{s3_bucket}] on region #{s3_region}"
107
+ end
108
+
109
+ def upload_files(files_to_upload: [], custom_message: nil)
110
+ # `files_to_upload` is an array of files that need to be uploaded to S3
111
+ # Those doesn't mean they're new, it might just be they're changed
112
+ # Either way, we'll upload them using the same technique
113
+
114
+ files_to_upload.each do |current_file|
115
+ # Go from
116
+ # "/var/folders/px/bz2kts9n69g8crgv4jpjh6b40000gn/T/d20181026-96528-1av4gge/profiles/development/Development_me.mobileprovision"
117
+ # to
118
+ # "profiles/development/Development_me.mobileprovision"
119
+ #
120
+
121
+ target_path = current_file.gsub(self.working_directory + "/", "")
122
+ UI.verbose("Uploading '#{target_path}' to S3 Storage...")
123
+
124
+ body = File.read(current_file)
125
+ acl = 'private'
126
+ s3_url = s3_client.upload_file(s3_bucket, target_path, body, acl)
127
+ UI.verbose("Uploaded '#{s3_url}' to S3 Storage.")
128
+ end
129
+ end
130
+
131
+ def delete_files(files_to_delete: [], custom_message: nil)
132
+ files_to_delete.each do |file_name|
133
+ s3_client.delete_file(s3_bucket, file_name)
134
+ end
135
+ end
136
+
137
+ def skip_docs
138
+ false
139
+ end
140
+
141
+ # Implement this for the `fastlane match init` command
142
+ # This method must return the content of the Matchfile
143
+ # that should be generated
144
+ def generate_matchfile_content(template: nil)
145
+ return "s3_bucket(\"#{self.s3_bucket}\")"
146
+ end
147
+
148
+ private
149
+
150
+ def currently_used_team_id
151
+ if self.readonly
152
+ # In readonly mode, we still want to see if the user provided a team_id
153
+ # see `prefixed_working_directory` comments for more details
154
+ return self.team_id
155
+ else
156
+ spaceship = SpaceshipEnsure.new(self.username, self.team_id, self.team_name)
157
+ return spaceship.team_id
158
+ end
159
+ end
160
+ end
161
+ end
162
+ end