Skip to content

Commit d53a695

Browse files
author
Steven Richardson
committed
Merge pull request #4 from richdynamix/feature/ga-custom-dimensions
Feature/ga custom dimensions
2 parents b14dcfc + 91ac1d6 commit d53a695

File tree

7 files changed

+339
-151
lines changed

7 files changed

+339
-151
lines changed

README.md

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@
1313
- Auto configure start URL to reuse tests across multiple stages
1414
- Send deployment information to Google Analytics
1515
- Send errors to Google Analytics on failed tests
16+
- Send successful test runs to Google Analytics
17+
- Use Custom Dimensions in Google Analytics
18+
- Send test names as Custom Dimension
19+
- Track Jira tickets as Custom Dimension
1620

1721
## Installation
1822

@@ -44,14 +48,17 @@ First thing you need to do is create your `YAML` file (`gi_config.yaml`) in the
4448
APIKEY: XXXXXXXXXXXXXXXXXXX
4549
gi_enabled: true
4650
rollback: true
47-
ga_property: ""
4851
suites:
4952
aboutpage: "XXXXXXXXXXXXXXXXXXX"
5053
suite2: ""
5154
tests:
5255
homepage: "XXXXXXXXXXXXXXXXXXX"
5356
test2: ""
5457
test3: ""
58+
ga_property: "UA-XXXXXXXX-X"
59+
ga_custom_1: 1
60+
ga_custom_2: 2
61+
jira_project_code: "GHOST"
5562
```
5663

5764
You can obtain your API key, suite ID and test ID from your Ghost Inspector console. At the bottom right of the suite page you will see API Access e.g.
@@ -70,7 +77,14 @@ By default the `rollback` feature is enabled, you can disabled this for all stag
7077
set :rollback, false
7178
```
7279

73-
The Google Analytics property must be inserted into the `ga_property` in order to log deployments and errors. Simply update your YAML to include this `ga_property: "UA-XXXXXXXX-1"`. To disable the Google Analytics tracking just leave the `ga_property` as empty string i.e. `ga_property: ""` in your YAML
80+
The Google Analytics property must be inserted into the `ga_property` in order to log deployments and errors. Simply update your YAML to include this `ga_property: "UA-XXXXXXXX-1"`. To disable the Google Analytics tracking just leave the `ga_property` as empty string i.e. `ga_property: ""` in your YAML.
81+
82+
Since version `0.3.0`, Google Analytics now uses Custom Dimensions as outlined in the [Google Measurement Protocol](https://developers.google.com/analytics/devguides/collection/protocol/v1/parameters?hl=en#cd_ "Google Measurement Protocol") documentation. When you define a new custom dimension in Google Analytics you are given a new dimension index. Default accounts have 20 available indexes where as premium accounts have 200. The `ga_custom_1` property is used to define the custom dimension for the testname and `ga_custom_2` is used to define the Jira tickets*. If you do not set the `ga_custom_1` or `ga_custom_2` properties then the default index of `1` & `2` will be used.
83+
84+
\*_Jira tickets are extracted from the git log during the deployment. For this reason it can only track the tickets where you have correctly assigned the ticket number and identifier to the commit message. i.e._
85+
```
86+
git commit -am "GHOST-123 Add new item to the gem"
87+
```
7488

7589
## Usage
7690

lib/capistrano/ghostinspector.rb

Lines changed: 142 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,66 +1,173 @@
1+
require "capistrano"
12
require "capistrano/ghostinspector/version"
23
require "capistrano/ghostinspector/arrays"
34
require "capistrano/ghostinspector/api"
4-
require "capistrano"
5+
require "capistrano/ghostinspector/analytics"
56

67
module Capistrano
78
module Ghostinspector
89
def self.load_into(config)
910
config.load do
10-
after "deploy", "capistrano:ghostinspector:run"
11+
after "deploy", "ghostinspector:setup"
12+
after "ghostinspector:setup", "ghostinspector:run"
1113

12-
namespace :capistrano do
13-
namespace :ghostinspector do
14-
task :run, :only => { :primary => true } do
14+
gi_config = YAML::load(File.read("gi_config.yaml"))
1515

16-
set :giconfig, YAML::load(File.read("gi_config.yaml"))
16+
namespace :ghostinspector do
17+
desc "Setup Ghost Inspector Config"
18+
task :setup, :only => { :primary => true } do
1719

18-
# Ghost Inspector API key
19-
set :gi_api_key, giconfig["APIKEY"]
20+
# Ghost Inspector API key
21+
set :gi_api_key, gi_config["APIKEY"]
2022

21-
# Google Analytics Tracking Property
22-
set :ga_property, giconfig["ga_property"]
23+
# Google Analytics Tracking Property
24+
set :ga_property, gi_config['ga_property']
2325

24-
# Get tests and suites from command line
25-
set :gitest, fetch(:gitest, nil)
26-
set :gisuite, fetch(:gisuite, nil)
26+
if gi_config.has_key?("ga_custom_1")
27+
set :ga_custom_1, gi_config["ga_custom_1"]
28+
else
29+
set :ga_custom_1, "1"
30+
end
2731

28-
# Check if GI is enabled for this deployment (Default: true)
29-
set :gi_enabled, fetch(:gi_enabled, giconfig["gi_enabled"])
32+
if gi_config.has_key?("ga_custom_2")
33+
set :ga_custom_2, gi_config["ga_custom_2"]
34+
else
35+
set :ga_custom_2, "2"
36+
end
3037

31-
# Should we rollback on failed GI tests (Default: true)
32-
set :rollback, fetch(:rollback, giconfig["rollback"])
38+
if gi_config.has_key?("jira_project_code")
39+
set :jira_project_code, gi_config["jira_project_code"]
40+
else
41+
set :jira_project_code, "GHOST"
42+
end
3343

34-
if (gi_enabled == true)
44+
# Get tests and suites from command line
45+
set :gitest, fetch(:gitest, nil)
46+
set :gisuite, fetch(:gisuite, nil)
3547

36-
# run each test
37-
Capistrano::Ghostinspector.getTests(gitest, giconfig["tests"]).each do |test|
38-
puts "* * * Running Ghost Inspector Test * * *"
39-
set :passing, Capistrano::Ghostinspector::Api.executeApi("tests", test, gi_api_key, domain, rollback, ga_property, current_revision[0,7])
40-
end
48+
# Check if GI is enabled for this deployment (Default: true)
49+
set :gi_enabled, fetch(:gi_enabled, gi_config['gi_enabled'])
4150

42-
# run each suite
43-
Capistrano::Ghostinspector.getTests(gisuite, giconfig["suites"]).each do |suite|
44-
puts "* * * Running Ghost Inspector Suite * * *"
45-
set :passing, Capistrano::Ghostinspector::Api.executeApi("suites", suite, gi_api_key, domain, rollback, ga_property, current_revision[0,7])
46-
end
51+
# Should we rollback on failed GI tests (Default: true)
52+
set :rollback, fetch(:rollback, gi_config['rollback'])
53+
end
54+
55+
desc "Run Ghost Inspector Tests"
56+
task :run, :only => { :primary => true } do
57+
58+
if (fetch(:gi_enabled) == true)
59+
60+
giApi = Api.new(fetch(:gi_api_key), fetch(:domain), fetch(:rollback), fetch(:ga_property))
61+
62+
@collection = Array.new
63+
# run each test
64+
Capistrano::Ghostinspector.getTests(fetch(:gitest), gi_config["tests"]).each do |test|
65+
puts "* * * Running Ghost Inspector Test * * *"
66+
set :data, giApi.executeApi("tests", test)
67+
68+
items = { :passing => data[0], :results => data[1], :type => "tests"}
69+
@collection << items
70+
end
4771

48-
# If any test fails and the stage allows rollbacks then
49-
# rollback to previous version.
50-
if (passing == false && rollback == true)
51-
puts "* * * Ghost Inspector Failed. Rolling back * * *"
52-
run_locally %{cap #{stage} deploy:rollback}
53-
else
54-
puts "* * * Ghost Inspector Complete. Deployment Complete * * *"
72+
# run each suite
73+
Capistrano::Ghostinspector.getTests(fetch(:gisuite), gi_config["suites"]).each do |suite|
74+
puts "* * * Running Ghost Inspector Suite * * *"
75+
set :data, giApi.executeApi("suites", suite)
76+
77+
data[1]["data"].each do |test|
78+
items = { :passing => test["passing"], :results => test, :type => "suites"}
79+
@collection << items
5580
end
5681

5782
end
83+
84+
end
85+
86+
end
87+
88+
desc "Send Results to Google Analytics"
89+
task :sendGA, :only => { :primary => true } do
90+
91+
puts "* * * Sending Data to Google Analytics * * *"
92+
93+
jira_project_code = fetch(:jira_project_code)
94+
95+
log = capture(
96+
"cd #{current_path} && git log #{previous_revision[0,7]}..#{current_revision[0,7]} --format=\"%s\" | grep -oh '#{jira_project_code}-[0-9]\\+' | sort | uniq"
97+
)
98+
99+
options = {
100+
:ga_property => fetch(:ga_property),
101+
:ga_custom_1 => fetch(:ga_custom_1),
102+
:ga_custom_2 => fetch(:ga_custom_2),
103+
:domain => fetch(:domain),
104+
:current_revision => fetch(:current_revision),
105+
:previous_revision => fetch(:previous_revision),
106+
:branch => fetch(:branch, "default"),
107+
:stage => fetch(:stage),
108+
:tickets => Capistrano::Ghostinspector.getTickets(log)
109+
}
110+
111+
analytics = Analytics.new(options)
112+
113+
@collection.each do |item|
114+
analytics.pushData(item[:type], item[:results])
115+
end
116+
117+
end
118+
119+
desc "Finalise Ghost Inspector Run"
120+
task :finalise_run, :only => { :primary => true } do
121+
122+
set :passing, true
123+
@collection.each do |item|
124+
if item[:passing] == false
125+
set :passing, false
126+
end
58127
end
128+
129+
# If any test fails and the stage allows rollbacks then
130+
# rollback to previous version.
131+
if (fetch(:passing) == false && fetch(:rollback) == true)
132+
puts "* * * Ghost Inspector Failed. Rolling back * * *"
133+
run_locally %{cap #{stage} deploy:rollback}
134+
else
135+
puts "* * * Ghost Inspector Complete. Deployment Complete * * *"
136+
end
137+
59138
end
139+
60140
end
61141

142+
143+
after "ghostinspector:run", "ghostinspector:sendGA"
144+
after "ghostinspector:sendGA", "ghostinspector:finalise_run"
145+
62146
end
63147
end
148+
149+
150+
def self.getTickets(log)
151+
152+
tickets = ""
153+
log.each_line do |line|
154+
line.delete!('";')
155+
line.strip!
156+
line.gsub!("'", '\u0027')
157+
tickets = "#{tickets}, #{line}"
158+
end
159+
160+
if (tickets.to_s == "")
161+
tickets = "None"
162+
else
163+
tickets[0] = ''
164+
end
165+
166+
return tickets
167+
168+
end
169+
170+
64171
end
65172
end
66173

Lines changed: 80 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,95 @@
1-
require "capistrano/ghostinspector/analytics"
21
require "staccato"
32

43
module Capistrano
54
module Ghostinspector
6-
module Analytics
7-
def self.pushDeployment(ga_property, current_revision)
5+
class Analytics
6+
def initialize(options)
7+
@options = options
8+
@tracker = Staccato.tracker(options[:ga_property])
9+
end
810

9-
tracker = Staccato.tracker(ga_property)
11+
def pushData(type, results)
1012

11-
# inform GA of a new deployment
12-
tracker.event(category: 'deployment', action: 'deploy', label: current_revision, non_interactive: true)
13+
# Lets push the deployment in GA if the configuration allows it.
14+
pushDeployment()
1315

14-
end
16+
if type == "tests"
17+
testname = "GI TEST - " + results["data"]["test"]["name"]
1518

16-
def self.pushErrors(ga_property, current_revision, data)
19+
if results["data"]["passing"] == true
20+
trackData(results["data"]["steps"], testname, "success")
21+
else
22+
trackData(results["data"]["steps"], testname, "error")
23+
end
1724

18-
tracker = Staccato.tracker(ga_property)
25+
else
1926

20-
data['steps'].each do |step|
27+
testname = "GI TEST - " + results["testName"]
2128

22-
if (step['passing'] == false)
23-
# send the errors to GA
24-
tracker.event(category: 'error', action: step['error'], label: "Command: #{step['command']} - Target: #{step['target']}", non_interactive: true)
25-
end
29+
if results["passing"] == true
30+
trackData(results["steps"], testname, "success")
31+
else
32+
trackData(results["steps"], testname, "error")
33+
end
2634

27-
end
35+
end
2836

29-
end
37+
end
3038

31-
end
39+
private
40+
41+
def pushDeployment()
42+
43+
# inform GA of a new deployment
44+
@action = "deploy to #{@options[:stage]}"
45+
current_revision = @options[:current_revision][0,7]
46+
previous_revision = @options[:previous_revision][0,7]
47+
@deployed = "Deployed revision #{current_revision} from branch #{@options[:branch]} (replacing #{previous_revision})"
48+
hit = Staccato::Event.new(@tracker, category: 'deployment', action: @action, label: @deployed, document_hostname: @options[:domain], document_path: @action)
49+
hit.add_custom_dimension(@options[:ga_custom_1], "deployment")
50+
hit.add_custom_dimension(@options[:ga_custom_2], "#{@options[:tickets]}")
51+
hit.track!
52+
53+
end
54+
55+
def trackData(steps, testName, type)
56+
57+
if type == 'success'
58+
steps.each do |step|
59+
60+
hit = Staccato::Event.new(@tracker, category: 'success', action: step['command'], label: step['target'], document_hostname: @options[:domain], document_path: testName)
61+
hit.add_custom_dimension(@options[:ga_custom_1], testName)
62+
hit.add_custom_dimension(@options[:ga_custom_2], "#{@options[:tickets]}")
63+
hit.track!
64+
65+
end
66+
# pageView(testName)
67+
else
68+
steps.each do |step|
69+
70+
if (step['passing'] == false)
71+
# send the errors to GA
72+
73+
hit = Staccato::Event.new(@tracker, category: 'error', action: step['error'], label: "Command: #{step['command']} - Target: #{step['target']}", document_hostname: @options[:domain], document_path: testName)
74+
hit.add_custom_dimension(@options[:ga_custom_1], testName)
75+
hit.add_custom_dimension(@options[:ga_custom_2], "#{@options[:tickets]}")
76+
hit.track!
77+
end
78+
79+
end
80+
end
81+
82+
end
83+
84+
def pageView(testName)
85+
86+
hit = Staccato::Pageview.new(@tracker, hostname: @options[:domain], path: testName, title: testName, document_hostname: @options[:domain])
87+
hit.add_custom_dimension(@options[:ga_custom_1], testName)
88+
hit.add_custom_dimension(@options[:ga_custom_2], "#{@options[:tickets]}")
89+
hit.track!
90+
91+
end
92+
93+
end
3294
end
33-
end
95+
end

0 commit comments

Comments
 (0)