fastlane-plugin-match_import 0.1.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE +21 -0
- data/README.md +149 -0
- data/lib/fastlane/plugin/match_import/actions/match_export_action.rb +49 -0
- data/lib/fastlane/plugin/match_import/actions/match_export_apns_action.rb +47 -0
- data/lib/fastlane/plugin/match_import/actions/match_import_action.rb +49 -0
- data/lib/fastlane/plugin/match_import/actions/match_import_apns_action.rb +47 -0
- data/lib/fastlane/plugin/match_import/actions/match_remove_action.rb +49 -0
- data/lib/fastlane/plugin/match_import/actions/match_remove_invalid_apns_action.rb +47 -0
- data/lib/fastlane/plugin/match_import/apns_export_file_options.rb +34 -0
- data/lib/fastlane/plugin/match_import/apns_file_options.rb +42 -0
- data/lib/fastlane/plugin/match_import/apns_remove_invalid_file_options.rb +30 -0
- data/lib/fastlane/plugin/match_import/commands_generator.rb +159 -0
- data/lib/fastlane/plugin/match_import/custom_file_options.rb +43 -0
- data/lib/fastlane/plugin/match_import/encryption/openssl.rb +18 -0
- data/lib/fastlane/plugin/match_import/helper/match_import_helper.rb +16 -0
- data/lib/fastlane/plugin/match_import/options.rb +26 -0
- data/lib/fastlane/plugin/match_import/runner.rb +153 -0
- data/lib/fastlane/plugin/match_import/runner_apns.rb +295 -0
- data/lib/fastlane/plugin/match_import/utils.rb +81 -0
- data/lib/fastlane/plugin/match_import/version.rb +6 -0
- data/lib/fastlane/plugin/match_import.rb +26 -0
- metadata +189 -0
@@ -0,0 +1,159 @@
|
|
1
|
+
require 'commander'
|
2
|
+
require 'fastlane_core/configuration/configuration'
|
3
|
+
|
4
|
+
require_relative '../match_import'
|
5
|
+
|
6
|
+
HighLine.track_eof = false
|
7
|
+
module Fastlane
|
8
|
+
module MatchImport
|
9
|
+
class CommandsGenerator
|
10
|
+
include Commander::Methods
|
11
|
+
|
12
|
+
def self.start
|
13
|
+
self.new.run
|
14
|
+
end
|
15
|
+
|
16
|
+
def run
|
17
|
+
program :name, 'match_import'
|
18
|
+
program :version, Fastlane::MatchImport::VERSION
|
19
|
+
program :description, Fastlane::MatchImport::DESCRIPTION
|
20
|
+
program :help, 'Author', 'Sergii Batsevych <serbats@ukr.net>'
|
21
|
+
program :help, 'Website', 'https://fastlane.tools'
|
22
|
+
program :help, 'GitHub', 'https://github.com/serbats/fastlane-plugin-match_import'
|
23
|
+
program :help_formatter, :compact
|
24
|
+
|
25
|
+
global_option('--verbose') { FastlaneCore::Globals.verbose = true }
|
26
|
+
|
27
|
+
command :import do |c|
|
28
|
+
c.syntax = 'match_import import'
|
29
|
+
c.description = Fastlane::MatchImport::DESCRIPTION
|
30
|
+
|
31
|
+
FastlaneCore::CommanderGenerator.new.generate(Fastlane::MatchImport::CustomFileOptions.available_options, command: c)
|
32
|
+
|
33
|
+
c.action do |args, options|
|
34
|
+
if args.count > 0
|
35
|
+
FastlaneCore::UI.user_error!("Please run `match_import import --file_name='*.txt' --source_path='testDir' --destination_path='repoDir'`")
|
36
|
+
end
|
37
|
+
|
38
|
+
params = FastlaneCore::Configuration.create(Fastlane::MatchImport::CustomFileOptions.available_options, options.__hash__)
|
39
|
+
params.load_configuration_file("Matchfile")
|
40
|
+
|
41
|
+
Match::Encryption.register_backend(type: "git", encryption_class: MatchImport::Encryption::OpenSSL)
|
42
|
+
Match::Encryption.register_backend(type: "s3", encryption_class: MatchImport::Encryption::OpenSSL)
|
43
|
+
|
44
|
+
Fastlane::MatchImport::Runner.new.run(params)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
command :export do |c|
|
49
|
+
c.syntax = 'match_import export'
|
50
|
+
c.description = Fastlane::MatchImport::DESCRIPTION
|
51
|
+
|
52
|
+
FastlaneCore::CommanderGenerator.new.generate(Fastlane::MatchImport::CustomFileOptions.available_options, command: c)
|
53
|
+
|
54
|
+
c.action do |args, options|
|
55
|
+
if args.count > 0
|
56
|
+
FastlaneCore::UI.user_error!("Please run `match_import export --file_name='*.txt' --source_path='repoDir' --destination_path='testDir'`")
|
57
|
+
end
|
58
|
+
|
59
|
+
params = FastlaneCore::Configuration.create(Fastlane::MatchImport::CustomFileOptions.available_options, options.__hash__)
|
60
|
+
params.load_configuration_file("Matchfile")
|
61
|
+
|
62
|
+
Match::Encryption.register_backend(type: "git", encryption_class: MatchImport::Encryption::OpenSSL)
|
63
|
+
Match::Encryption.register_backend(type: "s3", encryption_class: MatchImport::Encryption::OpenSSL)
|
64
|
+
|
65
|
+
Fastlane::MatchImport::Runner.new.run_export(params)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
command :remove do |c|
|
70
|
+
c.syntax = 'match_import remove'
|
71
|
+
c.description = Fastlane::MatchImport::DESCRIPTION
|
72
|
+
|
73
|
+
FastlaneCore::CommanderGenerator.new.generate(Fastlane::MatchImport::CustomFileOptions.available_options, command: c)
|
74
|
+
|
75
|
+
c.action do |args, options|
|
76
|
+
if args.count > 0
|
77
|
+
FastlaneCore::UI.user_error!("Please run `match_import remove --file_name='*.txt' --source_path='repoDir'`")
|
78
|
+
end
|
79
|
+
|
80
|
+
params = FastlaneCore::Configuration.create(Fastlane::MatchImport::CustomFileOptions.available_options, options.__hash__)
|
81
|
+
params.load_configuration_file("Matchfile")
|
82
|
+
|
83
|
+
Match::Encryption.register_backend(type: "git", encryption_class: MatchImport::Encryption::OpenSSL)
|
84
|
+
Match::Encryption.register_backend(type: "s3", encryption_class: MatchImport::Encryption::OpenSSL)
|
85
|
+
|
86
|
+
Fastlane::MatchImport::Runner.new.run_remove(params)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
command :import_apns do |c|
|
91
|
+
c.syntax = 'match_import import_apns'
|
92
|
+
c.description = Fastlane::MatchImport::DESCRIPTION
|
93
|
+
|
94
|
+
FastlaneCore::CommanderGenerator.new.generate(Fastlane::MatchImport::APNSFileOptions.available_options, command: c)
|
95
|
+
|
96
|
+
c.action do |args, options|
|
97
|
+
if args.count > 0
|
98
|
+
FastlaneCore::UI.user_error!("Please run `match_import import_apns --type='development' --cert_file_name='PushDev.cer' --p12_file_name='PushDev.p12'`")
|
99
|
+
end
|
100
|
+
|
101
|
+
params = FastlaneCore::Configuration.create(Fastlane::MatchImport::APNSFileOptions.available_options, options.__hash__)
|
102
|
+
params.load_configuration_file("Matchfile")
|
103
|
+
|
104
|
+
Match::Encryption.register_backend(type: "git", encryption_class: MatchImport::Encryption::OpenSSL)
|
105
|
+
Match::Encryption.register_backend(type: "s3", encryption_class: MatchImport::Encryption::OpenSSL)
|
106
|
+
|
107
|
+
Fastlane::MatchImport::RunnerAPNS.new.run(params)
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
command :export_apns do |c|
|
112
|
+
c.syntax = 'match_import export_apns'
|
113
|
+
c.description = Fastlane::MatchImport::DESCRIPTION
|
114
|
+
|
115
|
+
FastlaneCore::CommanderGenerator.new.generate(Fastlane::MatchImport::APNSExportFileOptions.available_options, command: c)
|
116
|
+
|
117
|
+
c.action do |args, options|
|
118
|
+
if args.count > 0
|
119
|
+
FastlaneCore::UI.user_error!("Please run `match_import export_apns --type='development' --keychain_name='FastlaneKeychain' --keychain_password='password' --destination_path='testDir'`")
|
120
|
+
end
|
121
|
+
|
122
|
+
params = FastlaneCore::Configuration.create(Fastlane::MatchImport::APNSExportFileOptions.available_options, options.__hash__)
|
123
|
+
params.load_configuration_file("Matchfile")
|
124
|
+
|
125
|
+
Match::Encryption.register_backend(type: "git", encryption_class: MatchImport::Encryption::OpenSSL)
|
126
|
+
Match::Encryption.register_backend(type: "s3", encryption_class: MatchImport::Encryption::OpenSSL)
|
127
|
+
|
128
|
+
Fastlane::MatchImport::RunnerAPNS.new.run_export(params)
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
command :remove_invalid_apns do |c|
|
133
|
+
c.syntax = 'match_import remove_invalid_apns'
|
134
|
+
c.description = Fastlane::MatchImport::DESCRIPTION
|
135
|
+
|
136
|
+
FastlaneCore::CommanderGenerator.new.generate(Fastlane::MatchImport::APNSRemoveInvalidFileOptions.available_options, command: c)
|
137
|
+
|
138
|
+
c.action do |args, options|
|
139
|
+
if args.count > 0
|
140
|
+
FastlaneCore::UI.user_error!("Please run `match_import remove_invalid_apns --type='development'`")
|
141
|
+
end
|
142
|
+
|
143
|
+
params = FastlaneCore::Configuration.create(Fastlane::MatchImport::APNSRemoveInvalidFileOptions.available_options, options.__hash__)
|
144
|
+
params.load_configuration_file("Matchfile")
|
145
|
+
|
146
|
+
Match::Encryption.register_backend(type: "git", encryption_class: MatchImport::Encryption::OpenSSL)
|
147
|
+
Match::Encryption.register_backend(type: "s3", encryption_class: MatchImport::Encryption::OpenSSL)
|
148
|
+
|
149
|
+
Fastlane::MatchImport::RunnerAPNS.new.run_remove_invalid(params)
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
default_command(:import)
|
154
|
+
|
155
|
+
run!
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
|
2
|
+
require 'fastlane_core'
|
3
|
+
require 'match'
|
4
|
+
|
5
|
+
module Fastlane
|
6
|
+
module MatchImport
|
7
|
+
class CustomFileOptions
|
8
|
+
def self.exclude_match_options
|
9
|
+
# [:type, :output_path, :keychain_name, :keychain_password]
|
10
|
+
# Don't know how to exclude unused options and don't get error like:
|
11
|
+
# Could not find option 'type' in the list of available options
|
12
|
+
[]
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.available_options
|
16
|
+
all = Fastlane::MatchImport::Options.available_options
|
17
|
+
|
18
|
+
exclude_match_options.each do |key|
|
19
|
+
(i = all.find_index { |item| item.key == key }) && all.delete_at(i)
|
20
|
+
end
|
21
|
+
|
22
|
+
return all + custom_options
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.custom_options
|
26
|
+
[
|
27
|
+
FastlaneCore::ConfigItem.new(key: :file_name,
|
28
|
+
env_name: "MATCH_IMPORT_FILENAME",
|
29
|
+
description: "File to import. Could contain mask like '*.txt'",
|
30
|
+
optional: false),
|
31
|
+
FastlaneCore::ConfigItem.new(key: :destination_path,
|
32
|
+
env_name: "MATCH_IMPORT_DESTINATION_PATH",
|
33
|
+
description: "Path to copy imported file to",
|
34
|
+
optional: true),
|
35
|
+
FastlaneCore::ConfigItem.new(key: :source_path,
|
36
|
+
env_name: "MATCH_IMPORT_SOURCE_PATH",
|
37
|
+
description: "Path to take importing file from",
|
38
|
+
optional: true)
|
39
|
+
]
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'match'
|
2
|
+
|
3
|
+
module Fastlane
|
4
|
+
module MatchImport
|
5
|
+
module Encryption
|
6
|
+
class OpenSSL < Match::Encryption::OpenSSL
|
7
|
+
def iterate(source_path)
|
8
|
+
super
|
9
|
+
# apns *.cer and *.p12 are encrypted/decrypted by 'super' call
|
10
|
+
Dir[File.join(source_path, "customImport/customImport/customImport", "custom", "**", "*")].each do |path|
|
11
|
+
next if File.directory?(path)
|
12
|
+
yield(path)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'fastlane_core/ui/ui'
|
2
|
+
|
3
|
+
module Fastlane
|
4
|
+
UI = FastlaneCore::UI unless Fastlane.const_defined?("UI")
|
5
|
+
|
6
|
+
module Helper
|
7
|
+
class MatchImportHelper
|
8
|
+
# class methods that you define here become available in your action
|
9
|
+
# as `Helper::MatchImportHelper.your_method`
|
10
|
+
#
|
11
|
+
def self.show_message
|
12
|
+
UI.message("Hello from the match_import plugin helper!")
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
|
2
|
+
require 'fastlane_core'
|
3
|
+
require 'match'
|
4
|
+
|
5
|
+
module Fastlane
|
6
|
+
module MatchImport
|
7
|
+
class Options
|
8
|
+
def self.exclude_match_options
|
9
|
+
# [:output_path, :additional_cert_types, :readonly, :generate_apple_certs, :skip_provisioning_profiles, :force, :force_for_new_devices, :skip_confirmation, :template_name]
|
10
|
+
# Don't know how to exclude unused options and don't get error like:
|
11
|
+
# Could not find option 'type' in the list of available options
|
12
|
+
[]
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.available_options
|
16
|
+
all = Match::Options.available_options
|
17
|
+
|
18
|
+
exclude_match_options.each do |key|
|
19
|
+
(i = all.find_index { |item| item.key == key }) && all.delete_at(i)
|
20
|
+
end
|
21
|
+
|
22
|
+
return all
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,153 @@
|
|
1
|
+
require 'fastlane_core/print_table'
|
2
|
+
|
3
|
+
module Fastlane
|
4
|
+
module MatchImport
|
5
|
+
class Runner
|
6
|
+
attr_accessor :files_to_commit
|
7
|
+
attr_accessor :storage
|
8
|
+
|
9
|
+
def run(params)
|
10
|
+
self.files_to_commit = []
|
11
|
+
|
12
|
+
FastlaneCore::PrintTable.print_values(config: params,
|
13
|
+
hide_keys: [],
|
14
|
+
title: "Summary for match_import #{Fastlane::MatchImport::VERSION}")
|
15
|
+
|
16
|
+
MatchImport::Utils.update_optional_values_depending_on_storage_type(params)
|
17
|
+
|
18
|
+
# Get and verify custom file path
|
19
|
+
file_path = MatchImport::Utils.ensure_valid_file_path(params[:file_name], params[:source_path], "File to import")
|
20
|
+
# Verify destination path is one level dir. Othervise encrypt/decript won't work
|
21
|
+
destination_path = MatchImport::Utils.ensure_valid_one_level_path(params[:destination_path])
|
22
|
+
|
23
|
+
# Choose the right storage and encryption implementations
|
24
|
+
storage = MatchImport::Utils.storage(params, false)
|
25
|
+
|
26
|
+
# Init the encryption only after the `storage.download` was called to have the right working directory
|
27
|
+
encryption = MatchImport::Utils.encryption(params, storage)
|
28
|
+
|
29
|
+
storage_workspace = storage.prefixed_working_directory
|
30
|
+
|
31
|
+
# Hack to avoid conflicts with "fastlane match" encryption.
|
32
|
+
# It uses pattern: [File.join(source_path, "**", "*.{cer,p12,mobileprovision,provisionprofile}")]
|
33
|
+
# To avoid conflicts we use three level deep folder.
|
34
|
+
output_dir = File.join(storage_workspace, "customImport/customImport/customImport", "custom")
|
35
|
+
output_dir = File.join(output_dir, destination_path) if destination_path
|
36
|
+
|
37
|
+
# Make dir if doesn't exist
|
38
|
+
FileUtils.mkdir_p(output_dir)
|
39
|
+
# dest_path = File.join(output_dir, params[:file_name])
|
40
|
+
dest_path = output_dir
|
41
|
+
|
42
|
+
# Copy file
|
43
|
+
# IO.copy_stream(file_path, dest_path)
|
44
|
+
|
45
|
+
Dir[file_path].each do |file|
|
46
|
+
dest_file = File.join(dest_path, File.basename(file))
|
47
|
+
if File.file?(dest_file) && FileUtils.compare_file(file, dest_file)
|
48
|
+
UI.success("File '#{file}' already exist at destination and is unchanged")
|
49
|
+
else
|
50
|
+
self.files_to_commit << dest_path
|
51
|
+
|
52
|
+
FileUtils.cp(file, dest_path)
|
53
|
+
UI.success("Finish copying '#{file}' to '#{dest_path}'") if FastlaneCore::Globals.verbose?
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
if self.files_to_commit.count > 0
|
58
|
+
encryption.encrypt_files if encryption
|
59
|
+
storage.save_changes!(files_to_commit: self.files_to_commit)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def run_export(params)
|
64
|
+
FastlaneCore::PrintTable.print_values(config: params,
|
65
|
+
hide_keys: [],
|
66
|
+
title: "Summary for match_import #{Fastlane::MatchImport::VERSION}")
|
67
|
+
|
68
|
+
MatchImport::Utils.update_optional_values_depending_on_storage_type(params)
|
69
|
+
|
70
|
+
# Verify source path is one level dir. Othervise encrypt/decript won't work
|
71
|
+
source_path = MatchImport::Utils.ensure_valid_one_level_path(params[:source_path])
|
72
|
+
|
73
|
+
# Choose the right storage and encryption implementations
|
74
|
+
storage = MatchImport::Utils.storage(params, true)
|
75
|
+
|
76
|
+
# Init the encryption only after the `storage.download` was called to have the right working directory
|
77
|
+
MatchImport::Utils.encryption(params, storage)
|
78
|
+
|
79
|
+
storage_workspace = storage.prefixed_working_directory
|
80
|
+
|
81
|
+
# Hack to avoid conflicts with "fastlane match" encryption.
|
82
|
+
# It uses pattern: [File.join(source_path, "**", "*.{cer,p12,mobileprovision,provisionprofile}")]
|
83
|
+
# To avoid conflicts we use three level deep folder.
|
84
|
+
input_dir = File.join(storage_workspace, "customImport/customImport/customImport", "custom")
|
85
|
+
source_path = source_path.nil? ? input_dir : File.join(input_dir, source_path)
|
86
|
+
|
87
|
+
# Get and verify custom file path
|
88
|
+
file_path = MatchImport::Utils.ensure_valid_file_path(params[:file_name], source_path, "File to export")
|
89
|
+
|
90
|
+
output_dir = params[:destination_path].nil? ? '.' : params[:destination_path]
|
91
|
+
|
92
|
+
# Make dir if doesn't exist
|
93
|
+
FileUtils.mkdir_p(output_dir)
|
94
|
+
# dest_path = File.join(output_dir, params[:file_name])
|
95
|
+
dest_path = output_dir
|
96
|
+
|
97
|
+
# Copy file
|
98
|
+
# IO.copy_stream(file_path, dest_path)
|
99
|
+
|
100
|
+
Dir[file_path].each do |file|
|
101
|
+
dest_file = File.join(dest_path, File.basename(file))
|
102
|
+
if File.file?(dest_file) && FileUtils.compare_file(file, dest_file)
|
103
|
+
UI.success("File '#{file}' already exist at destination and is unchanged")
|
104
|
+
else
|
105
|
+
FileUtils.cp(file, dest_path)
|
106
|
+
UI.success("Finish copying '#{file}' to '#{dest_path}'") if FastlaneCore::Globals.verbose?
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
def run_remove(params)
|
112
|
+
self.files_to_commit = []
|
113
|
+
|
114
|
+
FastlaneCore::PrintTable.print_values(config: params,
|
115
|
+
hide_keys: [],
|
116
|
+
title: "Summary for match_import #{Fastlane::MatchImport::VERSION}")
|
117
|
+
|
118
|
+
MatchImport::Utils.update_optional_values_depending_on_storage_type(params)
|
119
|
+
|
120
|
+
# Verify source path is one level dir. Othervise encrypt/decript won't work
|
121
|
+
source_path = MatchImport::Utils.ensure_valid_one_level_path(params[:source_path])
|
122
|
+
|
123
|
+
# Choose the right storage and encryption implementations
|
124
|
+
storage = MatchImport::Utils.storage(params, false)
|
125
|
+
|
126
|
+
storage_workspace = storage.prefixed_working_directory
|
127
|
+
|
128
|
+
# Hack to avoid conflicts with "fastlane match" encryption.
|
129
|
+
# It uses pattern: [File.join(source_path, "**", "*.{cer,p12,mobileprovision,provisionprofile}")]
|
130
|
+
# To avoid conflicts we use three level deep folder.
|
131
|
+
input_dir = File.join(storage_workspace, "customImport/customImport/customImport", "custom")
|
132
|
+
source_path = source_path.nil? ? input_dir : File.join(input_dir, source_path)
|
133
|
+
|
134
|
+
# Get and verify custom file path
|
135
|
+
file_path = MatchImport::Utils.ensure_valid_file_path(params[:file_name], source_path, "File to remove")
|
136
|
+
|
137
|
+
# Copy file
|
138
|
+
# IO.copy_stream(file_path, dest_path)
|
139
|
+
|
140
|
+
Dir[file_path].each do |file|
|
141
|
+
self.files_to_commit << file
|
142
|
+
|
143
|
+
FileUtils.rm(file)
|
144
|
+
UI.success("Finish removing '#{file}'") if FastlaneCore::Globals.verbose?
|
145
|
+
end
|
146
|
+
|
147
|
+
if self.files_to_commit.count > 0
|
148
|
+
storage.save_changes!(files_to_commit: self.files_to_commit)
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|