travis-surveillance 0.0.1

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.
@@ -0,0 +1,60 @@
1
+ module Travis
2
+ module Surveillance
3
+ class Project
4
+ attr_accessor :description, :id, :name, :owner, :slug, :status
5
+
6
+ def initialize(name)
7
+ @owner, @name = name.split('/')
8
+ @slug = name
9
+ populate
10
+ end
11
+
12
+ def add_build(json)
13
+ if build = build_for(json['id'])
14
+ return build
15
+ end
16
+
17
+ build = Build.new(json.merge({'project' => self}))
18
+ builds << build
19
+ build
20
+ end
21
+
22
+ def build_for(id)
23
+ builds.find { |b| b.id == id }
24
+ end
25
+
26
+ def building?
27
+ status.nil?
28
+ end
29
+
30
+ def builds
31
+ @builds ||= []
32
+ end
33
+
34
+ def failed?
35
+ !status.nil? && !passed?
36
+ end
37
+
38
+ def passed?
39
+ !status.nil? && status.zero?
40
+ end
41
+
42
+ private
43
+
44
+ def get_details
45
+ if Travis::Surveillance.mocking?
46
+ JSON.parse(IO.read(File.dirname(__FILE__) + "/../../../spec/support/projects/#{slug.gsub('/', '-')}.json"))
47
+ else
48
+ JSON.parse(open("http://travis-ci.org/#{slug}.json").read)
49
+ end
50
+ end
51
+
52
+ def populate
53
+ details = get_details
54
+ @description = details['description']
55
+ @id = details['id']
56
+ @status = details['last_build_status']
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,106 @@
1
+ require "json"
2
+ require "open-uri"
3
+
4
+ gem "pusher-client-merman"
5
+ require "pusher-client"
6
+ PusherClient.logger.level = Logger::INFO
7
+
8
+ module Travis
9
+ module Surveillance
10
+ class Surveyor
11
+ attr_accessor :project, :socket
12
+
13
+ def initialize(project, pusher_token = "23ed642e81512118260e")
14
+ @project = project
15
+ @socket = PusherClient::Socket.new(pusher_token)
16
+ end
17
+
18
+ def survey(&block)
19
+ @socket.subscribe('common')
20
+
21
+ @socket['common'].bind('build:started') do |payload|
22
+ payload_to_new_build(payload)
23
+ yield if block_given?
24
+ end
25
+ @socket['common'].bind('build:finished') do |payload|
26
+ payload_to_finished_build(payload)
27
+ yield if block_given?
28
+ end
29
+ @socket['common'].bind('job:started') do |payload|
30
+ payload_to_job_started(payload)
31
+ yield if block_given?
32
+ end
33
+ @socket['common'].bind('job:finished') do |payload|
34
+ payload_to_job_finished(payload)
35
+ yield if block_given?
36
+ end
37
+
38
+ @socket.connect unless Travis::Surveillance.mocking?
39
+ end
40
+
41
+ private
42
+
43
+ def add_missing_build(build)
44
+ Travis::Surveillance.log({ surveyor: true, build: true, missing: true, id: build['id'] })
45
+ @project.add_build(build)
46
+ end
47
+
48
+ def parse_and_check(payload)
49
+ json = JSON.parse(payload)
50
+ repository_id = json['repository'] ? json['repository']['id'] : json['repository_id']
51
+ repository_id == @project.id ? json : nil
52
+ end
53
+
54
+ def parse_and_check_and_build(payload)
55
+ return unless json = parse_and_check(payload)
56
+
57
+ json_build = json['build'] ? json['build'] : { 'id' => json['build_id'] }
58
+
59
+ unless build = @project.build_for(json_build['id'])
60
+ build = add_missing_build(json_build)
61
+ end
62
+
63
+ [json, build]
64
+ end
65
+
66
+ def payload_to_new_build(payload)
67
+ return unless json = parse_and_check(payload)
68
+
69
+ unless build = @project.build_for(json['build']['id'])
70
+ Travis::Surveillance.log({ surveyor: true, build: true, started: true, id: json['build']['id'] })
71
+ @project.add_build(json['build'])
72
+ end
73
+ end
74
+
75
+ def payload_to_finished_build(payload)
76
+ json, build = parse_and_check_and_build(payload)
77
+ return unless build
78
+
79
+ Travis::Surveillance.log({ surveyor: true, build: true, finished: true, id: build.id })
80
+ build.attributes = json['build']
81
+ @project.status = build.status
82
+ end
83
+
84
+ def payload_to_job_started(payload)
85
+ json, build = parse_and_check_and_build(payload)
86
+ return unless build
87
+
88
+ Travis::Surveillance.log({ surveyor: true, job: true, started: true, id: json['id'], build_id: build.id })
89
+ build.add_job(json)
90
+ end
91
+
92
+ def payload_to_job_finished(payload)
93
+ json, build = parse_and_check_and_build(payload)
94
+ return unless build
95
+
96
+ unless job = build.job_for(json['id'])
97
+ Travis::Surveillance.log({ surveyor: true, job: true, missing: true, id: json['id'], build_id: build.id })
98
+ job = build.add_job(json)
99
+ end
100
+
101
+ Travis::Surveillance.log({ surveyor: true, job: true, finished: true, id: json['id'], build_id: build.id })
102
+ job.attributes = json
103
+ end
104
+ end
105
+ end
106
+ end
@@ -0,0 +1,5 @@
1
+ module Travis
2
+ module Surveillance
3
+ VERSION = "0.0.1"
4
+ end
5
+ end
data/logs/.gitignore ADDED
@@ -0,0 +1 @@
1
+ *.log
data/spec/helper.rb ADDED
@@ -0,0 +1,40 @@
1
+ require "simplecov" unless ENV['NO_SIMPLECOV']
2
+ require 'minitest/autorun'
3
+
4
+ require "scrolls"
5
+ require "travis/surveillance"
6
+
7
+ Scrolls::Log.stream = File.open(File.dirname(__FILE__) + '/../logs/test.log', 'w')
8
+
9
+ module TestLogger
10
+ def self.log(data, &blk)
11
+ Scrolls.log(data, &blk)
12
+ end
13
+ end
14
+
15
+ Travis::Surveillance.instrument_with(TestLogger.method(:log))
16
+ Travis::Surveillance.mock!
17
+
18
+ # "".deindent from https://github.com/visionmedia/terminal-table/blob/master/spec/spec_helper.rb
19
+
20
+ class String
21
+ def deindent
22
+ strip.gsub(/^ */, '')
23
+ end
24
+ end
25
+
26
+ # PusherClient mock from https://github.com/pusher/pusher-ruby-client/blob/master/test/teststrap.rb
27
+
28
+ module PusherClient
29
+ class Socket
30
+ def simulate_received(event_name, event_data, channel_name)
31
+ send_local_event(event_name, event_data, channel_name)
32
+ end
33
+ end
34
+ end
35
+
36
+ PusherClient.logger.level = Logger::INFO
37
+
38
+ def pusher_json_for(slug, event)
39
+ JSON.parse(IO.read(File.dirname(__FILE__) + "/support/pusher/#{slug.gsub('/', '-')}-#{event.gsub(':', '-')}.json")).to_json
40
+ end
@@ -0,0 +1,16 @@
1
+ {
2
+ "id":1,
3
+ "number":"1",
4
+ "config":{
5
+ "language":"ruby"
6
+ },
7
+ "started_at":"2012-08-04T13:28:29Z",
8
+ "commit":"af0d1c46e019ff61f1faaba7003ebf912ab245d6",
9
+ "branch":"master",
10
+ "message":"Test",
11
+ "compare_url":"https://github.com/dylanegan/travis-surveillance/compare/74791a0faacf...af0d1c46e019",
12
+ "committed_at":"2012-08-04T13:28:22Z",
13
+ "author_name":"Dylan Egan",
14
+ "committer_name":"Dylan Egan",
15
+ "status":null
16
+ }
@@ -0,0 +1,10 @@
1
+ {
2
+ "id":1,
3
+ "number":"1.1",
4
+ "started_at":"2012-08-04T13:28:29Z",
5
+ "config": {
6
+ "env":"NO_SIMPLECOV=true",
7
+ "rvm":"1.9.3"
8
+ },
9
+ "result":null
10
+ }
@@ -0,0 +1,14 @@
1
+ {
2
+ "id":143690,
3
+ "slug":"dylanegan/travis-surveillance",
4
+ "description":"",
5
+ "public_key":"-----BEGIN RSA PUBLIC KEY-----\nMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCPeL3PD+uSXgaF4bvK4BMfCB3g\nple4P8PD+klPMQi3FTjXgyzPqsbiTaeKka0WNtmd+BXKIdczxrbjqNIAPurE3NeT\nM8aPbnkW0HNZ+oL1AsZveUyxjwMqN6iwrPbuLEKnueSpTcBOPBk3TY7Lec/HmlPV\n2PZM4LHOgmFA1P29pwIDAQAB\n-----END RSA PUBLIC KEY-----\n",
6
+ "last_build_id":2026814,
7
+ "last_build_number":"1",
8
+ "last_build_status":0,
9
+ "last_build_result":0,
10
+ "last_build_duration":113,
11
+ "last_build_language":null,
12
+ "last_build_started_at":"2012-08-03T09:13:51Z",
13
+ "last_build_finished_at":"2012-08-03T09:14:31Z"
14
+ }
@@ -0,0 +1,10 @@
1
+ {
2
+ "build":{
3
+ "id":1,
4
+ "finished_at":"2012-08-04T13:28:59Z",
5
+ "result":1
6
+ },
7
+ "repository":{
8
+ "id":143690
9
+ }
10
+ }
@@ -0,0 +1,13 @@
1
+ {
2
+ "build": {
3
+ "id":1,
4
+ "number":"1",
5
+ "result":null,
6
+ "matrix": [{
7
+ "number":"1.1"
8
+ }]
9
+ },
10
+ "repository": {
11
+ "id":143690
12
+ }
13
+ }
@@ -0,0 +1,7 @@
1
+ {
2
+ "id":1,
3
+ "build_id":1,
4
+ "finished_at":"2012-08-04T13:28:59Z",
5
+ "repository_id":143690,
6
+ "result":1
7
+ }
@@ -0,0 +1,5 @@
1
+ {
2
+ "id":1,
3
+ "build_id":1,
4
+ "repository_id":143690
5
+ }
@@ -0,0 +1,116 @@
1
+ require "helper"
2
+
3
+ describe Travis::Surveillance::Build do
4
+ before do
5
+ @project = Travis::Surveillance::Project.new("dylanegan/travis-surveillance")
6
+ @build = @project.add_build({'id' => 1})
7
+ end
8
+
9
+ describe "a new build" do
10
+ it "should have an author_name" do
11
+ @build.author_name.must_equal "Dylan Egan"
12
+ end
13
+
14
+ it "should have a branch" do
15
+ @build.branch.must_equal "master"
16
+ end
17
+
18
+ it "should have a commit" do
19
+ @build.commit.must_equal "af0d1c46e019ff61f1faaba7003ebf912ab245d6"
20
+ end
21
+
22
+ it "should have a committed_at" do
23
+ @build.committed_at.must_equal Time.parse("2012-08-04T13:28:22Z")
24
+ end
25
+
26
+ it "should have a committer_name" do
27
+ @build.committer_name.must_equal "Dylan Egan"
28
+ end
29
+
30
+ it "should have a compare_url" do
31
+ @build.compare_url.must_equal "https://github.com/dylanegan/travis-surveillance/compare/74791a0faacf...af0d1c46e019"
32
+ end
33
+
34
+ it "should have a configuration" do
35
+ @build.config.language.must_equal "ruby"
36
+ end
37
+
38
+ it "should have an id" do
39
+ @build.id.must_equal 1
40
+ end
41
+
42
+ it "should have a message" do
43
+ @build.message.must_equal "Test"
44
+ end
45
+
46
+ it "should have a number" do
47
+ @build.number.must_equal "1"
48
+ end
49
+
50
+ it "should have a project" do
51
+ @build.project.must_equal @project
52
+ end
53
+
54
+ it "should have a started_at" do
55
+ @build.started_at.must_equal Time.parse("2012-08-04T13:28:29Z")
56
+ end
57
+ end
58
+
59
+ describe "a finished build" do
60
+ before do
61
+ @surveyor = Travis::Surveillance::Surveyor.new(@project)
62
+ @surveyor.survey
63
+ @surveyor.socket.simulate_received('build:finished', pusher_json_for(@project.slug, 'build:finished'), 'common')
64
+ end
65
+
66
+ it "should have a duration" do
67
+ @build.duration.must_equal 30
68
+ end
69
+
70
+ it "should have a finished_at" do
71
+ @build.finished_at.must_equal Time.parse("2012-08-04T13:28:59Z")
72
+ end
73
+
74
+ it "should have a status" do
75
+ @build.status.must_equal 1
76
+ end
77
+ end
78
+
79
+ describe "status" do
80
+ describe "when nil" do
81
+ before do
82
+ @build.status = nil
83
+ end
84
+
85
+ it "should be building" do
86
+ @build.building?.must_equal true
87
+ @build.failed?.must_equal false
88
+ @build.passed?.must_equal false
89
+ end
90
+ end
91
+
92
+ describe "when zero" do
93
+ before do
94
+ @build.status = 0
95
+ end
96
+
97
+ it "should have passed" do
98
+ @build.building?.must_equal false
99
+ @build.failed?.must_equal false
100
+ @build.passed?.must_equal true
101
+ end
102
+ end
103
+
104
+ describe "when one" do
105
+ before do
106
+ @build.status = 1
107
+ end
108
+
109
+ it "should have failed" do
110
+ @build.building?.must_equal false
111
+ @build.failed?.must_equal true
112
+ @build.passed?.must_equal false
113
+ end
114
+ end
115
+ end
116
+ end
@@ -0,0 +1,89 @@
1
+ require "helper"
2
+
3
+ describe Travis::Surveillance::Job do
4
+ before do
5
+ @project = Travis::Surveillance::Project.new("dylanegan/travis-surveillance")
6
+ @build = @project.add_build({'id' => 1})
7
+ @job = @build.add_job({'id' => 1})
8
+ end
9
+
10
+ describe "a new job" do
11
+ it "should have a build" do
12
+ @job.build.must_equal @build
13
+ end
14
+
15
+ it "should have a config" do
16
+ @job.config.env.must_equal "NO_SIMPLECOV=true"
17
+ end
18
+
19
+ it "should have an id" do
20
+ @job.id.must_equal 1
21
+ end
22
+
23
+ it "should have a number" do
24
+ @job.number.must_equal "1.1"
25
+ end
26
+
27
+ it "should have a started_at" do
28
+ @job.started_at.must_equal Time.parse("2012-08-04T13:28:29Z")
29
+ end
30
+ end
31
+
32
+ describe "a finished job" do
33
+ before do
34
+ @surveyor = Travis::Surveillance::Surveyor.new(@project)
35
+ @surveyor.survey
36
+ @surveyor.socket.simulate_received('job:finished', pusher_json_for(@project.slug, 'job:finished'), 'common')
37
+ end
38
+
39
+ it "should have a duration" do
40
+ @job.duration.must_equal 30
41
+ end
42
+
43
+ it "should have a finished_at" do
44
+ @job.finished_at.must_equal Time.parse("2012-08-04T13:28:59Z")
45
+ end
46
+
47
+ it "should have a status" do
48
+ @job.status.must_equal 1
49
+ end
50
+ end
51
+
52
+ describe "status" do
53
+ describe "when nil" do
54
+ before do
55
+ @job.status = nil
56
+ end
57
+
58
+ it "should be running" do
59
+ @job.running?.must_equal true
60
+ @job.failed?.must_equal false
61
+ @job.passed?.must_equal false
62
+ end
63
+ end
64
+
65
+ describe "when zero" do
66
+ before do
67
+ @job.status = 0
68
+ end
69
+
70
+ it "should have passed" do
71
+ @job.running?.must_equal false
72
+ @job.failed?.must_equal false
73
+ @job.passed?.must_equal true
74
+ end
75
+ end
76
+
77
+ describe "when one" do
78
+ before do
79
+ @job.status = 1
80
+ end
81
+
82
+ it "should have failed" do
83
+ @job.running?.must_equal false
84
+ @job.failed?.must_equal true
85
+ @job.passed?.must_equal false
86
+ end
87
+ end
88
+ end
89
+ end