pindo 4.6.9 → 4.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (140) hide show
  1. checksums.yaml +4 -4
  2. data/lib/pindo/base/aeshelper.rb +48 -2
  3. data/lib/pindo/base/funlog.rb +89 -0
  4. data/lib/pindo/base/githelper.rb +30 -12
  5. data/lib/pindo/base/plaininformative.rb +3 -0
  6. data/lib/pindo/base/standarderror.rb +1 -0
  7. data/lib/pindo/base/xcodeconst.rb +251 -0
  8. data/lib/pindo/client/applovinclient.rb +6 -3
  9. data/lib/pindo/client/aws3sclient.rb +33 -46
  10. data/lib/pindo/client/bossclient.rb +1 -1
  11. data/lib/pindo/client/pgyerclient.rb +78 -14
  12. data/lib/pindo/command/appstore/iap.rb +43 -0
  13. data/lib/pindo/command/appstore/itcapp.rb +41 -0
  14. data/lib/pindo/command/appstore/metadata.rb +43 -0
  15. data/lib/pindo/command/appstore/screenshots.rb +43 -0
  16. data/lib/pindo/command/appstore/upload.rb +40 -0
  17. data/lib/pindo/command/appstore.rb +17 -0
  18. data/lib/pindo/command/deploy/build.rb +109 -0
  19. data/lib/pindo/{deploy → command/deploy}/bundleid.rb +1 -1
  20. data/lib/pindo/command/deploy/cert.rb +179 -0
  21. data/lib/pindo/command/deploy/configproj.rb +105 -0
  22. data/lib/pindo/{deploy → command/deploy}/getitcinfo.rb +1 -1
  23. data/lib/pindo/{deploy → command/deploy}/iap.rb +30 -9
  24. data/lib/pindo/{deploy → command/deploy}/itcapp.rb +0 -1
  25. data/lib/pindo/{deploy → command/deploy}/itcinfo.rb +2 -3
  26. data/lib/pindo/{deploy → command/deploy}/pem.rb +3 -2
  27. data/lib/pindo/{deploy → command/deploy}/resign.rb +14 -63
  28. data/lib/pindo/command/deploy.rb +44 -0
  29. data/lib/pindo/{dev → command/dev}/autobuild.rb +17 -80
  30. data/lib/pindo/{dev → command/dev}/autoresign.rb +17 -64
  31. data/lib/pindo/{dev → command/dev}/createbuild.rb +0 -2
  32. data/lib/pindo/{dev → command/dev}/debug.rb +6 -2
  33. data/lib/pindo/command/dev/pgyercert.rb +75 -0
  34. data/lib/pindo/command/dev.rb +25 -0
  35. data/lib/pindo/command/env.rb +17 -0
  36. data/lib/pindo/{ipa → command/ipa}/autoresign.rb +18 -70
  37. data/lib/pindo/{ipa → command/ipa}/import.rb +47 -102
  38. data/lib/pindo/{ipa → command/ipa}/output.rb +38 -135
  39. data/lib/pindo/command/ipa.rb +16 -0
  40. data/lib/pindo/{lib → command/lib}/update.rb +19 -10
  41. data/lib/pindo/command/lib.rb +16 -0
  42. data/lib/pindo/{pgyer → command/pgyer}/apptest.rb +7 -29
  43. data/lib/pindo/{pgyer → command/pgyer}/comment.rb +7 -30
  44. data/lib/pindo/{pgyer → command/pgyer}/download.rb +35 -30
  45. data/lib/pindo/{pgyer → command/pgyer}/login.rb +3 -4
  46. data/lib/pindo/command/pgyer/resign.rb +111 -0
  47. data/lib/pindo/command/pgyer/upload.rb +123 -0
  48. data/lib/pindo/command/pgyer.rb +18 -0
  49. data/lib/pindo/{repo.rb → command/repo.rb} +4 -4
  50. data/lib/pindo/{utils → command/utils}/applovin.rb +43 -33
  51. data/lib/pindo/{utils → command/utils}/boss.rb +3 -3
  52. data/lib/pindo/command/utils/icon.rb +81 -0
  53. data/lib/pindo/{utils → command/utils}/renewproj.rb +1 -0
  54. data/lib/pindo/command/utils.rb +26 -0
  55. data/lib/pindo/command.rb +23 -26
  56. data/lib/pindo/module/build/swarkhelper.rb +95 -0
  57. data/lib/pindo/module/cert/certhelper.rb +176 -0
  58. data/lib/pindo/module/cert/keychainhelper.rb +138 -0
  59. data/lib/pindo/module/{pemcreate.rb → cert/pemhelper.rb} +3 -1
  60. data/lib/pindo/module/cert/provisioninghelper.rb +137 -0
  61. data/lib/pindo/module/cert/xcodecerthelper.rb +301 -0
  62. data/lib/pindo/module/{pgyerhelper.rb → pgyer/pgyerhelper.rb} +246 -35
  63. data/lib/pindo/module/xcode/xcodeappconfig.rb +188 -0
  64. data/lib/pindo/module/xcode/xcodebuildconfig.rb +12 -0
  65. data/lib/pindo/module/xcode/xcodebuildhelper.rb +312 -0
  66. data/lib/pindo/module/xcode/xcoderesconstant.rb +248 -0
  67. data/lib/pindo/module/xcode/xcodereshandler.rb +198 -0
  68. data/lib/pindo/module/xcode/xcodereshelper.rb +120 -0
  69. data/lib/pindo/options/appconfigoptions.rb +1 -0
  70. data/lib/pindo/options/deployoptions.rb +38 -41
  71. data/lib/pindo/version.rb +1 -1
  72. metadata +109 -97
  73. data/lib/pindo/deploy/Fastfile +0 -233
  74. data/lib/pindo/deploy/build.rb +0 -167
  75. data/lib/pindo/deploy/cert.rb +0 -508
  76. data/lib/pindo/deploy/configproj.rb +0 -89
  77. data/lib/pindo/deploy.rb +0 -44
  78. data/lib/pindo/dev.rb +0 -23
  79. data/lib/pindo/env/flutter.rb +0 -59
  80. data/lib/pindo/env/flutter.sh +0 -116
  81. data/lib/pindo/env.rb +0 -17
  82. data/lib/pindo/ipa.rb +0 -22
  83. data/lib/pindo/lib.rb +0 -18
  84. data/lib/pindo/module/buildconfighelper.rb +0 -13
  85. data/lib/pindo/module/buildhelper.rb +0 -76
  86. data/lib/pindo/module/config_project.sh +0 -143
  87. data/lib/pindo/module/configprojhelper.rb +0 -631
  88. data/lib/pindo/module/icon_contents.json +0 -116
  89. data/lib/pindo/module/imessage_icon.json +0 -91
  90. data/lib/pindo/module/imgset_contents.json +0 -21
  91. data/lib/pindo/module/launchimg_contents.json +0 -21
  92. data/lib/pindo/module/xcodebuildpre.rb +0 -258
  93. data/lib/pindo/pgyer/upload.rb +0 -234
  94. data/lib/pindo/pgyer.rb +0 -17
  95. data/lib/pindo/utils/icon.rb +0 -91
  96. data/lib/pindo/utils/icon.sh +0 -133
  97. data/lib/pindo/utils/podindex.rb +0 -56
  98. data/lib/pindo/utils/podindex.sh +0 -30
  99. data/lib/pindo/utils.rb +0 -29
  100. /data/lib/pindo/{deploy → command/deploy}/check.rb +0 -0
  101. /data/lib/pindo/{deploy → command/deploy}/confusecode.rb +0 -0
  102. /data/lib/pindo/{deploy → command/deploy}/confuseproj.rb +0 -0
  103. /data/lib/pindo/{deploy → command/deploy}/fabric.rb +0 -0
  104. /data/lib/pindo/{deploy → command/deploy}/initconfig.rb +0 -0
  105. /data/lib/pindo/{deploy → command/deploy}/pullconfig.rb +0 -0
  106. /data/lib/pindo/{deploy → command/deploy}/pushconfig.rb +0 -0
  107. /data/lib/pindo/{deploy → command/deploy}/quswark.rb +0 -0
  108. /data/lib/pindo/{deploy → command/deploy}/quswauth.rb +0 -0
  109. /data/lib/pindo/{deploy → command/deploy}/reportbug.rb +0 -0
  110. /data/lib/pindo/{deploy → command/deploy}/tag.rb +0 -0
  111. /data/lib/pindo/{deploy → command/deploy}/updateconfig.rb +0 -0
  112. /data/lib/pindo/{deploy → command/deploy}/uploadipa.rb +0 -0
  113. /data/lib/pindo/{dev → command/dev}/confusecode.rb +0 -0
  114. /data/lib/pindo/{dev → command/dev}/confuseproj.rb +0 -0
  115. /data/lib/pindo/{dev → command/dev}/pub.rb +0 -0
  116. /data/lib/pindo/{dev → command/dev}/renewcert.rb +0 -0
  117. /data/lib/pindo/{env → command/env}/dreamstudio.rb +0 -0
  118. /data/lib/pindo/{env → command/env}/quarkenv.rb +0 -0
  119. /data/lib/pindo/{env → command/env}/swarkenv.rb +0 -0
  120. /data/lib/pindo/{env → command/env}/workhard.rb +0 -0
  121. /data/lib/pindo/{lib → command/lib}/forcepush.rb +0 -0
  122. /data/lib/pindo/{lib → command/lib}/lint.rb +0 -0
  123. /data/lib/pindo/{lib → command/lib}/push.rb +0 -0
  124. /data/lib/pindo/{repo → command/repo}/clone.rb +0 -0
  125. /data/lib/pindo/{repo → command/repo}/create.rb +0 -0
  126. /data/lib/pindo/{repo → command/repo}/login.rb +0 -0
  127. /data/lib/pindo/{repo → command/repo}/search.rb +0 -0
  128. /data/lib/pindo/{setup.rb → command/setup.rb} +0 -0
  129. /data/lib/pindo/{upgrade.rb → command/upgrade.rb} +0 -0
  130. /data/lib/pindo/{utils → command/utils}/clearcert.rb +0 -0
  131. /data/lib/pindo/{utils → command/utils}/device.rb +0 -0
  132. /data/lib/pindo/{utils → command/utils}/tgate.rb +0 -0
  133. /data/lib/pindo/{utils → command/utils}/xcassets.rb +0 -0
  134. /data/lib/pindo/{utils → command/utils}/xcassets.sh +0 -0
  135. /data/lib/pindo/module/{appstore_in_app_purchase.rb → appstore/appstore_in_app_purchase.rb} +0 -0
  136. /data/lib/pindo/module/{appstore_metadata_connect_api_helper.rb → appstore/appstore_metadata_connect_api_helper.rb} +0 -0
  137. /data/lib/pindo/module/{appstore_metadata_fastlane_helper.rb → appstore/appstore_metadata_fastlane_helper.rb} +0 -0
  138. /data/lib/pindo/module/{iap_tier.json → appstore/iap_tier.json} +0 -0
  139. /data/lib/pindo/module/{commonconfuseproj.rb → build/commonconfuseproj.rb} +0 -0
  140. /data/lib/pindo/module/{xcodehelper.rb → xcode/xcodehelper.rb} +0 -0
@@ -0,0 +1,138 @@
1
+
2
+ require 'open3'
3
+ require 'security'
4
+
5
+ module Pindo
6
+
7
+ module KeychainHelper
8
+
9
+ def self.import_file(path, keychain_path, keychain_password: nil, certificate_password: "", skip_set_partition_list: false, output: false)
10
+ puts "Could not find file '#{path}'" unless File.exist?(path)
11
+
12
+ password_part = " -P #{certificate_password.shellescape}"
13
+
14
+ command = "security import #{path.shellescape} -k '#{keychain_path.shellescape}'"
15
+ command << password_part
16
+ command << " -T /usr/bin/codesign" # to not be asked for permission when running a tool like `gym` (before Sierra)
17
+ command << " -T /usr/bin/security"
18
+ command << " -T /usr/bin/productbuild" # to not be asked for permission when using an installer cert for macOS
19
+ command << " -T /usr/bin/productsign" # to not be asked for permission when using an installer cert for macOS
20
+ command << " 1> /dev/null" unless output
21
+
22
+ sensitive_command = command.gsub(password_part, " -P ********")
23
+ UI.command(sensitive_command) if output
24
+ Open3.popen3(command) do |stdin, stdout, stderr, thrd|
25
+ UI.command_output(stdout.read.to_s) if output
26
+
27
+ # Set partition list only if success since it can be a time consuming process if a lot of keys are installed
28
+ if thrd.value.success? && !skip_set_partition_list
29
+ keychain_password ||= resolve_keychain_password(keychain_path)
30
+ set_partition_list(path, keychain_path, keychain_password: keychain_password, output: output)
31
+ else
32
+ # Output verbose if file is already installed since not an error otherwise we will show the whole error
33
+ err = stderr.read.to_s.strip
34
+ if err.include?("SecKeychainItemImport") && err.include?("The specified item already exists in the keychain")
35
+ # UI.verbose("'#{File.basename(path)}' is already installed on this machine")
36
+ else
37
+ raise Informative, err
38
+ end
39
+ end
40
+ end
41
+ end
42
+
43
+ def self.help_backticks(command, print: true)
44
+ # UI.command(command) if print
45
+ result = `#{command}`
46
+ # UI.command_output(result) if print
47
+ return result
48
+ end
49
+
50
+ def self.set_partition_list(path, keychain_path, keychain_password: nil, output: false)
51
+ # When security supports partition lists, also add the partition IDs
52
+ # See https://openradar.appspot.com/28524119
53
+ if help_backticks('security -h | grep set-key-partition-list', print: false).length > 0
54
+ password_part = " -k #{keychain_password.to_s.shellescape}"
55
+
56
+ command = "security set-key-partition-list"
57
+ command << " -S apple-tool:,apple:,codesign:"
58
+ command << " -s" # This is a needed in Catalina to prevent "security: SecKeychainItemCopyAccess: A missing value was detected."
59
+ command << password_part
60
+ command << " #{keychain_path.shellescape}"
61
+ command << " 1> /dev/null" # always disable stdout. This can be very verbose, and leak potentially sensitive info
62
+
63
+ # Showing loading indicator as this can take some time if a lot of keys installed
64
+ # Helper.show_loading_indicator("Setting key partition list... (this can take a minute if there are a lot of keys installed)")
65
+
66
+ # Strip keychain password from command output
67
+ sensitive_command = command.gsub(password_part, " -k ********")
68
+ UI.command(sensitive_command) if output
69
+ Open3.popen3(command) do |stdin, stdout, stderr, thrd|
70
+ unless thrd.value.success?
71
+ err = stderr.read.to_s.strip
72
+
73
+ # Inform user when no/wrong password was used as its needed to prevent UI permission popup from Xcode when signing
74
+ if err.include?("SecKeychainItemSetAccessWithPassword")
75
+ keychain_name = File.basename(keychain_path, ".*")
76
+ Security::InternetPassword.delete(server: server_name(keychain_name))
77
+
78
+ # UI.important("")
79
+ # UI.important("Could not configure imported keychain item (certificate) to prevent UI permission popup when code signing\n" \
80
+ # "Check if you supplied the correct `keychain_password` for keychain: `#{keychain_path}`\n" \
81
+ # "#{err}")
82
+ # UI.important("")
83
+ # UI.important("Please look at the following docs to see how to set a keychain password:")
84
+ # UI.important(" - https://docs.fastlane.tools/actions/sync_code_signing")
85
+ # UI.important(" - https://docs.fastlane.tools/actions/get_certificates")
86
+ puts "密码错误"
87
+ else
88
+ raise Informative, err
89
+ end
90
+ end
91
+ end
92
+
93
+ # Hiding after Open3 finishes
94
+ # Helper.hide_loading_indicator
95
+
96
+ end
97
+ end
98
+
99
+ # https://github.com/fastlane/fastlane/issues/14196
100
+ # Keychain password is needed to set the partition list to
101
+ # prevent Xcode from prompting dialog for keychain password when signing
102
+ # 1. Uses keychain password from login keychain if found
103
+ # 2. Prompts user for keychain password and stores it in login keychain for user later
104
+ def self.resolve_keychain_password(keychain_path)
105
+ keychain_name = File.basename(keychain_path, ".*")
106
+ server = server_name(keychain_name)
107
+
108
+ # Attempt to find password in keychain for keychain
109
+ item = Security::InternetPassword.find(server: server)
110
+ if item
111
+ keychain_password = item.password
112
+ # UI.important("Using keychain password from keychain item #{server} in #{keychain_path}")
113
+ end
114
+
115
+ if keychain_password.nil?
116
+ # if UI.interactive?
117
+ # UI.important("Enter the password for #{keychain_path}")
118
+ # UI.important("This passphrase will be stored in your local keychain with the name #{server} and used in future runs")
119
+ # UI.important("This prompt can be avoided by specifying the 'keychain_password' option or 'MATCH_KEYCHAIN_PASSWORD' environment variable")
120
+ keychain_password = FastlaneCore::Helper.ask_password(message: "Password for #{keychain_name} keychain: ", confirm: true, confirmation_message: "Type password for #{keychain_name} keychain again: ")
121
+ Security::InternetPassword.add(server, "", keychain_password)
122
+ # else
123
+ # UI.important("Keychain password for #{keychain_path} was not specified and not found in your keychain. Specify the 'keychain_password' option to prevent the UI permission popup when code signing")
124
+ # keychain_password = ""
125
+ # end
126
+ end
127
+
128
+ return keychain_password
129
+ end
130
+
131
+ # server name used for accessing the macOS keychain
132
+ def self.server_name(keychain_name)
133
+ ["fastlane", "keychain", keychain_name].join("_")
134
+ end
135
+
136
+ private_class_method :server_name
137
+ end
138
+ end
@@ -1,6 +1,8 @@
1
1
 
2
2
  module Pindo
3
- module Pemcreate
3
+
4
+ module PemHelper
5
+
4
6
  def create_certificate(bundle_id:nil, type:"prod", output_path:"")
5
7
 
6
8
  if bundle_id.empty? || output_path.empty?
@@ -0,0 +1,137 @@
1
+ require 'plist'
2
+ require 'json'
3
+
4
+ module Pindo
5
+ class Provisioninghelper
6
+ class << self
7
+ # @return (Hash) The hash with the data of the provisioning profile
8
+ # @example
9
+ # {"AppIDName"=>"My App Name",
10
+ # "ApplicationIdentifierPrefix"=>["5A997XSAAA"],
11
+ # "CreationDate"=>#<DateTime: 2015-05-24T20:38:03+00:00 ((2457167j,74283s,0n),+0s,2299161j)>,
12
+ # "DeveloperCertificates"=>[#<StringIO:0x007f944b9666f8>],
13
+ # "Entitlements"=>
14
+ # {"keychain-access-groups"=>["5A997XSAAA.*"],
15
+ # "get-task-allow"=>false,
16
+ # "application-identifier"=>"5A997XAAA.net.sunapps.192",
17
+ # "com.apple.developer.team-identifier"=>"5A997XAAAA",
18
+ # "aps-environment"=>"production",
19
+ # "beta-reports-active"=>true},
20
+ # "ExpirationDate"=>#<DateTime: 2015-11-25T22:45:50+00:00 ((2457352j,81950s,0n),+0s,2299161j)>,
21
+ # "Name"=>"net.sunapps.192 AppStore",
22
+ # "TeamIdentifier"=>["5A997XSAAA"],
23
+ # "TeamName"=>"SunApps GmbH",
24
+ # "TimeToLive"=>185,
25
+ # "UUID"=>"1752e382-53bd-4910-a393-aaa7de0005ad",
26
+ # "Version"=>1}
27
+ def parse(path, keychain_path = nil)
28
+
29
+
30
+ plist = Plist.parse_xml(decode(path, keychain_path))
31
+ # puts JSON.pretty_generate(plist)
32
+ if (plist || []).count > 5
33
+ plist
34
+ else
35
+ raise Informative, "Error parsing provisioning profile at path '#{path}'"
36
+ end
37
+ end
38
+
39
+ # @return [String] The UUID of the given provisioning profile
40
+ def uuid(path, keychain_path = nil)
41
+ parse(path, keychain_path).fetch("UUID")
42
+ end
43
+
44
+ # @return [String] The Name of the given provisioning profile
45
+ def name(path, keychain_path = nil)
46
+ parse(path, keychain_path).fetch("Name")
47
+ end
48
+
49
+ def bundle_id(path, keychain_path = nil)
50
+ profile = parse(path, keychain_path)
51
+ app_id_prefix = profile["ApplicationIdentifierPrefix"].first
52
+ entitlements = profile["Entitlements"]
53
+ app_identifier = entitlements["application-identifier"] || entitlements["com.apple.application-identifier"]
54
+ bundle_id = app_identifier.gsub("#{app_id_prefix}.", "")
55
+ bundle_id
56
+ rescue
57
+ UI.error("Unable to extract the Bundle Id from the provided provisioning profile '#{path}'.")
58
+ end
59
+
60
+ def mac?(path, keychain_path = nil)
61
+ parse(path, keychain_path).fetch("Platform", []).include?('OSX')
62
+ end
63
+
64
+ def profile_filename(path, keychain_path = nil)
65
+ basename = uuid(path, keychain_path)
66
+ basename + profile_extension(path, keychain_path)
67
+ end
68
+
69
+ def profile_extension(path, keychain_path = nil)
70
+ if mac?(path, keychain_path)
71
+ ".provisionprofile"
72
+ else
73
+ ".mobileprovision"
74
+ end
75
+ end
76
+
77
+ def profiles_path
78
+ path = File.expand_path("~") + "/Library/MobileDevice/Provisioning Profiles/"
79
+ # If the directory doesn't exist, create it first
80
+ unless File.directory?(path)
81
+ FileUtils.mkdir_p(path)
82
+ end
83
+
84
+ return path
85
+ end
86
+
87
+ # Installs a provisioning profile for Xcode to use
88
+ def install(path, keychain_path = nil)
89
+
90
+
91
+ destination = File.join(profiles_path, profile_filename(path, keychain_path))
92
+ puts "Installing provisioning profile... #{destination}"
93
+
94
+ if path != destination
95
+ # copy to Xcode provisioning profile directory
96
+ FileUtils.copy(path, destination)
97
+ unless File.exist?(destination)
98
+ raise Informative, "Failed installation of provisioning profile at location: '#{destination}'"
99
+ end
100
+ end
101
+ destination
102
+ end
103
+
104
+ private
105
+
106
+ def isMacOS?
107
+ (/darwin/ =~ RUBY_PLATFORM) != nil
108
+ end
109
+
110
+
111
+ def decode(path, keychain_path = nil)
112
+ require 'tmpdir'
113
+ Dir.mktmpdir('fastlane') do |dir|
114
+ err = "#{dir}/cms.err"
115
+ # we want to prevent the error output to mix up with the standard output because of
116
+ # /dev/null: https://github.com/fastlane/fastlane/issues/6387
117
+ if isMacOS?
118
+ if keychain_path.nil?
119
+ decoded = `security cms -D -i "#{path}" 2> #{err}`
120
+ else
121
+ decoded = `security cms -D -i "#{path}" -k "#{keychain_path.shellescape}" 2> #{err}`
122
+ end
123
+ else
124
+ # `security` only works on Mac, fallback to `openssl`
125
+ # via https://stackoverflow.com/a/14379814/252627
126
+ decoded = `openssl smime -inform der -verify -noverify -in #{path.shellescape} 2> #{err}`
127
+ end
128
+
129
+ if $?.exitstatus != 0
130
+ raise Informative, "Failure to decode #{path}"
131
+ end
132
+ decoded
133
+ end
134
+ end
135
+ end
136
+ end
137
+ end
@@ -0,0 +1,301 @@
1
+
2
+ require 'fileutils'
3
+
4
+ module Pindo
5
+
6
+ module XcodeCertHelper
7
+
8
+ def get_target_name_map
9
+ return {
10
+ "MainTarget" => "bundle_id",
11
+ "Content" => "bundle_id_pushcontent",
12
+ "Service" => "bundle_id_pushservice",
13
+ "Keyboard" => "bundle_id_keyboard",
14
+ "iMessage" => "bundle_id_imessage",
15
+ "Siri" => "bundle_id_siri",
16
+ "SiriUI" => "bundle_id_siriui",
17
+ "Widget" => "bundle_id_widget",
18
+ "Extension" => "bundle_id_extension",
19
+ "ExtensionAd" => "bundle_id_extensionad",
20
+ "ExtensionPorn" => "bundle_id_extensionporn",
21
+ "WatchApp" => "bundle_id_watchapp",
22
+ "WatchAppComplication" => "bundle_id_watchapp_extension"
23
+ }
24
+ end
25
+
26
+ def create_provisioning_info_array(build_type:nil)
27
+
28
+ provisioning_info_array = []
29
+
30
+ bundle_id_map = get_bundle_id_map
31
+
32
+ bundle_id_map.each do |type, bundle_id_temp|
33
+ provisioning_info = {}
34
+ provisioning_info['type'] = type
35
+ provisioning_info['bundle_id'] = bundle_id_temp
36
+ name_temp = Match::Utils.environment_variable_name_profile_name(app_identifier: bundle_id_temp, type: build_type)
37
+ provisioning_info['profile_name'] = ENV[name_temp]
38
+ path_temp = Match::Utils.environment_variable_name_profile_path(app_identifier:bundle_id_temp,type: build_type)
39
+ provisioning_info['profile_path'] = ENV[path_temp]
40
+ signing_identity_key=Match::Utils.environment_variable_name_certificate_name(app_identifier: bundle_id_temp,type: build_type)
41
+ provisioning_info["signing_identity"] = ENV[signing_identity_key]
42
+ team_id_key = Match::Utils.environment_variable_name_team_id(app_identifier: bundle_id_temp,type:build_type)
43
+ provisioning_info["team_id"] = ENV[team_id_key]
44
+ provisioning_info_array << provisioning_info
45
+ end
46
+
47
+
48
+ return provisioning_info_array
49
+ end
50
+
51
+ def config_project_cert(new_proj_name:nil, new_project_dir:nil, cert_type:nil, team_id_vaule:nil, provisioning_info_array:nil)
52
+
53
+
54
+ new_proj_fullname = File.join(new_project_dir, new_proj_name) + ".xcodeproj"
55
+ new_project_obj = Xcodeproj::Project.open(new_proj_fullname)
56
+
57
+ new_project_obj.root_object.build_configuration_list.set_setting('CODE_SIGN_IDENTITY[sdk=iphoneos*]', "Apple Distribution")
58
+ new_project_obj.root_object.build_configuration_list.set_setting('CODE_SIGN_IDENTITY*', "Apple Distribution")
59
+
60
+ if cert_type == "development"
61
+ new_project_obj.root_object.build_configuration_list.set_setting('CODE_SIGN_IDENTITY[sdk=iphoneos*]', "Apple Development")
62
+ new_project_obj.root_object.build_configuration_list.set_setting('CODE_SIGN_IDENTITY*', "Apple Development")
63
+ end
64
+
65
+ new_project_obj.root_object.attributes['TargetAttributes'] = new_project_obj.root_object.attributes['TargetAttributes'] || {}
66
+ target_atts_obj = new_project_obj.root_object.attributes['TargetAttributes']
67
+
68
+ target_map = get_target_name_map
69
+
70
+ new_project_obj.targets.each do |target|
71
+
72
+ provisioning_info = nil
73
+
74
+ if target.product_type.include?(Xcodeproj::Constants::PRODUCT_TYPE_UTI[:application])
75
+ bundle_id_map_key = target_map["MainTarget"]
76
+ provisioning_info = provisioning_info_array.select { |s| s["type"].to_s.eql?(bundle_id_map_key.to_s) }.first
77
+ elsif
78
+ target_map.each do |k, v|
79
+ if target.name.to_s.end_with?(k)
80
+ bundle_id_map_key = v.to_s
81
+ provisioning_info = provisioning_info_array.select { |s| s["type"].to_s.eql?(bundle_id_map_key.to_s) }.first
82
+ end
83
+ end
84
+ end
85
+
86
+ target.build_configurations.each do |config|
87
+ target_atts_obj[target.uuid] = target_atts_obj[target.uuid] || {}
88
+ target_atts_obj[target.uuid]['DevelopmentTeam'] = team_id_vaule
89
+ target_atts_obj[target.uuid]['ProvisioningStyle'] = "Manual"
90
+ config.build_settings['DEVELOPMENT_TEAM'] = team_id_vaule
91
+ config.build_settings['DEVELOPMENT_TEAM[sdk=iphoneos*]'] = team_id_vaule
92
+ config.build_settings['CODE_SIGN_STYLE'] = "Manual"
93
+
94
+ config.build_settings['CODE_SIGN_IDENTITY'] = "Apple Distribution"
95
+ config.build_settings['CODE_SIGN_IDENTITY[sdk=iphoneos*]'] = "Apple Distribution"
96
+
97
+ if cert_type == "development"
98
+ config.build_settings['CODE_SIGN_IDENTITY'] = "Apple Development"
99
+ config.build_settings['CODE_SIGN_IDENTITY[sdk=iphoneos*]'] = "Apple Development"
100
+ end
101
+
102
+ if !provisioning_info.nil?
103
+ config.build_settings['PRODUCT_BUNDLE_IDENTIFIER'] = provisioning_info["bundle_id"]
104
+ config.build_settings['PROVISIONING_PROFILE_SPECIFIER'] = provisioning_info['profile_name']
105
+ config.build_settings['PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]'] = provisioning_info['profile_name']
106
+
107
+ end
108
+ end
109
+
110
+ end
111
+ new_project_obj.save
112
+
113
+ end
114
+
115
+ def config_infoplist_cert(new_proj_name:nil, new_project_dir:nil, icloud_id:nil, group_id:nil, provisioning_info_array:nil)
116
+
117
+ new_proj_fullname = File.join(new_project_dir, new_proj_name) + ".xcodeproj"
118
+ project_obj = Xcodeproj::Project.open(new_proj_fullname)
119
+ entitlements_plist_path = File.join(new_project_dir, new_proj_name + ".entitlements")
120
+
121
+ project_obj.targets.each do |target|
122
+
123
+ temp_entitlements_file = target.build_configurations.first.build_settings['CODE_SIGN_ENTITLEMENTS']
124
+ if !temp_entitlements_file.nil? && !temp_entitlements_file.empty?
125
+ entitlements_plist_path = File.join(new_project_dir, temp_entitlements_file)
126
+
127
+ if !File.exist?(entitlements_plist_path)
128
+ raise Informative, "Target: #{target.name.to_s} 找不到文件 #{entitlements_plist_path}"
129
+ end
130
+ end
131
+
132
+ temp_info = target.build_configurations.first.build_settings['INFOPLIST_FILE']
133
+ info_plist_path = File.join(new_project_dir, temp_info)
134
+ if target.product_type.to_s.eql?("com.apple.product-type.application") && !File.exist?(info_plist_path)
135
+ raise Informative, "Missing Target #{target.name.to_s} Info.plist!!! #{info_plist_path} Modify Info.plist Error !!!"
136
+ end
137
+
138
+
139
+ if target.product_type.to_s.eql?("com.apple.product-type.application") then
140
+ add_swark_entitlement(entitlements_plist_path:entitlements_plist_path, bundle_id_dict:provisioning_info_array)
141
+ if !icloud_id.nil?
142
+ modify_entitlements_plist(entitlements_plist_path:entitlements_plist_path, icloud_id:icloud_id)
143
+ modify_info_plist_icloud(plist_file_name:info_plist_path, icloud_id:icloud_id)
144
+ else
145
+ modify_info_plist_icloud(plist_file_name:info_plist_path, icloud_id:nil)
146
+ end
147
+ end
148
+ if !group_id.nil?
149
+ modify_entitlements_plist(entitlements_plist_path:entitlements_plist_path, group_id:group_id)
150
+ end
151
+ end
152
+
153
+ end
154
+
155
+ def modify_entitlements_plist(entitlements_plist_path:nil, group_id:nil, icloud_id:nil)
156
+ if File.exist?(entitlements_plist_path)
157
+
158
+ entitlements_plist_dict = Xcodeproj::Plist.read_from_path(entitlements_plist_path)
159
+
160
+ if !group_id.nil? && !entitlements_plist_dict['com.apple.security.application-groups'].nil?
161
+ entitlements_plist_dict['com.apple.security.application-groups'] = [group_id]
162
+ end
163
+
164
+ if !icloud_id.nil?
165
+ entitlements_plist_dict['com.apple.developer.icloud-container-identifiers'] = [icloud_id]
166
+ entitlements_plist_dict['com.apple.developer.ubiquity-container-identifiers'] = [icloud_id]
167
+ end
168
+
169
+ Xcodeproj::Plist.write_to_path(entitlements_plist_dict, entitlements_plist_path)
170
+ end
171
+ end
172
+
173
+
174
+ def modify_info_plist_icloud(plist_file_name:nil, icloud_id:nil)
175
+ if ! File.exist? (plist_file_name)
176
+ raise Informative, "修改Info.list 路径错误!!! #{plist_file_name}"
177
+ end
178
+ if File.exist?(plist_file_name)
179
+ info_plist_dict = Xcodeproj::Plist.read_from_path(plist_file_name)
180
+
181
+ if !icloud_id.nil?
182
+
183
+ temp_value = {}
184
+ if !info_plist_dict['NSUbiquitousContainers'].nil? && info_plist_dict['NSUbiquitousContainers'].is_a?(Hash)
185
+ info_plist_dict['NSUbiquitousContainers'].each do |key, value|
186
+ if key.include?("iCloud.")
187
+ temp_value = value
188
+ break;
189
+ end
190
+ end
191
+ end
192
+ info_plist_dict['NSUbiquitousContainers'] = {}
193
+ info_plist_dict['NSUbiquitousContainers'][icloud_id] = temp_value || {}
194
+ else
195
+ info_plist_dict['NSUbiquitousContainers'] = nil
196
+ end
197
+
198
+ Xcodeproj::Plist.write_to_path(info_plist_dict, plist_file_name)
199
+
200
+ end
201
+ end
202
+
203
+ def create_upload_cert_info(apple_id:nil, cert_type:nil, provisioning_info_array:nil)
204
+
205
+ cert_dir = File.join(Dir.pwd, "cert")
206
+ cert_json_file = File.join(cert_dir, "certs.json")
207
+
208
+ if !File.exist?(cert_dir)
209
+ FileUtils.mkdir_p(cert_dir)
210
+ end
211
+
212
+ cert_json = []
213
+ begin
214
+ cert_json = JSON.parse(File.read(cert_json_file)) if File.exist?(cert_json_file)
215
+ cert_json = cert_json || []
216
+ rescue StandardError => e
217
+ cert_json = []
218
+ end
219
+
220
+ bundle_id = provisioning_info_array.select { |s| s["type"].to_s.eql?("bundle_id") }.first["bundle_id"]
221
+ team_id_vaule = provisioning_info_array.first["team_id"]
222
+ bundle_id_signing_identity = provisioning_info_array.first["signing_identity"]
223
+
224
+ account_cert_set = {}
225
+ select_result= cert_json.select { |x| x["account_name"].eql?(apple_id) }.first
226
+ if select_result.nil?
227
+
228
+ account_cert_set = {}
229
+ else
230
+
231
+ account_cert_set = select_result
232
+ cert_json.delete_if { |x| x["account_name"].eql?(apple_id) }
233
+ end
234
+
235
+ account_cert_set["account_name"] = apple_id
236
+ account_cert_set["team_id"] = team_id_vaule
237
+ account_cert_set["certs"] = account_cert_set["certs"] || []
238
+
239
+ cert_item = {}
240
+ cert_item_result = account_cert_set["certs"].select { |x| x["cert_id"].eql?(bundle_id_signing_identity)}.first
241
+ if cert_item_result.nil?
242
+ cert_item = {}
243
+ else
244
+ cert_item = cert_item_result
245
+ account_cert_set["certs"].delete_if { |x| x["cert_id"].eql?(bundle_id_signing_identity)}
246
+ end
247
+
248
+ cert_item["cert_id"] = cert_item["cert_id"] || bundle_id_signing_identity
249
+ cert_item["password"] = "goodcert1"
250
+ cert_item["cert_file"] = "#{cert_type}.p12".downcase
251
+ cert_item["cert_type"] = cert_type.downcase
252
+ cert_item["cert_provisioning_group"] = cert_item["cert_provisioning_group"] || []
253
+
254
+
255
+
256
+ cert_provisioning_group_item = {}
257
+ provisioning_group_id = [cert_type, "group", bundle_id].join("_")
258
+
259
+ provisioning_group_result = cert_item["cert_provisioning_group"].select { |x| x["provisioning_group_id"].eql?(provisioning_group_id)}.first
260
+ if provisioning_group_result.nil?
261
+ cert_provisioning_group_item = {}
262
+ else
263
+ cert_provisioning_group_item = provisioning_group_result
264
+ cert_item["cert_provisioning_group"].delete_if { |x| x["provisioning_group_id"].eql?(provisioning_group_id)}
265
+ end
266
+
267
+
268
+
269
+ cert_provisioning_group_item["provisioning_group_id"] = provisioning_group_id
270
+ cert_provisioning_group_item["provisioning_main_bundle_id"] = bundle_id
271
+ cert_provisioning_group_item["provisioning_items"] = []
272
+
273
+ group_id = [cert_type, "group", bundle_id].join("_")
274
+ provisioning_info_array.each do |provisioning_info|
275
+ bundle_id_temp = provisioning_info['bundle_id']
276
+ provisioning_id = [cert_type, bundle_id_temp].join("_")
277
+
278
+ cert_provisioning_group_item["provisioning_items"] << {
279
+ "bundle_id" => bundle_id_temp,
280
+ "provisioning_id" => provisioning_id,
281
+ "group_id" => group_id,
282
+ "provisioning_file" => provisioning_id + ".mobileprovision"
283
+ }
284
+ real_path = provisioning_info["profile_path"]
285
+ FileUtils.cp_r(real_path, File.join(cert_dir, provisioning_id + ".mobileprovision"))
286
+
287
+ end
288
+
289
+ cert_item["cert_provisioning_group"] << cert_provisioning_group_item
290
+ account_cert_set["certs"] << cert_item
291
+ cert_json << account_cert_set
292
+ File.open(cert_json_file, "w") do |f|
293
+ f.write(JSON.pretty_generate(cert_json.compact))
294
+ end
295
+
296
+ return account_cert_set
297
+ end
298
+
299
+
300
+ end
301
+ end