Skip to content

Commit 02c9b6d

Browse files
committed
Add script to attempt group metrics upload
1 parent a510530 commit 02c9b6d

File tree

2 files changed

+97
-0
lines changed

2 files changed

+97
-0
lines changed

.buildkite/commands/build-and-test.sh

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,9 @@ for file in DerivedData/Logs/Build/*.xcactivitylog; do
5454
echo "$filename queued"
5555
done
5656

57+
echo "--- :arrow_up: Upload build metrics to Apps Metrics"
58+
ruby .buildkite/commands/upload_metrics.rb
59+
5760
echo "--- 🚦 Report Tests Status"
5861
if [[ $TESTS_EXIT_STATUS -eq 0 ]]; then
5962
echo "Unit Tests seems to have passed (exit code 0). All good 👍"
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
# frozen_string_literal: true
2+
3+
require 'json'
4+
require 'time'
5+
require 'open3'
6+
require 'net/http'
7+
require 'uri'
8+
require 'shellwords'
9+
10+
PREFIX = 'simplenote-ios'
11+
12+
XCRESULT_PATH = ARGV[0] || 'build/results/Simplenote.xcresult'
13+
14+
# Hardcoded auth config (or set via ENV)
15+
METRICS_URL = ENV['METRICS_URL'] || 'https://metrics.a8c-ci.services/api/grouped-metrics'
16+
TOKEN = ENV['APPS_METRICS_UPLOAD_TOKEN']
17+
18+
META = [
19+
{ name: 'simplenote-ios-user', value: ENV['USER'] || ENV['USERNAME'] || 'unknown' },
20+
{ name: 'simplenote-ios-project', value: 'simplenote-ios' },
21+
{ name: 'simplenote-ios-environment', value: ENV['CI'] ? 'CI' : 'LOCAL' },
22+
{ name: 'simplenote-ios-architecture', value: `uname -m`.strip },
23+
{ name: 'simplenote-ios-operating-system', value: `uname -s`.strip.downcase }
24+
].freeze
25+
26+
# ---------- HELPERS ----------
27+
def run_cmd!(cmd)
28+
out, err, status = Open3.capture3(cmd)
29+
raise "Command failed (#{status.exitstatus}): #{cmd}\n#{err}" unless status.success?
30+
31+
out
32+
end
33+
34+
def to_epoch_ms(str_time)
35+
return nil if str_time.nil? || str_time.empty?
36+
37+
(Time.parse(str_time).to_f * 1000).to_i
38+
rescue
39+
nil
40+
end
41+
42+
def dig_count(obj, *path)
43+
v = obj.dig(*path)
44+
return v.to_i if v.is_a?(Numeric) || v.is_a?(String)
45+
return v.length if v.is_a?(Array)
46+
47+
0
48+
end
49+
50+
raw_json = run_cmd!("xcrun xcresulttool get build-results --path #{Shellwords.escape(XCRESULT_PATH)} --format json")
51+
data = JSON.parse(raw_json)
52+
53+
end_time = (data['endTime'] * 1_000).round(0)
54+
start_time = (data['startTime'] * 1_000).round(0)
55+
56+
explicit_fields = {
57+
'action-title' => data['actionTitle'],
58+
'analyzer-warning-count' => data['analyzerWarningCount'],
59+
'end-time-unix-ms' => end_time,
60+
'error-count' => data['errorCount'],
61+
'start-time-unix-ms' => start_time,
62+
'status' => data['status'],
63+
'warning-count' => data['warningCount'],
64+
'build-time' => end_time - start_time
65+
}
66+
67+
metrics_payload = explicit_fields.map do |k, v|
68+
{ name: "#{PREFIX}-#{k}", value: v.to_s }
69+
end
70+
71+
payload = {
72+
meta: META,
73+
metrics: metrics_payload
74+
}
75+
76+
puts JSON.pretty_generate(payload)
77+
78+
uri = URI(METRICS_URL)
79+
http = Net::HTTP.new(uri.host, uri.port)
80+
http.use_ssl = (uri.scheme == 'https')
81+
82+
req = Net::HTTP::Post.new(uri.request_uri)
83+
req['Accept'] = 'application/json'
84+
req['Accept-Charset'] = 'UTF-8'
85+
req['Authorization'] = "Bearer #{TOKEN}"
86+
req['User-Agent'] = 'Xcode/xcresulttool'
87+
req['Content-Type'] = 'application/json'
88+
req.body = JSON.dump(payload)
89+
90+
res = http.request(req)
91+
92+
puts "POST #{METRICS_URL} -> #{res.code}"
93+
puts res.body
94+
exit(res.code.to_i.between?(200, 299) ? 0 : 1)

0 commit comments

Comments
 (0)