fastlane-plugin-amazon_app_submission 0.1.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +68 -1
- data/lib/fastlane/plugin/amazon_app_submission/actions/amazon_app_submission_action.rb +47 -12
- data/lib/fastlane/plugin/amazon_app_submission/helper/amazon_app_submission_helper.rb +112 -34
- data/lib/fastlane/plugin/amazon_app_submission/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f52eed564ae7f2ef5d42738c00c3f45a71e0438cb63b6bcad67b53f0c646562b
|
4
|
+
data.tar.gz: 623727ff4a80c261d9ff34c28b012b2c2f067295eabdb3cf40ee2dbbc1f0e40c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c9e84b1862121a03660d78b7fdcd5c0a45290982f5e5e8fd1a5b76bdfc37dfa199c9f03c9c7262cf262e6fdb7a0ac6b3cf6633244f93e937acde4494d8ccdfa9
|
7
|
+
data.tar.gz: d345f6b63c462c4510edc2df6e9aa3957711abf93e83f58f022c8742117fe9bc6db8ebd920a94568dcbd3c9c7c461eb9e25a57ac3b5fa698cae8b5d2bf479140
|
data/README.md
CHANGED
@@ -1 +1,68 @@
|
|
1
|
-
# amazon-app-
|
1
|
+
# fastlane-plugin-amazon-app-submission
|
2
|
+
|
3
|
+
## Getting Started
|
4
|
+
|
5
|
+
This project is a [_fastlane_](https://github.com/fastlane/fastlane) plugin. To get started with `amazon_app_submission`, add it to your project by running:
|
6
|
+
|
7
|
+
```bash
|
8
|
+
fastlane add_plugin amazon_app_submission
|
9
|
+
```
|
10
|
+
|
11
|
+
## About amazon_app_submission
|
12
|
+
|
13
|
+
* Project link on rubygems [fastlane-plugin-amazon_app_submission](https://rubygems.org/gems/fastlane-plugin-amazon_app_submission)
|
14
|
+
* Upload the apk to the Amazon Appstore using the [App Submission API](https://developer.amazon.com/docs/app-submission-api/overview.html).
|
15
|
+
* App Submission API Reference is [App Submission RESTFUL API](https://developer.amazon.com/docs/app-submission-api/appsub-api-ref.html).
|
16
|
+
|
17
|
+
## Usage
|
18
|
+
|
19
|
+
Following the [guide](https://developer.amazon.com/docs/app-submission-api/auth.html), you will need to generate `client_id` and `client_secret` to access the console in advance.
|
20
|
+
|
21
|
+
For `app_id` you can get it from Amazon app dashboard
|
22
|
+
Please set the apk path to `apk_path` field
|
23
|
+
|
24
|
+
Call `amazon_app_submission` in your Fastfile.
|
25
|
+
|
26
|
+
```ruby
|
27
|
+
amazon_app_submission(
|
28
|
+
client_id: "<CLIENT_ID>",
|
29
|
+
client_secret: "<CLIENT_SECRET>",
|
30
|
+
app_id: "<APP_ID>",
|
31
|
+
apk_path: "<APK_PATH>",
|
32
|
+
# Optional
|
33
|
+
changelogs_folder_path: "<CHANGELOG_PATH>",
|
34
|
+
upload_changelogs: false,
|
35
|
+
submit_for_review: false
|
36
|
+
)
|
37
|
+
```
|
38
|
+
|
39
|
+
| param | default value | optional | description
|
40
|
+
|:----------|:-----------:|:-----------:|:-----------:|
|
41
|
+
client_id | - | false | getting client id from Amazon developer console dashboard
|
42
|
+
client_secret | - | false | getting client secret from Amazon developer console dashboard
|
43
|
+
app_id | - | false | getting app id from Amazon developer console dashboard
|
44
|
+
apk_path | - | false | link where you storing the release apk
|
45
|
+
changelogs_folder_path | "" | true | setting the folder path where you have the change logs with different file for each language, if language file not found it will use default.txt
|
46
|
+
upload_changelogs | false | true | updating the change logs for the upcoming version
|
47
|
+
submit_for_review | false | true | submit the uploaded APK to the store
|
48
|
+
|
49
|
+
* changelogs folder files name should be:
|
50
|
+
|
51
|
+
| Language | File name
|
52
|
+
|:----------|:-----------:|
|
53
|
+
English-US | en-US.txt
|
54
|
+
English-British | en-GB.txt
|
55
|
+
English-Australia | en-AU.txt
|
56
|
+
English-India | en-IN.txt
|
57
|
+
Italian |it-IT.txt
|
58
|
+
French | fr-FR.txt
|
59
|
+
Spanish | es-ES.txt
|
60
|
+
Spanish-Mexican | es-MX.txt
|
61
|
+
Other | default.txt
|
62
|
+
|
63
|
+
## Testing
|
64
|
+
|
65
|
+
For testing the plugin locally you have to get `client_id`, `client_secret`, `app_id` and `apk_path` in fastlane/Fastfile
|
66
|
+
please check Usage step to see how you can get them.
|
67
|
+
|
68
|
+
Then call `bundle exec fastlane test` in your terminal
|
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
require 'fastlane/action'
|
2
2
|
require_relative '../helper/amazon_app_submission_helper'
|
3
3
|
|
4
4
|
module Fastlane
|
@@ -11,31 +11,45 @@ module Fastlane
|
|
11
11
|
|
12
12
|
if token.nil?
|
13
13
|
UI.message("Cannot retrieve token, please check your client ID and client secret")
|
14
|
-
else
|
15
|
-
UI.message("the token is #{token}")
|
16
14
|
end
|
17
15
|
|
16
|
+
UI.message("Getting current edit")
|
18
17
|
current_edit_id, edit_eTag = Helper::AmazonAppSubmissionHelper.open_edit(token, params[:app_id])
|
19
18
|
|
20
19
|
if current_edit_id.nil?
|
20
|
+
UI.message("Current edit not found, creating a new edit")
|
21
21
|
Helper::AmazonAppSubmissionHelper.create_new_edit(token, params[:app_id])
|
22
22
|
current_edit_id, edit_eTag = Helper::AmazonAppSubmissionHelper.open_edit(token, params[:app_id])
|
23
23
|
end
|
24
24
|
|
25
|
+
UI.message("Get current apk id")
|
25
26
|
current_apk_id = Helper::AmazonAppSubmissionHelper.get_current_apk_id(token, params[:app_id], current_edit_id)
|
26
27
|
|
28
|
+
UI.message("Get current apk ETag")
|
27
29
|
current_apk_eTag = Helper::AmazonAppSubmissionHelper.get_current_apk_etag(token, params[:app_id], current_edit_id, current_apk_id)
|
28
30
|
|
29
|
-
|
30
|
-
|
31
|
-
if replace_apk_response_code === 200
|
32
|
-
Helper::AmazonAppSubmissionHelper.commit_edit(token, params[:app_id], current_edit_id, edit_eTag)
|
33
|
-
end
|
31
|
+
UI.message("Replacing the apk with ETag #{current_apk_eTag}")
|
32
|
+
replace_apk_response_code, replace_apk_response = Helper::AmazonAppSubmissionHelper.replaceExistingApk(token, params[:app_id], current_edit_id, current_apk_id, current_apk_eTag, params[:apk_path])
|
34
33
|
|
34
|
+
if params[:upload_changelogs]
|
35
|
+
UI.message("Updating the changelogs")
|
36
|
+
Helper::AmazonAppSubmissionHelper.update_listings( token, params[:app_id],current_edit_id, params[:changelogs_path], params[:changelogs_path])
|
37
|
+
end
|
38
|
+
|
39
|
+
if replace_apk_response_code == '200'
|
40
|
+
if params[:submit_for_review]
|
41
|
+
UI.message("Submitting to Amazon app store")
|
42
|
+
Helper::AmazonAppSubmissionHelper.commit_edit(token, params[:app_id], current_edit_id, edit_eTag)
|
43
|
+
end
|
44
|
+
else
|
45
|
+
UI.message("Amazon app submission failed at replacing the apk error code #{replace_apk_response_code} and error respones #{replace_apk_response}")
|
46
|
+
return
|
47
|
+
end
|
48
|
+
UI.message("Amazon app submission finished successfully!")
|
35
49
|
end
|
36
50
|
|
37
51
|
def self.description
|
38
|
-
"
|
52
|
+
"fast-lane plugin for Amazon App Submissions"
|
39
53
|
end
|
40
54
|
|
41
55
|
def self.authors
|
@@ -48,7 +62,7 @@ module Fastlane
|
|
48
62
|
|
49
63
|
def self.details
|
50
64
|
# Optional:
|
51
|
-
"
|
65
|
+
"fast-lane plugin for Amazon App Submissions"
|
52
66
|
end
|
53
67
|
|
54
68
|
def self.available_options
|
@@ -75,8 +89,29 @@ module Fastlane
|
|
75
89
|
env_name: "AMAZON_APP_SUBMISSION_APK_PATH",
|
76
90
|
description: "Amazon App Submission APK Path",
|
77
91
|
optional: false,
|
78
|
-
type: String)
|
79
|
-
|
92
|
+
type: String),
|
93
|
+
|
94
|
+
FastlaneCore::ConfigItem.new(key: :changelogs_path,
|
95
|
+
env_name: "AMAZON_APP_SUBMISSION_CHANGELOGS_PATH",
|
96
|
+
description: "Amazon App Submission changelogs path",
|
97
|
+
default_value: "",
|
98
|
+
optional: true,
|
99
|
+
type: String),
|
100
|
+
|
101
|
+
FastlaneCore::ConfigItem.new(key: :upload_changelogs,
|
102
|
+
env_name: "AMAZON_APP_SUBMISSION_SKIP_UPLOAD_CHANGELOGS",
|
103
|
+
description: "Amazon App Submission skip upload changelogs",
|
104
|
+
default_value: false,
|
105
|
+
optional: true,
|
106
|
+
type: Boolean),
|
107
|
+
|
108
|
+
FastlaneCore::ConfigItem.new(key: :submit_for_review,
|
109
|
+
env_name: "AMAZON_APP_SUBMISSION_SUBMIT_FOR_REVIEW",
|
110
|
+
description: "Amazon App Submission submit for review",
|
111
|
+
default_value: false,
|
112
|
+
optional: true,
|
113
|
+
type: Boolean)
|
114
|
+
|
80
115
|
# FastlaneCore::ConfigItem.new(key: :your_option,
|
81
116
|
# env_name: "AMAZON_APP_SUBMISSION_YOUR_OPTION",
|
82
117
|
# description: "A description of your option",
|
@@ -13,10 +13,6 @@ module Fastlane
|
|
13
13
|
|
14
14
|
def self.get_token(client_id, client_secret)
|
15
15
|
UI.important("Fetching app access token")
|
16
|
-
|
17
|
-
UI.important("client_id #{client_id}")
|
18
|
-
UI.important("client_secret #{client_secret}")
|
19
|
-
|
20
16
|
uri = URI('https://api.amazon.com/auth/o2/token')
|
21
17
|
http = Net::HTTP.new(uri.host, uri.port)
|
22
18
|
http.use_ssl = true
|
@@ -26,9 +22,8 @@ module Fastlane
|
|
26
22
|
|
27
23
|
res = http.request(req)
|
28
24
|
result_json = JSON.parse(res.body)
|
29
|
-
|
30
25
|
auth_token = "Bearer #{result_json['access_token']}"
|
31
|
-
|
26
|
+
|
32
27
|
return auth_token
|
33
28
|
end
|
34
29
|
|
@@ -69,17 +64,15 @@ module Fastlane
|
|
69
64
|
res = http.request(req)
|
70
65
|
current_edit = JSON.parse(res.body)
|
71
66
|
|
72
|
-
UI.message("eTag #{res.header['ETag']}")
|
73
|
-
|
74
67
|
return current_edit['id'], res.header['ETag']
|
75
68
|
end
|
76
69
|
|
77
|
-
def self.
|
70
|
+
def self.get_current_apk_id(token, app_id, edit_id)
|
78
71
|
|
79
|
-
|
80
|
-
|
72
|
+
get_apks_path = "/v1/applications/#{app_id}/edits/#{edit_id}/apks"
|
73
|
+
get_apks_url = BASE_URL + get_apks_path
|
81
74
|
|
82
|
-
uri = URI(
|
75
|
+
uri = URI(get_apks_url)
|
83
76
|
http = Net::HTTP.new(uri.host, uri.port)
|
84
77
|
http.use_ssl = true
|
85
78
|
req = Net::HTTP::Get.new(
|
@@ -89,15 +82,20 @@ module Fastlane
|
|
89
82
|
)
|
90
83
|
|
91
84
|
res = http.request(req)
|
92
|
-
|
85
|
+
if !res.body.nil?
|
86
|
+
apks = JSON.parse(res.body)
|
87
|
+
firstAPK = apks[0]
|
88
|
+
apk_id = firstAPK['id']
|
89
|
+
return apk_id
|
90
|
+
end
|
93
91
|
end
|
94
92
|
|
95
|
-
def self.
|
93
|
+
def self.get_current_apk_etag(token, app_id, edit_id, apk_id)
|
96
94
|
|
97
|
-
|
98
|
-
|
95
|
+
get_apks_etag = "/v1/applications/#{app_id}/edits/#{edit_id}/apks/#{apk_id}"
|
96
|
+
get_apks_etag_url = BASE_URL + get_apks_etag
|
99
97
|
|
100
|
-
uri = URI(
|
98
|
+
uri = URI(get_apks_etag_url)
|
101
99
|
http = Net::HTTP.new(uri.host, uri.port)
|
102
100
|
http.use_ssl = true
|
103
101
|
req = Net::HTTP::Get.new(
|
@@ -107,34 +105,40 @@ module Fastlane
|
|
107
105
|
)
|
108
106
|
|
109
107
|
res = http.request(req)
|
110
|
-
|
111
|
-
apks = JSON.parse(res.body)
|
112
|
-
firstAPK = apks[0]
|
113
|
-
apk_id = firstAPK['id']
|
114
|
-
return apk_id
|
115
|
-
end
|
108
|
+
return res.header['ETag']
|
116
109
|
end
|
117
110
|
|
118
|
-
def self.replaceExistingApk(token, app_id, edit_id, apk_id, eTag, apk_path)
|
111
|
+
def self.replaceExistingApk(token, app_id, edit_id, apk_id, eTag, apk_path, should_retry = true)
|
119
112
|
|
120
113
|
replace_apk_path = "/v1/applications/#{app_id}/edits/#{edit_id}/apks/#{apk_id}/replace"
|
121
114
|
local_apk = File.open(apk_path, "r").read
|
122
115
|
|
116
|
+
apk_uri = URI.parse(apk_path)
|
117
|
+
apk_name = apk_uri.path.split('/').last
|
118
|
+
|
123
119
|
replace_apk_url = BASE_URL + replace_apk_path
|
124
120
|
uri = URI(replace_apk_url)
|
125
121
|
http = Net::HTTP.new(uri.host, uri.port)
|
126
122
|
http.use_ssl = true
|
127
|
-
http.write_timeout =
|
123
|
+
http.write_timeout = 1000
|
128
124
|
req = Net::HTTP::Put.new(
|
129
125
|
uri.path,
|
130
126
|
'Authorization' => token,
|
131
127
|
'Content-Type' => 'application/vnd.android.package-archive',
|
128
|
+
'fileName' => apk_name,
|
132
129
|
'If-Match' => eTag
|
133
130
|
)
|
134
131
|
|
135
132
|
req.body = local_apk
|
136
133
|
res = http.request(req)
|
137
|
-
|
134
|
+
replace_apk_response = JSON.parse(res.body)
|
135
|
+
# Retry again if replace failed
|
136
|
+
if res.code == '412' && should_retry
|
137
|
+
UI.message("replacing the apk failed, retrying uploading it again...")
|
138
|
+
replaceExistingApk(token, app_id, edit_id, apk_id, eTag, apk_path, false)
|
139
|
+
return
|
140
|
+
end
|
141
|
+
return res.code, replace_apk_response
|
138
142
|
end
|
139
143
|
|
140
144
|
def self.delete_apk(token, app_id, edit_id, apk_id, eTag)
|
@@ -142,8 +146,6 @@ module Fastlane
|
|
142
146
|
delete_apk_path = "/v1/applications/#{app_id}/edits/#{edit_id}/apks/#{apk_id}"
|
143
147
|
delete_apk_url = BASE_URL + delete_apk_path
|
144
148
|
|
145
|
-
UI.message("delete_apk_url #{delete_apk_url}")
|
146
|
-
|
147
149
|
uri = URI(delete_apk_url)
|
148
150
|
http = Net::HTTP.new(uri.host, uri.port)
|
149
151
|
http.use_ssl = true
|
@@ -167,8 +169,8 @@ module Fastlane
|
|
167
169
|
uri = URI(add_apk_url)
|
168
170
|
http = Net::HTTP.new(uri.host, uri.port)
|
169
171
|
http.use_ssl = true
|
170
|
-
http.write_timeout =
|
171
|
-
http.read_timeout =
|
172
|
+
http.write_timeout = 1000
|
173
|
+
http.read_timeout = 1000
|
172
174
|
req = Net::HTTP::Post.new(
|
173
175
|
uri.path,
|
174
176
|
'Authorization' => token,
|
@@ -180,6 +182,86 @@ module Fastlane
|
|
180
182
|
result_json = JSON.parse(res.body)
|
181
183
|
end
|
182
184
|
|
185
|
+
def self.update_listings(token, app_id, edit_id, changelogs_path, upload_changelogs)
|
186
|
+
|
187
|
+
listings_path = "/v1/applications/#{app_id}/edits/#{edit_id}/listings"
|
188
|
+
listings_url = BASE_URL + listings_path
|
189
|
+
|
190
|
+
uri = URI(listings_url)
|
191
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
192
|
+
http.use_ssl = true
|
193
|
+
req = Net::HTTP::Get.new(
|
194
|
+
uri.path,
|
195
|
+
'Authorization' => token,
|
196
|
+
'Content-Type' => 'application/json'
|
197
|
+
)
|
198
|
+
|
199
|
+
res = http.request(req)
|
200
|
+
listings_response = JSON.parse(res.body)
|
201
|
+
|
202
|
+
# Iterating over the languages for getting the ETag.
|
203
|
+
listings_response['listings'].each do |lang, listing|
|
204
|
+
lang_path = "/v1/applications/#{app_id}/edits/#{edit_id}/listings/#{lang}"
|
205
|
+
lang_url = BASE_URL + lang_path
|
206
|
+
|
207
|
+
uri = URI(lang_url)
|
208
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
209
|
+
http.use_ssl = true
|
210
|
+
req = Net::HTTP::Get.new(
|
211
|
+
uri.path,
|
212
|
+
'Authorization' => token,
|
213
|
+
'Content-Type' => 'application/json'
|
214
|
+
)
|
215
|
+
etag_response = http.request(req)
|
216
|
+
etag = etag_response.header['Etag']
|
217
|
+
|
218
|
+
recent_changes = find_changelog(
|
219
|
+
changelogs_path,
|
220
|
+
lang,
|
221
|
+
upload_changelogs,
|
222
|
+
)
|
223
|
+
|
224
|
+
listing[:recentChanges] = recent_changes
|
225
|
+
|
226
|
+
update_listings_path = "/v1/applications/#{app_id}/edits/#{edit_id}/listings/#{lang}"
|
227
|
+
update_listings_url = BASE_URL + update_listings_path
|
228
|
+
|
229
|
+
uri = URI(update_listings_url)
|
230
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
231
|
+
http.use_ssl = true
|
232
|
+
req = Net::HTTP::Put.new(
|
233
|
+
uri.path,
|
234
|
+
'Authorization' => token,
|
235
|
+
'Content-Type' => 'application/json',
|
236
|
+
'If-Match' => etag
|
237
|
+
)
|
238
|
+
|
239
|
+
req.body = listing.to_json
|
240
|
+
res = http.request(req)
|
241
|
+
listings_response = JSON.parse(res.body)
|
242
|
+
end
|
243
|
+
end
|
244
|
+
|
245
|
+
def self.find_changelog(changelogs_path, language, upload_changelogs)
|
246
|
+
# The Amazon appstore requires you to enter changelogs before reviewing.
|
247
|
+
# Therefore, if there is no metadata, hyphen text is returned.
|
248
|
+
changelog_text = '-'
|
249
|
+
return changelog_text if !upload_changelogs
|
250
|
+
|
251
|
+
path = File.join(changelogs_path, "#{language}.txt")
|
252
|
+
if File.exist?(path) && !File.zero?(path)
|
253
|
+
changelog_text = File.read(path, encoding: 'UTF-8')
|
254
|
+
else
|
255
|
+
defalut_changelog_path = File.join(changelogs_path, 'default.txt')
|
256
|
+
if File.exist?(defalut_changelog_path) && !File.zero?(defalut_changelog_path)
|
257
|
+
changelog_text = File.read(defalut_changelog_path, encoding: 'UTF-8')
|
258
|
+
else
|
259
|
+
UI.message("Could not find changelog for language '#{language}' at path #{path}...")
|
260
|
+
end
|
261
|
+
end
|
262
|
+
changelog_text
|
263
|
+
end
|
264
|
+
|
183
265
|
def self.commit_edit(token, app_id, edit_id, eTag)
|
184
266
|
|
185
267
|
commit_edit_path = "/v1/applications/#{app_id}/edits/#{edit_id}/commit"
|
@@ -197,10 +279,6 @@ module Fastlane
|
|
197
279
|
res = http.request(req)
|
198
280
|
result_json = JSON.parse(res.body)
|
199
281
|
end
|
200
|
-
|
201
|
-
def self.show_message
|
202
|
-
UI.message("Hello from the amazon_app_submission plugin helper!")
|
203
|
-
end
|
204
282
|
end
|
205
283
|
end
|
206
284
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fastlane-plugin-amazon_app_submission
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- mohammedhemaid
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-06-
|
11
|
+
date: 2022-06-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -162,7 +162,7 @@ files:
|
|
162
162
|
- lib/fastlane/plugin/amazon_app_submission/actions/amazon_app_submission_action.rb
|
163
163
|
- lib/fastlane/plugin/amazon_app_submission/helper/amazon_app_submission_helper.rb
|
164
164
|
- lib/fastlane/plugin/amazon_app_submission/version.rb
|
165
|
-
homepage:
|
165
|
+
homepage: https://github.com/ugroupmedia/fastlane-plugin-amazon-app-store-submission
|
166
166
|
licenses:
|
167
167
|
- MIT
|
168
168
|
metadata: {}
|