slack_page_speed 0.0.6 → 0.0.8
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 +4 -4
- data/bin/slack_page_speed +1 -1
- data/lib/slack_page_speed.rb +186 -160
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: e471a023a7b3da86129fb1778186644208c0174e
|
|
4
|
+
data.tar.gz: b8b8233436752ed9bb85d1c2ce27f795ea1e4782
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ee04bfebdb8aaa77d94e04c7535a2f4003d77094dc5e62c97743705192520cd86b4dc08b8d27d5c16028d1a4b6afdad355f2545a86dfc54281cab273658e9f11
|
|
7
|
+
data.tar.gz: f418d704cb4f9903728705a1b2b3fdfbdf7e6bd89ff3f7855e78c7837c66e0eac4ce8e71835a7eab67644b1d0006b88464ae8c025ee57c5f2dee29b43d614c49
|
data/bin/slack_page_speed
CHANGED
data/lib/slack_page_speed.rb
CHANGED
|
@@ -2,29 +2,26 @@ require 'httparty'
|
|
|
2
2
|
require 'json'
|
|
3
3
|
require 'yaml'
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
@
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
@
|
|
15
|
-
@
|
|
16
|
-
@
|
|
17
|
-
@
|
|
18
|
-
@
|
|
19
|
-
@
|
|
20
|
-
@
|
|
21
|
-
@
|
|
22
|
-
@
|
|
23
|
-
@
|
|
24
|
-
@
|
|
25
|
-
@message = configuration_info['include_timestamp'] ? "Page performance scores for #{Date.today.strftime('%d/%m/%Y')}. \n" : ''
|
|
26
|
-
@threshold = configuration_info['threshold'].to_i
|
|
27
|
-
@results = {}
|
|
5
|
+
class SlackPageSpeed
|
|
6
|
+
def main
|
|
7
|
+
configuration_info = YAML.load_file('configuration.yml')
|
|
8
|
+
@slack_post_url = configuration_info['slack_url']
|
|
9
|
+
|
|
10
|
+
HTTParty::Basement.default_options.update(verify: false)
|
|
11
|
+
@pagespeed_api_key = configuration_info['pagespeed_api_key']
|
|
12
|
+
@webpagetest_api_key = configuration_info['webpagetest_api_key']
|
|
13
|
+
@slack_post_url = configuration_info['slack_url']
|
|
14
|
+
@history_file = './pagespeed_history.txt'
|
|
15
|
+
@slack_channel = configuration_info['slack_channel']
|
|
16
|
+
@slack_username = configuration_info['slack_username']
|
|
17
|
+
@slack_bot_emoji = configuration_info['slack_bot_emoji']
|
|
18
|
+
@improvement_emoji = configuration_info['improvement_emoji']
|
|
19
|
+
@minimal_change_emoji = configuration_info['minimal_change_emoji']
|
|
20
|
+
@regression_emoji = configuration_info['regression_emoji']
|
|
21
|
+
@domain = configuration_info['domain']
|
|
22
|
+
@message = configuration_info['include_timestamp'] ? "Page performance scores for #{Date.today.strftime('%d/%m/%Y')}. \n" : ''
|
|
23
|
+
@threshold = configuration_info['threshold'].to_i
|
|
24
|
+
@results = {}
|
|
28
25
|
# @page_list = %w(
|
|
29
26
|
# credit-cards/
|
|
30
27
|
# life-insurance/
|
|
@@ -34,167 +31,196 @@ HTTParty::Basement.default_options.update(verify: false)
|
|
|
34
31
|
# car-insurance/
|
|
35
32
|
# Homepage
|
|
36
33
|
# )
|
|
37
|
-
@page_list = configuration_info['page_list']
|
|
34
|
+
@page_list = configuration_info['page_list']
|
|
38
35
|
|
|
39
36
|
# @run_results = [{}, {}, {}]
|
|
40
|
-
@run_results = [{}]
|
|
41
|
-
@page_list.each do |page|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
end
|
|
37
|
+
@run_results = [{}]
|
|
38
|
+
@page_list.each do |page|
|
|
39
|
+
search_string = page.gsub('-', '+').gsub('/', '')
|
|
40
|
+
search_string = search_string + '+switch' if page == 'energy/'
|
|
41
|
+
search_string = 'compare+the+market' if page == 'Homepage'
|
|
42
|
+
@results[page] = { search_string: search_string }
|
|
43
|
+
@run_results.each do |run_result|
|
|
44
|
+
run_result[page] = { search_string: search_string }
|
|
45
|
+
end
|
|
46
|
+
end
|
|
50
47
|
|
|
51
48
|
# Gets google page rank
|
|
52
|
-
def get_gpr(page, search_string, iteration)
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
end
|
|
49
|
+
def get_gpr(page, search_string, iteration)
|
|
50
|
+
puts page
|
|
51
|
+
response = JSON.parse(HTTParty.get("https://www.googleapis.com/customsearch/v1element?key=#{@pagespeed_api_key}&rsz=filtered_cse&num=10&hl=en&prettyPrint=false&source=gcsc&gss=.com&q=#{search_string}&sort=&googlehost=www.google.co.uk&oq=#{search_string}&gs_l=partner.12...31030.31885.0.34635.7.7.0.0.0.0.73.428.7.7.0.gsnos%2Cn%3D13...0.864j151518j7..1ac.1.25.partner..7.0.0.-WiGDitO8Y8&callback=google.search.Search.apiary19818&nocache=1502961217931").body.chomp[49..-3])
|
|
52
|
+
begin
|
|
53
|
+
@run_results[iteration][page][:rank] = response['results'].index { |result_property| result_property['url'].include? 'comparethemarket.com' } + 1
|
|
54
|
+
rescue NoMethodError => e
|
|
55
|
+
puts "Not on the front page of Google results for '#{page}'.\nResults were: \n"
|
|
56
|
+
response['results'].each { |result| puts result['url'] }
|
|
57
|
+
raise e
|
|
58
|
+
end
|
|
59
|
+
end
|
|
63
60
|
|
|
64
61
|
# Gets google pagespeed score for a 'page'
|
|
65
|
-
def get_gps_score(page, strategy, iteration)
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
end
|
|
62
|
+
def get_gps_score(page, strategy, iteration)
|
|
63
|
+
response = HTTParty.get("https://www.googleapis.com/pagespeedonline/v2/runPagespeed?url=#{@domain + page.gsub('Homepage', '') + '?src=TSTT'}&strategy=#{strategy}&key=#{@pagespeed_api_key}")
|
|
64
|
+
unless response.response.code == '200' && JSON.parse(response.body)['responseCode'] != '400'
|
|
65
|
+
puts response
|
|
66
|
+
raise "Couldn't get Google PageSpeed score for #{page}"
|
|
67
|
+
end
|
|
68
|
+
score = JSON.parse(response.body)['ruleGroups']['SPEED']['score']
|
|
69
|
+
@run_results[iteration][page][strategy.to_sym] = score
|
|
70
|
+
end
|
|
74
71
|
|
|
75
72
|
# runs a new WebPageTest test based on the url supplied
|
|
76
|
-
def start_wpt_test(page, iteration)
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
end
|
|
73
|
+
def start_wpt_test(page, iteration)
|
|
74
|
+
response = HTTParty.get("http://www.webpagetest.org/runtest.php?url=#{@domain + page.gsub('Homepage', '') + '?src=TSTT'}&location=Dulles.3G&f=json&fvonly=1&k=#{@webpagetest_api_key}")
|
|
75
|
+
raise "Couldn't get WebPageTest score for #{page}" unless response.response.code == '200'
|
|
76
|
+
@run_results[iteration][page][:results_url] = JSON.parse(response.body)['data']['jsonUrl']
|
|
77
|
+
end
|
|
81
78
|
|
|
82
79
|
# waits until the status of the run at 'results_url' is 200 (test finished)
|
|
83
|
-
def wait_for_wpt_results(page, result_url, iteration)
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
end
|
|
80
|
+
def wait_for_wpt_results(page, result_url, iteration)
|
|
81
|
+
361.times do
|
|
82
|
+
@response = HTTParty.get(result_url)
|
|
83
|
+
puts "#{JSON.parse(@response.body)['statusText']} for #{page}"
|
|
84
|
+
break if JSON.parse(@response.body)['statusCode'] == 200
|
|
85
|
+
sleep 10
|
|
86
|
+
end
|
|
87
|
+
@run_results[iteration][page][:speed_index] = (JSON.parse(@response.body)['data']['runs']['1']['firstView']['SpeedIndex'].to_f / 1000).round(2)
|
|
88
|
+
end
|
|
92
89
|
|
|
93
90
|
# Send a slack message with all the scores
|
|
94
|
-
def slack_notify(message)
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
end
|
|
100
|
-
|
|
101
|
-
def get_old_score(latest_score, page, score_key)
|
|
102
|
-
threshold = score_key == :rank ? 0 : @threshold
|
|
103
|
-
comparison_message = ''
|
|
104
|
-
if File.exist?(@history_file) && JSON.parse(File.read(@history_file)).keys.include?(page)
|
|
105
|
-
# We want the pagespeed score to be greater than before,
|
|
106
|
-
# but we want the speed index to be less than.
|
|
107
|
-
compare_operator = (score_key == :speed_index || score_key == :rank) ? :> : :<
|
|
108
|
-
# Open file that stores the history of the latest scores
|
|
109
|
-
file = File.open(@history_file, 'r')
|
|
110
|
-
# Find the value of the score of the page we want
|
|
111
|
-
old_score = JSON.parse(file.read)[page][score_key.to_s]
|
|
112
|
-
# Check if it's within the acceptable threshold, otherwise,
|
|
113
|
-
# check if it's greater than or less than (depending on what type of score it is)
|
|
114
|
-
# and add the relevant emoji
|
|
115
|
-
comparison_message = " (was #{old_score})"
|
|
116
|
-
if latest_score.to_f.between?(old_score.to_f - threshold, old_score.to_f + threshold)
|
|
117
|
-
comparison_message += " #{@minimal_change_emoji}"
|
|
118
|
-
elsif latest_score.to_f.send(compare_operator, old_score.to_f)
|
|
119
|
-
comparison_message += " #{@regression_emoji}"
|
|
120
|
-
else
|
|
121
|
-
comparison_message += " #{@improvement_emoji}"
|
|
91
|
+
def slack_notify(message)
|
|
92
|
+
HTTParty.post(@slack_post_url,
|
|
93
|
+
body: { 'channel': "##{@slack_channel}", 'icon_emoji': @slack_bot_emoji, 'username': @slack_username, 'text': message }.to_json,
|
|
94
|
+
headers: { 'Content-Type': 'application/json',
|
|
95
|
+
'Accept': 'application/json' })
|
|
122
96
|
end
|
|
123
|
-
end
|
|
124
|
-
comparison_message
|
|
125
|
-
end
|
|
126
97
|
|
|
127
|
-
def
|
|
128
|
-
|
|
98
|
+
def get_old_score(latest_score, page, score_key)
|
|
99
|
+
threshold = score_key == :rank ? 0 : @threshold
|
|
100
|
+
comparison_message = ''
|
|
101
|
+
if File.exist?(@history_file) && JSON.parse(File.read(@history_file)).keys.include?(page)
|
|
102
|
+
# We want the pagespeed score to be greater than before,
|
|
103
|
+
# but we want the speed index to be less than.
|
|
104
|
+
compare_operator = (score_key == :speed_index || score_key == :rank) ? :> : :<
|
|
105
|
+
# Open file that stores the history of the latest scores
|
|
106
|
+
file = File.open(@history_file, 'r')
|
|
107
|
+
# Find the value of the score of the page we want
|
|
108
|
+
old_score = JSON.parse(file.read)[page][score_key.to_s]
|
|
109
|
+
# Check if it's within the acceptable threshold, otherwise,
|
|
110
|
+
# check if it's greater than or less than (depending on what type of score it is)
|
|
111
|
+
# and add the relevant emoji
|
|
112
|
+
comparison_message = " (was #{old_score})"
|
|
113
|
+
if latest_score.to_f.between?(old_score.to_f - threshold, old_score.to_f + threshold)
|
|
114
|
+
comparison_message += " #{@minimal_change_emoji}"
|
|
115
|
+
elsif latest_score.to_f.send(compare_operator, old_score.to_f)
|
|
116
|
+
comparison_message += " #{@regression_emoji}"
|
|
117
|
+
else
|
|
118
|
+
comparison_message += " #{@improvement_emoji}"
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
comparison_message
|
|
122
|
+
end
|
|
129
123
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
124
|
+
def write_new_scores
|
|
125
|
+
file = File.open(@history_file, 'w+')
|
|
126
|
+
|
|
127
|
+
# Clear the file
|
|
128
|
+
file.truncate(0)
|
|
129
|
+
file.write(@results.to_json)
|
|
130
|
+
file.close
|
|
131
|
+
end
|
|
135
132
|
|
|
136
133
|
# ==========
|
|
137
134
|
# RUN SCRIPT
|
|
138
135
|
# ==========
|
|
139
136
|
|
|
140
137
|
# This kicks off a WebPageTest test for every page in the '@page_list' array
|
|
141
|
-
@page_list.each do |page|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
end
|
|
138
|
+
@page_list.each do |page|
|
|
139
|
+
@run_results.length.times do |iteration|
|
|
140
|
+
start_wpt_test(page, iteration)
|
|
141
|
+
# get_gpr(page, @results[page][:search_string], iteration)
|
|
142
|
+
end
|
|
143
|
+
end
|
|
147
144
|
|
|
148
145
|
# Waiting for WebPageTest results and storing them
|
|
149
|
-
@page_list.reverse_each do |page|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
146
|
+
@page_list.reverse_each do |page|
|
|
147
|
+
# This collates the results after all tests have finished
|
|
148
|
+
@run_results.length.times do |iteration|
|
|
149
|
+
wait_for_wpt_results(page, @run_results[iteration][page][:results_url], iteration)
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
# Average all the GPS scores
|
|
153
|
+
@run_results.length.times do |iteration|
|
|
154
|
+
get_gps_score(page, 'desktop', iteration)
|
|
155
|
+
get_gps_score(page, 'mobile', iteration)
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
# Reset the temporary results array
|
|
159
|
+
# @results[page][:rank] = []
|
|
160
|
+
@results[page][:speed_index] = []
|
|
161
|
+
@results[page][:desktop] = []
|
|
162
|
+
@results[page][:mobile] = []
|
|
163
|
+
|
|
164
|
+
# Add all results to an array of results for each numerical result type
|
|
165
|
+
@run_results.each do |result|
|
|
166
|
+
# @results[page][:rank].push(result[page][:rank])
|
|
167
|
+
@results[page][:speed_index].push(result[page][:speed_index])
|
|
168
|
+
@results[page][:desktop].push(result[page][:desktop])
|
|
169
|
+
@results[page][:mobile].push(result[page][:mobile])
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
# Calculate the mean speed, desktop and mobile scores, and the mode search ranking
|
|
173
|
+
# @results[page][:rank] = @results[page][:rank].max_by { |i| @results[page][:rank].count(i) }
|
|
174
|
+
@results[page][:desktop] = @results[page][:desktop].max_by { |i| @results[page][:desktop].count(i) }
|
|
175
|
+
@results[page][:mobile] = @results[page][:mobile].max_by { |i| @results[page][:mobile].count(i) }
|
|
176
|
+
@results[page][:speed_index] = (@results[page][:speed_index].inject(:+)/@run_results.length).round(2)
|
|
177
|
+
|
|
178
|
+
# Build the slack message
|
|
179
|
+
puts @results if ENV['logging'] == 'true'
|
|
180
|
+
@message += "\n*" + page + ':*'
|
|
181
|
+
@message += "\n desktop score: " + @results[page][:desktop].to_s
|
|
182
|
+
@message += get_old_score(@results[page][:desktop], page, :desktop)
|
|
183
|
+
@message += "\n mobile score: " + @results[page][:mobile].to_s
|
|
184
|
+
@message += get_old_score(@results[page][:mobile], page, :mobile)
|
|
185
|
+
@message += "\n SpeedIndex: " + @results[page][:speed_index].to_s
|
|
186
|
+
@message += get_old_score(@results[page][:speed_index].to_f, page, :speed_index) + "\n"
|
|
187
|
+
# @message += "\n Google Search Rank: " + @results[page][:rank].to_s
|
|
188
|
+
# @message += get_old_score(@results[page][:rank].to_f, page, :rank) + "\n"
|
|
189
|
+
end
|
|
154
190
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
191
|
+
# Add an '@here' to the slack notification if any score has regressed
|
|
192
|
+
@message += ' <!here> Something is worse than last time!' if @message.include?(@regression_emoji)
|
|
193
|
+
puts @message
|
|
194
|
+
slack_notify(@message)
|
|
195
|
+
# Create the scores history file if this is the first run
|
|
196
|
+
File.new(@history_file, 'w') unless File.exist?(@history_file)
|
|
197
|
+
write_new_scores
|
|
159
198
|
end
|
|
160
199
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
200
|
+
def configure
|
|
201
|
+
config_file = File.open('configuration.yml', 'w+')
|
|
202
|
+
config_file.write("""---
|
|
203
|
+
##############
|
|
204
|
+
## Required ##
|
|
205
|
+
##############
|
|
206
|
+
slack_url: 'https://hooks.slack.com/services/foo/bar/baz' # Set up an incoming webhook for your Slack account here https://get.slack.help/hc/en-us/articles/115005265063-Incoming-WebHooks-for-Slack#set-up-incoming-webhooks
|
|
207
|
+
pagespeed_api_key: 'Get an Google Search API key from https://developers.google.com/webmaster-tools/search-console-api/v1/configure'
|
|
208
|
+
webpagetest_api_key: 'Get a WebPageTest API key from https://www.webpagetest.org/getkey.php'
|
|
209
|
+
slack_channel: 'Select existing Slack channel to post to'
|
|
210
|
+
domain: 'https://www.google.com/' # Change this to the domain you want to test
|
|
211
|
+
page_list: # Change these to the pages you want to test on your domain
|
|
212
|
+
- 'drive/'
|
|
213
|
+
- 'calendar/'
|
|
214
|
+
|
|
215
|
+
#############
|
|
216
|
+
## Default ##
|
|
217
|
+
#############
|
|
218
|
+
slack_username: 'PageSpeed BOT' # Change this to any name you like
|
|
219
|
+
slack_bot_emoji: ':zap:'
|
|
220
|
+
improvement_emoji: ':racehorse:'
|
|
221
|
+
minimal_change_emoji: ':no_mouth:'
|
|
222
|
+
regression_emoji: ':no-entry:'
|
|
223
|
+
include_timestamp: true
|
|
224
|
+
threshold: '2'""")
|
|
173
225
|
end
|
|
174
|
-
|
|
175
|
-
# Calculate the mean speed, desktop and mobile scores, and the mode search ranking
|
|
176
|
-
# @results[page][:rank] = @results[page][:rank].max_by { |i| @results[page][:rank].count(i) }
|
|
177
|
-
@results[page][:desktop] = @results[page][:desktop].max_by { |i| @results[page][:desktop].count(i) }
|
|
178
|
-
@results[page][:mobile] = @results[page][:mobile].max_by { |i| @results[page][:mobile].count(i) }
|
|
179
|
-
@results[page][:speed_index] = (@results[page][:speed_index].inject(:+)/@run_results.length).round(2)
|
|
180
|
-
|
|
181
|
-
# Build the slack message
|
|
182
|
-
puts @results if ENV['logging'] == 'true'
|
|
183
|
-
@message += "\n*" + page + ':*'
|
|
184
|
-
@message += "\n desktop score: " + @results[page][:desktop].to_s
|
|
185
|
-
@message += get_old_score(@results[page][:desktop], page, :desktop)
|
|
186
|
-
@message += "\n mobile score: " + @results[page][:mobile].to_s
|
|
187
|
-
@message += get_old_score(@results[page][:mobile], page, :mobile)
|
|
188
|
-
@message += "\n SpeedIndex: " + @results[page][:speed_index].to_s
|
|
189
|
-
@message += get_old_score(@results[page][:speed_index].to_f, page, :speed_index) + "\n"
|
|
190
|
-
# @message += "\n Google Search Rank: " + @results[page][:rank].to_s
|
|
191
|
-
# @message += get_old_score(@results[page][:rank].to_f, page, :rank) + "\n"
|
|
192
|
-
end
|
|
193
|
-
|
|
194
|
-
# Add an '@here' to the slack notification if any score has regressed
|
|
195
|
-
@message += ' <!here> Something is worse than last time!' if @message.include?(@regression_emoji)
|
|
196
|
-
puts @message
|
|
197
|
-
slack_notify(@message)
|
|
198
|
-
# Create the scores history file if this is the first run
|
|
199
|
-
File.new(@history_file, 'w') unless File.exist?(@history_file)
|
|
200
|
-
write_new_scores
|
|
226
|
+
end
|