Skip to content

Commit 5fa4270

Browse files
committed
Implement send_metrics (using gzip'd payload)
1 parent e9a0f3f commit 5fa4270

File tree

4 files changed

+7721
-3
lines changed

4 files changed

+7721
-3
lines changed

lib/fastlane/plugin/wpmreleasetoolkit/models/app_size_metrics_payload.rb

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
require 'json'
2+
require('net/http')
3+
require('zlib')
24

35
module Fastlane
46
module WPMRT
@@ -43,11 +45,28 @@ def to_h
4345
#
4446
# @param [String] base_url The base URL of the App Metrics service
4547
# @param [String] api_token The API bearer token to use to register the metric.
48+
# @return [Integer] the HTTP response code
4649
#
4750
def send_metrics(base_url:, api_token:)
48-
# TODO: Implement this
49-
UI.message("TODO: Would send the following payload to #{base_url}:")
50-
UI.message(JSON.pretty_generate(to_h))
51+
uri = URI.parse(base_url)
52+
headers = {
53+
Authorization: "Bearer #{api_token}",
54+
Accept: 'application/json',
55+
'Content-Type': 'application/json',
56+
'Content-Encoding': 'gzip'
57+
}
58+
request = Net::HTTP::Post.new(uri, headers)
59+
60+
gzip = Zlib::GzipWriter.new(StringIO.new)
61+
gzip << to_h.to_json
62+
request.body = gzip.close.string
63+
64+
response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == 'https') do |http|
65+
http.request(request)
66+
end
67+
68+
UI.verbose("#{response.code} #{response.message}")
69+
response.code.to_i
5170
end
5271
end
5372
end

spec/ios_send_app_size_metrics_spec.rb

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,3 +40,86 @@
4040
expect(payload.to_h).to eq(expected_hash)
4141
end
4242
end
43+
44+
# A test double to mock the Gzip compression and keep the 'fake-compressed' result readable in test failures
45+
class GzipWriterDouble < StringIO
46+
def close
47+
super
48+
self # `GzipWriter#close` returns `self` after closing (allowing method chaining), unlike default `StringIO#close`
49+
end
50+
51+
def string
52+
"GZIP<#{super}>"
53+
end
54+
end
55+
56+
describe Fastlane::Actions::IosSendAppSizeMetricsAction do
57+
let(:test_data_dir) { File.join(File.dirname(__FILE__), 'test-data', 'app_size_metrics') }
58+
59+
def test_app_size_action(fake_ipa_size:, expected_json:, **other_action_args)
60+
mocked_endpoint = 'https://localhost/api/metrics'
61+
in_tmp_dir do |tmp_dir|
62+
ipa_path = File.join(tmp_dir, 'fake.ipa')
63+
File.write(ipa_path, SecureRandom.random_bytes(fake_ipa_size))
64+
allow(Zlib::GzipWriter).to receive(:new).and_return(GzipWriterDouble.new)
65+
66+
expected_headers = {
67+
Authorization: 'Bearer token/1',
68+
'Content-Type': 'application/json',
69+
'Content-Encoding': 'gzip'
70+
}
71+
72+
stub = stub_request(:post, mocked_endpoint).with(
73+
headers: expected_headers,
74+
body: "GZIP<#{expected_json}>"
75+
).to_return(status: 200)
76+
77+
code = run_described_fastlane_action(
78+
api_base_url: mocked_endpoint,
79+
api_token: 'token/1',
80+
ipa_path: ipa_path,
81+
**other_action_args
82+
)
83+
84+
expect(stub).to have_been_made.once
85+
expect(code).to eq(200)
86+
end
87+
end
88+
89+
it 'sends the right payload from just an ipa file' do
90+
expected_json = {
91+
meta: [
92+
{ name: 'App Name', value: 'my-app' },
93+
{ name: 'Build Type', value: 'beta' },
94+
{ name: 'App Version', value: '1.2.3' },
95+
],
96+
metrics: [
97+
{ name: 'File Size', value: 123_456 },
98+
]
99+
}.to_json
100+
101+
test_app_size_action(
102+
fake_ipa_size: 123_456,
103+
expected_json: expected_json,
104+
app_name: 'my-app',
105+
build_type: 'beta',
106+
app_version: '1.2.3'
107+
)
108+
end
109+
110+
it 'sends the right payload from an ipa file and an app-thinning.plist' do
111+
app_thinning_plist_path = File.join(test_data_dir, 'app-thinning.plist')
112+
expected_fixture = File.join(test_data_dir, 'app-size-metrics-payload.json')
113+
# Parse as Hash then reconvert to JSON, in order to get the 'minified' JSON version
114+
expected_json = JSON.parse(File.read(expected_fixture)).to_json
115+
116+
test_app_size_action(
117+
fake_ipa_size: 1337,
118+
expected_json: expected_json,
119+
app_thinning_plist_path: app_thinning_plist_path,
120+
app_name: 'wordpress',
121+
build_type: 'internal',
122+
app_version: '19.8.0.2'
123+
)
124+
end
125+
end

0 commit comments

Comments
 (0)