Class: Match::Nuke
- Inherits:
-
Object
- Object
- Match::Nuke
- Defined in:
- match/lib/match/nuke.rb
Instance Attribute Summary collapse
-
#certs ⇒ Object
Returns the value of attribute certs.
-
#encryption ⇒ Object
Returns the value of attribute encryption.
-
#files ⇒ Object
Returns the value of attribute files.
-
#params ⇒ Object
Returns the value of attribute params.
-
#profiles ⇒ Object
Returns the value of attribute profiles.
-
#storage ⇒ Object
Returns the value of attribute storage.
-
#type ⇒ Object
Returns the value of attribute type.
Instance Method Summary collapse
- #nuke_it_now! ⇒ Object
-
#prepare_list ⇒ Object
Collect all the certs/profiles.
-
#print_tables ⇒ Object
Print tables to ask the user.
- #run(params, type: nil) ⇒ Object
- #spaceship_login ⇒ Object
-
#update_optional_values_depending_on_storage_type(params) ⇒ Object
Be smart about optional values here Depending on the storage mode, different values are required.
Instance Attribute Details
#certs ⇒ Object
Returns the value of attribute certs.
17 18 19 |
# File 'match/lib/match/nuke.rb', line 17 def certs @certs end |
#encryption ⇒ Object
Returns the value of attribute encryption.
22 23 24 |
# File 'match/lib/match/nuke.rb', line 22 def encryption @encryption end |
#files ⇒ Object
Returns the value of attribute files.
19 20 21 |
# File 'match/lib/match/nuke.rb', line 19 def files @files end |
#params ⇒ Object
Returns the value of attribute params.
14 15 16 |
# File 'match/lib/match/nuke.rb', line 14 def params @params end |
#profiles ⇒ Object
Returns the value of attribute profiles.
18 19 20 |
# File 'match/lib/match/nuke.rb', line 18 def profiles @profiles end |
#storage ⇒ Object
Returns the value of attribute storage.
21 22 23 |
# File 'match/lib/match/nuke.rb', line 21 def storage @storage end |
#type ⇒ Object
Returns the value of attribute type.
15 16 17 |
# File 'match/lib/match/nuke.rb', line 15 def type @type end |
Instance Method Details
#nuke_it_now! ⇒ Object
227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 |
# File 'match/lib/match/nuke.rb', line 227 def nuke_it_now! UI.header("Deleting #{self.profiles.count} provisioning profiles...") unless self.profiles.count == 0 self.profiles.each do |profile| UI.("Deleting profile '#{profile.name}' (#{profile.id})...") begin profile.delete! rescue => ex UI.(ex.to_s) end UI.success("Successfully deleted profile") end UI.header("Revoking #{self.certs.count} certificates...") unless self.certs.count == 0 self.certs.each do |cert| UI.("Revoking certificate '#{cert.name}' (#{cert.id})...") begin cert.delete! rescue => ex UI.(ex.to_s) end UI.success("Successfully deleted certificate") end if self.files.count > 0 files_to_delete = delete_files! end self.encryption.encrypt_files if self.encryption if files_to_delete.count > 0 # Now we need to save all this to the storage too, if needed = ["[fastlane]", "Nuked", "files", "for", type.to_s].join(" ") self.storage.save_changes!(files_to_commit: [], files_to_delete: files_to_delete, custom_message: ) else UI.("Your storage had no files to be deleted. This happens when you run `nuke` with an empty storage. Nothing to be worried about!") end end |
#prepare_list ⇒ Object
Collect all the certs/profiles
126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 |
# File 'match/lib/match/nuke.rb', line 126 def prepare_list UI.("Fetching certificates and profiles...") cert_type = Match.cert_type_sym(type) cert_types = [cert_type] prov_types = [] prov_types = [:development] if cert_type == :development prov_types = [:appstore, :adhoc, :developer_id] if cert_type == :distribution prov_types = [:enterprise] if cert_type == :enterprise # Get all iOS and macOS profile self.profiles = [] prov_types.each do |prov_type| types = profile_types(prov_type) # Filtering on 'profileType' seems to be undocumented as of 2020-07-30 # but works on both web session and official API self.profiles += Spaceship::ConnectAPI::Profile.all(filter: { profileType: types.join(",") }) end # Gets the main and additional cert types cert_types += (params[:additional_cert_types] || []).map do |ct| Match.cert_type_sym(ct) end # Gets all the certs form the cert types self.certs = [] self.certs += cert_types.map do |ct| certificate_type(ct).flat_map do |cert| Spaceship::ConnectAPI::Certificate.all(filter: { certificateType: cert }) end end.flatten # Finds all the .cer and .p12 files in the file storage certs = [] keys = [] cert_types.each do |ct| certs += self.storage.list_files(file_name: ct.to_s, file_ext: "cer") keys += self.storage.list_files(file_name: ct.to_s, file_ext: "p12") end # Finds all the iOS and macOS profofiles in the file storage profiles = [] prov_types.each do |prov_type| profiles += self.storage.list_files(file_name: prov_type.to_s, file_ext: "mobileprovision") profiles += self.storage.list_files(file_name: prov_type.to_s, file_ext: "provisionprofile") end self.files = certs + keys + profiles end |
#print_tables ⇒ Object
Print tables to ask the user
177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 |
# File 'match/lib/match/nuke.rb', line 177 def print_tables puts("") if self.certs.count > 0 rows = self.certs.collect do |cert| cert_expiration = cert.expiration_date.nil? ? "Unknown" : Time.parse(cert.expiration_date).strftime("%Y-%m-%d") [cert.name, cert.id, cert.class.to_s.split("::").last, cert_expiration] end puts(Terminal::Table.new({ title: "Certificates that are going to be revoked".green, headings: ["Name", "ID", "Type", "Expires"], rows: FastlaneCore::PrintTable.transform_output(rows) })) puts("") end if self.profiles.count > 0 rows = self.profiles.collect do |p| status = p.valid? ? p.profile_state.green : p.profile_state.red # Expires is sometimes nil expires = p.expiration_date ? Time.parse(p.expiration_date).strftime("%Y-%m-%d") : nil [p.name, p.id, status, p.profile_type, expires] end puts(Terminal::Table.new({ title: "Provisioning Profiles that are going to be revoked".green, headings: ["Name", "ID", "Status", "Type", "Expires"], rows: FastlaneCore::PrintTable.transform_output(rows) })) puts("") end if self.files.count > 0 rows = self.files.collect do |f| components = f.split(File::SEPARATOR)[-3..-1] # from "...1o7xtmh/certs/distribution/8K38XUY3AY.cer" to "distribution cert" file_type = components[0..1].reverse.join(" ")[0..-2] [file_type, components[2]] end puts(Terminal::Table.new({ title: "Files that are going to be deleted".green + "\n" + self.storage.human_readable_description, headings: ["Type", "File Name"], rows: rows })) puts("") end end |
#run(params, type: nil) ⇒ Object
24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 |
# File 'match/lib/match/nuke.rb', line 24 def run(params, type: nil) self.params = params self.type = type update_optional_values_depending_on_storage_type(params) spaceship_login self.storage = Storage.for_mode(params[:storage_mode], { git_url: params[:git_url], shallow_clone: params[:shallow_clone], skip_docs: params[:skip_docs], git_branch: params[:git_branch], git_full_name: params[:git_full_name], git_user_email: params[:git_user_email], git_private_key: params[:git_private_key], git_basic_authorization: params[:git_basic_authorization], git_bearer_authorization: params[:git_bearer_authorization], clone_branch_directly: params[:clone_branch_directly], google_cloud_bucket_name: params[:google_cloud_bucket_name].to_s, google_cloud_keys_file: params[:google_cloud_keys_file].to_s, google_cloud_project_id: params[:google_cloud_project_id].to_s, s3_region: params[:s3_region].to_s, s3_access_key: params[:s3_access_key].to_s, s3_secret_access_key: params[:s3_secret_access_key].to_s, s3_bucket: params[:s3_bucket].to_s, team_id: params[:team_id] || Spaceship::ConnectAPI.client.portal_team_id }) self.storage.download # After the download was complete self.encryption = Encryption.for_storage_mode(params[:storage_mode], { git_url: params[:git_url], working_directory: storage.working_directory }) self.encryption.decrypt_files if self.encryption had_app_identifier = self.params.fetch(:app_identifier, ask: false) self.params[:app_identifier] = '' # we don't really need a value here FastlaneCore::PrintTable.print_values(config: params, hide_keys: [:app_identifier], title: "Summary for match nuke #{Fastlane::VERSION}") prepare_list print_tables if params[:readonly] UI.user_error!("`fastlane match nuke` doesn't delete anything when running with --readonly enabled") end if (self.certs + self.profiles + self.files).count > 0 unless params[:skip_confirmation] UI.error("---") UI.error("Are you sure you want to completely delete and revoke all the") UI.error("certificates and provisioning profiles listed above? (y/n)") UI.error("Warning: By nuking distribution, both App Store and Ad Hoc profiles will be deleted") if type == "distribution" UI.error("Warning: The :app_identifier value will be ignored - this will delete all profiles for all your apps!") if had_app_identifier UI.error("---") end if params[:skip_confirmation] || UI.confirm("Do you really want to nuke everything listed above?") nuke_it_now! UI.success("Successfully cleaned your account ♻️") else UI.success("Cancelled nuking #thanks 🏠 👨 👩 👧") end else UI.success("No relevant certificates or provisioning profiles found, nothing to nuke here :)") end end |
#spaceship_login ⇒ Object
104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 |
# File 'match/lib/match/nuke.rb', line 104 def spaceship_login if (api_token = Spaceship::ConnectAPI::Token.from(hash: params[:api_key], filepath: params[:api_key_path])) UI.("Creating authorization token for App Store Connect API") Spaceship::ConnectAPI.token = api_token elsif !Spaceship::ConnectAPI.token.nil? UI.("Using existing authorization token for App Store Connect API") else Spaceship::ConnectAPI.login(params[:username], use_portal: true, use_tunes: false, portal_team_id: params[:team_id], team_name: params[:team_name]) end if Spaceship::ConnectAPI.client.in_house? && (type == "distribution" || type == "enterprise") UI.error("---") UI.error("⚠️ Warning: This seems to be an Enterprise account!") UI.error("By nuking your account's distribution, all your apps deployed via ad-hoc will stop working!") if type == "distribution" UI.error("By nuking your account's enterprise, all your in-house apps will stop working!") if type == "enterprise" UI.error("---") UI.user_error!("Enterprise account nuke cancelled") unless UI.confirm("Do you really want to nuke your Enterprise account?") end end |
#update_optional_values_depending_on_storage_type(params) ⇒ Object
Be smart about optional values here Depending on the storage mode, different values are required
98 99 100 101 102 |
# File 'match/lib/match/nuke.rb', line 98 def update_optional_values_depending_on_storage_type(params) if params[:storage_mode] != "git" params.option_for_key(:git_url).optional = true end end |