fastlane-plugin-sapfire 1.0.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 +7 -0
- data/LICENSE +21 -0
- data/README.md +135 -0
- data/lib/fastlane/plugin/sapfire/actions/app_certification_action.rb +79 -0
- data/lib/fastlane/plugin/sapfire/actions/associate_ms_store_action.rb +263 -0
- data/lib/fastlane/plugin/sapfire/actions/build_uwp_app_action.rb +55 -0
- data/lib/fastlane/plugin/sapfire/actions/dotnet_select_action.rb +46 -0
- data/lib/fastlane/plugin/sapfire/actions/ensure_dotnet_version_action.rb +123 -0
- data/lib/fastlane/plugin/sapfire/actions/ms_credentials_action.rb +91 -0
- data/lib/fastlane/plugin/sapfire/actions/msbuild_action.rb +45 -0
- data/lib/fastlane/plugin/sapfire/actions/msbuild_select_action.rb +53 -0
- data/lib/fastlane/plugin/sapfire/actions/nuget_pack_action.rb +46 -0
- data/lib/fastlane/plugin/sapfire/actions/update_uwp_signing_settings_action.rb +73 -0
- data/lib/fastlane/plugin/sapfire/actions/upload_ms_store_action.rb +218 -0
- data/lib/fastlane/plugin/sapfire/actions/upload_nuget_action.rb +95 -0
- data/lib/fastlane/plugin/sapfire/actions_base/msbuild_action_base.rb +42 -0
- data/lib/fastlane/plugin/sapfire/helper/ms_devcenter_helper.rb +292 -0
- data/lib/fastlane/plugin/sapfire/helper/sapfire_helper.rb +55 -0
- data/lib/fastlane/plugin/sapfire/msbuild/module.rb +34 -0
- data/lib/fastlane/plugin/sapfire/msbuild/options.rb +123 -0
- data/lib/fastlane/plugin/sapfire/msbuild/runner.rb +171 -0
- data/lib/fastlane/plugin/sapfire/sln_project/block.rb +30 -0
- data/lib/fastlane/plugin/sapfire/sln_project/global_block.rb +147 -0
- data/lib/fastlane/plugin/sapfire/sln_project/module.rb +14 -0
- data/lib/fastlane/plugin/sapfire/sln_project/project_block.rb +82 -0
- data/lib/fastlane/plugin/sapfire/sln_project/root_block.rb +72 -0
- data/lib/fastlane/plugin/sapfire/version.rb +5 -0
- data/lib/fastlane/plugin/sapfire.rb +16 -0
- metadata +182 -0
@@ -0,0 +1,123 @@
|
|
1
|
+
require "open3"
|
2
|
+
require_relative "../helper/sapfire_helper"
|
3
|
+
|
4
|
+
module Fastlane
|
5
|
+
module Actions
|
6
|
+
class EnsureDotnetVersionAction < Action
|
7
|
+
def self.run(params)
|
8
|
+
UI.user_error!("Can't find dotnet") unless Helper::SapfireHelper.dotnet_specified?
|
9
|
+
|
10
|
+
dotnet_path = Actions.lane_context[SharedValues::SF_DOTNET_PATH]
|
11
|
+
cmd = "\"#{dotnet_path}\" --list-sdks"
|
12
|
+
|
13
|
+
UI.command(cmd)
|
14
|
+
stdin, stdout = Open3.popen2(cmd)
|
15
|
+
output = stdout.read
|
16
|
+
stdin.close
|
17
|
+
stdout.close
|
18
|
+
|
19
|
+
versions = output.split("\n")
|
20
|
+
available_versions = []
|
21
|
+
current_version = nil
|
22
|
+
required_version = nil
|
23
|
+
found = false
|
24
|
+
|
25
|
+
begin
|
26
|
+
required_version = Gem::Version.new(params[:version])
|
27
|
+
rescue ArgumentError => ex
|
28
|
+
UI.user_error!("Invalid version number provided, make sure it's valid: #{ex}")
|
29
|
+
end
|
30
|
+
|
31
|
+
required_version_numbers = required_version.to_s.split(".")
|
32
|
+
|
33
|
+
versions.each do |value|
|
34
|
+
path_bracket_index = value.index("[")
|
35
|
+
|
36
|
+
begin
|
37
|
+
ver_number = value[0..path_bracket_index - 1].strip
|
38
|
+
current_version = Gem::Version.new(ver_number)
|
39
|
+
available_versions.append(current_version.to_s)
|
40
|
+
rescue ArgumentError => ex
|
41
|
+
UI.user_error!("Can't parse the version entry from dotnet output: #{ex}")
|
42
|
+
end
|
43
|
+
|
44
|
+
if params[:strict]
|
45
|
+
next unless current_version == required_version
|
46
|
+
|
47
|
+
success(required_version)
|
48
|
+
else
|
49
|
+
current_version_numbers = current_version.to_s.split(".")
|
50
|
+
all_correct = true
|
51
|
+
|
52
|
+
required_version_numbers.each_with_index do |required_version_number, index|
|
53
|
+
current_version_number = current_version_numbers[index]
|
54
|
+
next if required_version_number == current_version_number
|
55
|
+
|
56
|
+
all_correct = false
|
57
|
+
break
|
58
|
+
end
|
59
|
+
|
60
|
+
next unless all_correct
|
61
|
+
|
62
|
+
success(current_version)
|
63
|
+
end
|
64
|
+
|
65
|
+
found = true
|
66
|
+
break
|
67
|
+
end
|
68
|
+
|
69
|
+
error(required_version, available_versions) unless found
|
70
|
+
end
|
71
|
+
|
72
|
+
def self.success(version)
|
73
|
+
UI.success("Required .NET version has found: #{version}")
|
74
|
+
end
|
75
|
+
|
76
|
+
def self.error(version, available_versions)
|
77
|
+
str = [
|
78
|
+
"Required .NET version hasn't been found: #{version}",
|
79
|
+
"Available versions: #{available_versions}"
|
80
|
+
].join("\n")
|
81
|
+
|
82
|
+
UI.user_error!(str)
|
83
|
+
end
|
84
|
+
|
85
|
+
def self.description
|
86
|
+
"Ensures the right version of .NET is installed and can be used"
|
87
|
+
end
|
88
|
+
|
89
|
+
def self.authors
|
90
|
+
["CheeryLee"]
|
91
|
+
end
|
92
|
+
|
93
|
+
def self.is_supported?(platform)
|
94
|
+
true
|
95
|
+
end
|
96
|
+
|
97
|
+
def self.available_options
|
98
|
+
[
|
99
|
+
FastlaneCore::ConfigItem.new(
|
100
|
+
key: :version,
|
101
|
+
description: ".NET version to verify that is installed",
|
102
|
+
optional: false,
|
103
|
+
type: String,
|
104
|
+
verify_block: proc do |value|
|
105
|
+
UI.user_error!("The version of .NET to check is empty") unless value && !value.empty?
|
106
|
+
end
|
107
|
+
),
|
108
|
+
FastlaneCore::ConfigItem.new(
|
109
|
+
key: :strict,
|
110
|
+
description: "Should the version be verified strictly (all 3 version numbers), or matching only the given version numbers (i.e. 6.0 == 6.0.x)",
|
111
|
+
optional: true,
|
112
|
+
default_value: true,
|
113
|
+
type: Boolean
|
114
|
+
)
|
115
|
+
]
|
116
|
+
end
|
117
|
+
|
118
|
+
def self.category
|
119
|
+
:building
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
require "fastlane/action"
|
2
|
+
|
3
|
+
module Fastlane
|
4
|
+
module Actions
|
5
|
+
module SharedValues
|
6
|
+
SF_MS_USERNAME = :SF_MS_USERNAME
|
7
|
+
SF_MS_PASSWORD = :SF_MS_PASSWORD
|
8
|
+
SF_MS_TENANT_ID = :SF_MS_TENANT_ID
|
9
|
+
SF_MS_CLIENT_ID = :SF_MS_CLIENT_ID
|
10
|
+
SF_MS_CLIENT_SECRET = :SF_MS_CLIENT_SECRET
|
11
|
+
end
|
12
|
+
|
13
|
+
class MsCredentialsAction < Action
|
14
|
+
def self.run(params)
|
15
|
+
Actions.lane_context[SharedValues::SF_MS_USERNAME] = params[:username]
|
16
|
+
Actions.lane_context[SharedValues::SF_MS_PASSWORD] = params[:password]
|
17
|
+
Actions.lane_context[SharedValues::SF_MS_TENANT_ID] = params[:tenant_id]
|
18
|
+
Actions.lane_context[SharedValues::SF_MS_CLIENT_ID] = params[:client_id]
|
19
|
+
Actions.lane_context[SharedValues::SF_MS_CLIENT_SECRET] = params[:client_secret]
|
20
|
+
|
21
|
+
UI.success("Credentials for Azure AD account is successfully saved for further actions")
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.description
|
25
|
+
"Sets Azure AD account credentials"
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.authors
|
29
|
+
["CheeryLee"]
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.is_supported?(platform)
|
33
|
+
[:windows].include?(platform)
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.available_options
|
37
|
+
[
|
38
|
+
FastlaneCore::ConfigItem.new(
|
39
|
+
key: :username,
|
40
|
+
description: "The username of Azure AD account",
|
41
|
+
optional: false,
|
42
|
+
type: String,
|
43
|
+
verify_block: proc do |value|
|
44
|
+
UI.user_error!("Microsoft username can't be empty") unless value && !value.empty?
|
45
|
+
end
|
46
|
+
),
|
47
|
+
FastlaneCore::ConfigItem.new(
|
48
|
+
key: :password,
|
49
|
+
description: "The password of Azure AD account",
|
50
|
+
optional: false,
|
51
|
+
type: String,
|
52
|
+
verify_block: proc do |value|
|
53
|
+
UI.user_error!("Microsoft password can't be empty") unless value && !value.empty?
|
54
|
+
end
|
55
|
+
),
|
56
|
+
FastlaneCore::ConfigItem.new(
|
57
|
+
key: :tenant_id,
|
58
|
+
description: "The unique identifier of the Azure AD instance",
|
59
|
+
optional: false,
|
60
|
+
type: String,
|
61
|
+
verify_block: proc do |value|
|
62
|
+
UI.user_error!("Tenant ID can't be empty") unless value && !value.empty?
|
63
|
+
end
|
64
|
+
),
|
65
|
+
FastlaneCore::ConfigItem.new(
|
66
|
+
key: :client_id,
|
67
|
+
description: "The ID of an application that would be associate to get working with Microsoft account",
|
68
|
+
optional: false,
|
69
|
+
type: String,
|
70
|
+
verify_block: proc do |value|
|
71
|
+
UI.user_error!("Client ID can't be empty") unless value && !value.empty?
|
72
|
+
end
|
73
|
+
),
|
74
|
+
FastlaneCore::ConfigItem.new(
|
75
|
+
key: :client_secret,
|
76
|
+
description: "The unique secret string of an application that can be generated in Microsoft Partner Center",
|
77
|
+
optional: false,
|
78
|
+
type: String,
|
79
|
+
verify_block: proc do |value|
|
80
|
+
UI.user_error!("Client secret string can't be empty") unless value && !value.empty?
|
81
|
+
end
|
82
|
+
)
|
83
|
+
]
|
84
|
+
end
|
85
|
+
|
86
|
+
def self.category
|
87
|
+
:misc
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require "fastlane/action"
|
2
|
+
require_relative "../msbuild/options"
|
3
|
+
require_relative "../msbuild/module"
|
4
|
+
require_relative "../actions_base/msbuild_action_base"
|
5
|
+
|
6
|
+
module Fastlane
|
7
|
+
module Actions
|
8
|
+
class MsbuildAction < MsbuildActionBase
|
9
|
+
def self.run(params)
|
10
|
+
Msbuild.config.certificate = nil
|
11
|
+
Msbuild.config.certificate_password = nil
|
12
|
+
Msbuild.config.certificate_thumbprint = nil
|
13
|
+
Msbuild.config.build_type = Msbuild::BuildType::GENERIC
|
14
|
+
|
15
|
+
super(params)
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.description
|
19
|
+
"Executes MSBuild to build the application"
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.authors
|
23
|
+
["CheeryLee"]
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.is_supported?(platform)
|
27
|
+
true
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.rejected_options
|
31
|
+
%i[
|
32
|
+
appx_output_path
|
33
|
+
appx_output_name
|
34
|
+
appx_bundle_platforms
|
35
|
+
build_mode
|
36
|
+
skip_codesigning
|
37
|
+
]
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.category
|
41
|
+
:building
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require "fastlane/action"
|
2
|
+
require_relative "../msbuild/module"
|
3
|
+
|
4
|
+
module Fastlane
|
5
|
+
module Actions
|
6
|
+
module SharedValues
|
7
|
+
SF_MSBUILD_PATH = :SF_MSBUILD_PATH
|
8
|
+
SF_MSBUILD_TYPE = :SF_MSBUILD_TYPE
|
9
|
+
end
|
10
|
+
|
11
|
+
class MsbuildSelectAction < Action
|
12
|
+
def self.run(params)
|
13
|
+
path = (params || []).first.to_s
|
14
|
+
path = File.expand_path(path)
|
15
|
+
|
16
|
+
UI.user_error!("File '#{path}' doesn't exist") unless File.exist?(path)
|
17
|
+
UI.user_error!("Path to MSBuild executable or library required") if
|
18
|
+
path.empty? || (!path.end_with?("MSBuild.exe") && !path.end_with?("MSBuild.dll"))
|
19
|
+
|
20
|
+
Actions.lane_context[SharedValues::SF_MSBUILD_PATH] = path
|
21
|
+
Actions.lane_context[SharedValues::SF_MSBUILD_TYPE] = if path.end_with?("MSBuild.exe")
|
22
|
+
Msbuild::MsbuildType::EXE
|
23
|
+
else
|
24
|
+
Msbuild::MsbuildType::LIBRARY
|
25
|
+
end
|
26
|
+
|
27
|
+
UI.message("Setting MSBuild executable to '#{path}' for all next build steps")
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.description
|
31
|
+
"Changes the MSBuild executable to use. Useful if you have multiple installed versions."
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.authors
|
35
|
+
["CheeryLee"]
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.is_supported?(platform)
|
39
|
+
true
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.example_code
|
43
|
+
[
|
44
|
+
'msbuild_select("/cygdrive/c/Program\ Files/Microsoft\ Visual\ Studio/2022/Community/Msbuild/Current/Bin/MSBuild.exe")'
|
45
|
+
]
|
46
|
+
end
|
47
|
+
|
48
|
+
def self.category
|
49
|
+
:building
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require "fastlane/action"
|
2
|
+
require_relative "../msbuild/options"
|
3
|
+
require_relative "../msbuild/module"
|
4
|
+
require_relative "../actions_base/msbuild_action_base"
|
5
|
+
|
6
|
+
module Fastlane
|
7
|
+
module Actions
|
8
|
+
class NugetPackAction < MsbuildActionBase
|
9
|
+
def self.run(params)
|
10
|
+
Msbuild.config.certificate = nil
|
11
|
+
Msbuild.config.certificate_password = nil
|
12
|
+
Msbuild.config.certificate_thumbprint = nil
|
13
|
+
Msbuild.config.build_type = Msbuild::BuildType::NUGET
|
14
|
+
|
15
|
+
super(params)
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.description
|
19
|
+
"Executes MSBuild to create a NuGet package"
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.authors
|
23
|
+
["CheeryLee"]
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.is_supported?(platform)
|
27
|
+
true
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.rejected_options
|
31
|
+
%i[
|
32
|
+
restore
|
33
|
+
appx_output_path
|
34
|
+
appx_output_name
|
35
|
+
appx_bundle_platforms
|
36
|
+
build_mode
|
37
|
+
skip_codesigning
|
38
|
+
]
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.category
|
42
|
+
:building
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
require "fastlane/action"
|
2
|
+
|
3
|
+
module Fastlane
|
4
|
+
module Actions
|
5
|
+
module SharedValues
|
6
|
+
SF_CERTIFICATE_PATH = :SF_CERTIFICATE_PATH
|
7
|
+
SF_CERTIFICATE_PASSWORD = :SF_CERTIFICATE_PASSWORD
|
8
|
+
SF_CERTIFICATE_THUMBPRINT = :SF_CERTIFICATE_THUMBPRINT
|
9
|
+
end
|
10
|
+
|
11
|
+
class UpdateUwpSigningSettingsAction < Action
|
12
|
+
def self.run(params)
|
13
|
+
path = params[:certificate]
|
14
|
+
|
15
|
+
Actions.lane_context[SharedValues::SF_CERTIFICATE_PATH] = path
|
16
|
+
Actions.lane_context[SharedValues::SF_CERTIFICATE_PASSWORD] = params[:password]
|
17
|
+
Actions.lane_context[SharedValues::SF_CERTIFICATE_THUMBPRINT] = params[:thumbprint]
|
18
|
+
|
19
|
+
UI.message("Setting signing certificate to '#{path}' for all next build steps")
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.description
|
23
|
+
"Configures UWP package signing settings. Works only on 'windows' platform. Values that would be set in this action will be applied to all next actions."
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.details
|
27
|
+
"Works only on `windows` platform"
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.authors
|
31
|
+
["CheeryLee"]
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.is_supported?(platform)
|
35
|
+
[:windows].include?(platform)
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.available_options
|
39
|
+
[
|
40
|
+
FastlaneCore::ConfigItem.new(
|
41
|
+
key: :certificate,
|
42
|
+
description: "Path to the certificate to use",
|
43
|
+
optional: false,
|
44
|
+
type: String,
|
45
|
+
verify_block: proc do |value|
|
46
|
+
UI.user_error!("Path to certificate is invalid") unless value && !value.empty?
|
47
|
+
UI.user_error!("The provided path doesn't point to PFX-file") unless
|
48
|
+
File.exist?(File.expand_path(value)) && value.end_with?(".pfx")
|
49
|
+
end
|
50
|
+
),
|
51
|
+
FastlaneCore::ConfigItem.new(
|
52
|
+
key: :password,
|
53
|
+
description: "The password for the private key in the certificate",
|
54
|
+
optional: true,
|
55
|
+
default_value: "",
|
56
|
+
type: String
|
57
|
+
),
|
58
|
+
FastlaneCore::ConfigItem.new(
|
59
|
+
key: :thumbprint,
|
60
|
+
description: "This value must match the thumbprint in the signing certificate or be an empty string",
|
61
|
+
optional: true,
|
62
|
+
default_value: "",
|
63
|
+
type: String
|
64
|
+
)
|
65
|
+
]
|
66
|
+
end
|
67
|
+
|
68
|
+
def self.category
|
69
|
+
:code_signing
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,218 @@
|
|
1
|
+
require "fastlane/action"
|
2
|
+
require_relative "../helper/ms_devcenter_helper"
|
3
|
+
require_relative "../msbuild/options"
|
4
|
+
|
5
|
+
module Fastlane
|
6
|
+
module Actions
|
7
|
+
class UploadMsStoreAction < Action
|
8
|
+
DEFAULT_TIMEOUT = 300
|
9
|
+
|
10
|
+
def self.run(params)
|
11
|
+
tenant_id = Actions.lane_context[SharedValues::SF_MS_TENANT_ID]
|
12
|
+
client_id = Actions.lane_context[SharedValues::SF_MS_CLIENT_ID]
|
13
|
+
client_secret = Actions.lane_context[SharedValues::SF_MS_CLIENT_SECRET]
|
14
|
+
app_id = params[:app_id]
|
15
|
+
path = params[:path]
|
16
|
+
timeout = params.values.include?(:timeout) && params[:timeout].positive? ? params[:timeout] : DEFAULT_TIMEOUT
|
17
|
+
|
18
|
+
UI.message("Acquiring authorization token for DevCenter ...")
|
19
|
+
auth_token = Helper::MsDevCenterHelper.acquire_authorization_token(tenant_id, client_id, client_secret, timeout)
|
20
|
+
UI.message("Authorization token was obtained")
|
21
|
+
|
22
|
+
UI.message("Creating submission for app #{app_id} ...")
|
23
|
+
submission_obj = Helper::MsDevCenterHelper.create_submission(app_id, auth_token, timeout)
|
24
|
+
submission_id = submission_obj["id"]
|
25
|
+
UI.message("Submission #{submission_id} created")
|
26
|
+
|
27
|
+
UI.message("Prepare ZIP blob for upload ...")
|
28
|
+
zip_path = create_blob_zip(File.expand_path(path))
|
29
|
+
UI.success("Blob is ready")
|
30
|
+
|
31
|
+
UI.message("Uploading ZIP blob ...")
|
32
|
+
Helper::MsDevCenterHelper.upload_blob(submission_obj["fileUploadUrl"], zip_path, timeout)
|
33
|
+
UI.success("ZIP blob uploaded successfully")
|
34
|
+
|
35
|
+
submission_obj = prepare_empty_submission(submission_obj)
|
36
|
+
submission_obj = add_package_to_submission(submission_obj, File.basename(path))
|
37
|
+
|
38
|
+
UI.message("Updating submission data ...")
|
39
|
+
Helper::MsDevCenterHelper.update_submission(app_id, submission_obj, auth_token, timeout)
|
40
|
+
UI.message("Updated successfully")
|
41
|
+
|
42
|
+
UI.message("Committing ...")
|
43
|
+
Helper::MsDevCenterHelper.commit_submission(app_id, submission_id, auth_token, timeout)
|
44
|
+
|
45
|
+
if params.values.include?(:skip_waiting_for_build_processing) &&
|
46
|
+
[true].include?(params[:skip_waiting_for_build_processing])
|
47
|
+
UI.success("Submission passed, but build processing were skipped. Check the Dev Center page.")
|
48
|
+
return
|
49
|
+
|
50
|
+
end
|
51
|
+
|
52
|
+
status = false
|
53
|
+
data = nil
|
54
|
+
until status
|
55
|
+
UI.message("Waiting for the submission to change the status - this may take a few minutes")
|
56
|
+
data = Helper::MsDevCenterHelper.get_submission_status(app_id, submission_id, auth_token, timeout)
|
57
|
+
status = data["status"] != "CommitStarted"
|
58
|
+
sleep(30) unless status
|
59
|
+
end
|
60
|
+
|
61
|
+
if data["status"] == "CommitFailed"
|
62
|
+
errors = data["statusDetails"]["errors"]
|
63
|
+
if errors.length == 1 && errors[0]["code"] == "InvalidState"
|
64
|
+
UI.important(
|
65
|
+
[
|
66
|
+
"All submission operations passed correctly, but there are some things that you need to proceed using DevCenter.",
|
67
|
+
"Message: #{errors[0]["details"]}"
|
68
|
+
].join("\n")
|
69
|
+
)
|
70
|
+
return
|
71
|
+
end
|
72
|
+
|
73
|
+
errors.each do |error|
|
74
|
+
UI.error("Error code: #{error["code"]}\nMessage: #{error["details"]}")
|
75
|
+
end
|
76
|
+
|
77
|
+
UI.user_error!("Submission failed")
|
78
|
+
end
|
79
|
+
|
80
|
+
UI.success("Submission passed. Check the DevCenter page.")
|
81
|
+
end
|
82
|
+
|
83
|
+
def self.description
|
84
|
+
"Uploads new binary to Microsoft Partner Center"
|
85
|
+
end
|
86
|
+
|
87
|
+
def self.authors
|
88
|
+
["CheeryLee"]
|
89
|
+
end
|
90
|
+
|
91
|
+
def self.is_supported?(platform)
|
92
|
+
[:windows].include?(platform)
|
93
|
+
end
|
94
|
+
|
95
|
+
def self.available_options
|
96
|
+
[
|
97
|
+
FastlaneCore::ConfigItem.new(
|
98
|
+
key: :timeout,
|
99
|
+
description: "The timeout for pushing to a server in seconds",
|
100
|
+
optional: true,
|
101
|
+
default_value: 0,
|
102
|
+
type: Integer
|
103
|
+
),
|
104
|
+
FastlaneCore::ConfigItem.new(
|
105
|
+
key: :app_id,
|
106
|
+
description: "The Microsoft Store ID of an application",
|
107
|
+
optional: false,
|
108
|
+
type: String,
|
109
|
+
verify_block: proc do |value|
|
110
|
+
UI.user_error!("The Microsoft Store ID can't be empty") unless value && !value.empty?
|
111
|
+
end
|
112
|
+
),
|
113
|
+
FastlaneCore::ConfigItem.new(
|
114
|
+
key: :skip_waiting_for_build_processing,
|
115
|
+
description: "If set to true, the action will only commit the submission and skip the remaining build validation",
|
116
|
+
optional: true,
|
117
|
+
default_value: false,
|
118
|
+
type: Fastlane::Boolean
|
119
|
+
),
|
120
|
+
FastlaneCore::ConfigItem.new(
|
121
|
+
key: :path,
|
122
|
+
description: "The file path to the package to be uploaded",
|
123
|
+
optional: false,
|
124
|
+
type: String,
|
125
|
+
verify_block: proc do |value|
|
126
|
+
UI.user_error!("Path to UWP package is invalid") unless value && !value.empty?
|
127
|
+
|
128
|
+
format_valid = false
|
129
|
+
Msbuild::Options::PACKAGE_FORMATS.each do |extension|
|
130
|
+
if value.end_with?(extension)
|
131
|
+
format_valid = true
|
132
|
+
break
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
UI.user_error!("The provided path doesn't point to UWP file") unless
|
137
|
+
File.exist?(File.expand_path(value)) && format_valid
|
138
|
+
end
|
139
|
+
)
|
140
|
+
]
|
141
|
+
end
|
142
|
+
|
143
|
+
def self.category
|
144
|
+
:production
|
145
|
+
end
|
146
|
+
|
147
|
+
def self.create_blob_zip(package_path)
|
148
|
+
File.delete(File.join(File.dirname(package_path), "blob.zip"))
|
149
|
+
zip_path = File.join(File.dirname(package_path), "blob.zip")
|
150
|
+
|
151
|
+
Zip::File.open(zip_path, create: true) do |file|
|
152
|
+
file.add(File.basename(package_path), package_path)
|
153
|
+
|
154
|
+
screenshot_path = File.join(Helper::SapfireHelper.root_plugin_location, "assets", "ms_example_screenshot.png")
|
155
|
+
file.add("ms_example_screenshot.png", File.expand_path(screenshot_path))
|
156
|
+
end
|
157
|
+
|
158
|
+
zip_path
|
159
|
+
end
|
160
|
+
|
161
|
+
def self.add_package_to_submission(submission_obj, file_name)
|
162
|
+
check_submission(submission_obj)
|
163
|
+
UI.user_error!("Package file name can't be null or empty") if file_name.nil? || file_name.empty?
|
164
|
+
|
165
|
+
key = "applicationPackages"
|
166
|
+
package = {
|
167
|
+
"fileName": file_name,
|
168
|
+
"fileStatus": "PendingUpload",
|
169
|
+
"minimumDirectXVersion": "None",
|
170
|
+
"minimumSystemRam": "None"
|
171
|
+
}
|
172
|
+
|
173
|
+
submission_obj[key] = [] if submission_obj[key].empty?
|
174
|
+
submission_obj[key].append(package)
|
175
|
+
submission_obj
|
176
|
+
end
|
177
|
+
|
178
|
+
def self.prepare_empty_submission(submission_obj)
|
179
|
+
check_submission(submission_obj)
|
180
|
+
|
181
|
+
submission_obj["applicationCategory"] = "UtilitiesAndTools" if submission_obj["applicationCategory"] == "NotSet"
|
182
|
+
submission_obj["targetPublishMode"] = "Manual"
|
183
|
+
|
184
|
+
if submission_obj["allowTargetFutureDeviceFamilies"].empty?
|
185
|
+
submission_obj["allowTargetFutureDeviceFamilies"] = {
|
186
|
+
"Desktop": false,
|
187
|
+
"Mobile": false,
|
188
|
+
"Holographic": false,
|
189
|
+
"Xbox": false
|
190
|
+
}
|
191
|
+
end
|
192
|
+
|
193
|
+
if submission_obj["listings"].empty?
|
194
|
+
submission_obj["listings"]["en-us"] = {}
|
195
|
+
submission_obj["listings"]["en-us"]["baseListing"] = {
|
196
|
+
"description": "1",
|
197
|
+
"privacyPolicy": "https://example.com",
|
198
|
+
"images": [
|
199
|
+
{
|
200
|
+
"fileName": "ms_example_screenshot.png",
|
201
|
+
"fileStatus": "PendingUpload",
|
202
|
+
"imageType": "Screenshot"
|
203
|
+
}
|
204
|
+
]
|
205
|
+
}
|
206
|
+
end
|
207
|
+
|
208
|
+
submission_obj
|
209
|
+
end
|
210
|
+
|
211
|
+
def self.check_submission(submission_obj)
|
212
|
+
UI.user_error!("Submission data object need to be provided") if submission_obj.nil?
|
213
|
+
end
|
214
|
+
|
215
|
+
private_constant(:DEFAULT_TIMEOUT)
|
216
|
+
end
|
217
|
+
end
|
218
|
+
end
|