dash-mario 0.15
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.
- data/CHANGELOG +93 -0
- data/Gemfile +16 -0
- data/MIT-LICENSE +21 -0
- data/README.rdoc +100 -0
- data/Rakefile +34 -0
- data/dash-mario.gemspec +22 -0
- data/lib/dash-fu/mario.rb +154 -0
- data/lib/dash-fu/marios/backtweets.rb +57 -0
- data/lib/dash-fu/marios/backtweets.yml +9 -0
- data/lib/dash-fu/marios/github.rb +110 -0
- data/lib/dash-fu/marios/github.yml +15 -0
- data/lib/dash-fu/marios/github_issues.rb +91 -0
- data/lib/dash-fu/marios/github_issues.yml +14 -0
- data/lib/dash-fu/marios/ruby_gems.rb +55 -0
- data/lib/dash-fu/marios/ruby_gems.yml +6 -0
- data/test/api_keys.yml +1 -0
- data/test/backtweets_test.rb +151 -0
- data/test/cassettes/backtweets.yml +63 -0
- data/test/cassettes/github.yml +126 -0
- data/test/cassettes/github_issues.yml +123 -0
- data/test/cassettes/ruby_gems.yml +36 -0
- data/test/github_issues_test.rb +194 -0
- data/test/github_test.rb +251 -0
- data/test/helpers/activity.rb +21 -0
- data/test/helpers/metric.rb +22 -0
- data/test/helpers/person.rb +25 -0
- data/test/helpers/test.rb +161 -0
- data/test/ruby_gems_test.rb +164 -0
- data/test/setup.rb +31 -0
- data/test/test.log +852 -0
- metadata +164 -0
data/CHANGELOG
ADDED
@@ -0,0 +1,93 @@
|
|
1
|
+
2010-09-07 v0.15 Renamed to DashFu::Mario
|
2
|
+
|
3
|
+
2010-09-07 v0.14 RubyGems and Github identities
|
4
|
+
|
5
|
+
RubyGems releases now identify RubyGems as the source of the activity.
|
6
|
+
|
7
|
+
Github source includes github login name as identity.
|
8
|
+
|
9
|
+
2010-08-31 v0.13 Github data source merges related commits
|
10
|
+
|
11
|
+
Now it does.
|
12
|
+
|
13
|
+
2010-08-31 v0.12 Github data source merges related commits
|
14
|
+
|
15
|
+
Github data source merges related commits (same committer/time) into single
|
16
|
+
activity and shows first line of all commit messages.
|
17
|
+
|
18
|
+
Changed to coding/testing with Ruby 1.9.2, since this is the target
|
19
|
+
environment.
|
20
|
+
|
21
|
+
2010-08-30 v0.11 Changes to activity person, AS 3.0 support
|
22
|
+
|
23
|
+
Activity's person name is now fullname, photo is photo_url and url is no
|
24
|
+
longer, but we do accept multiple identities of the form domain:id, e.g
|
25
|
+
twitter.com:assaf, linkedin.com:assafarkin.
|
26
|
+
|
27
|
+
Test suite now allows validating metric, activity and person. Call the validate
|
28
|
+
method to run validation and raise exception on error (with a helpful error
|
29
|
+
message). Call valid? if you're only interested in true/false.
|
30
|
+
|
31
|
+
Gem dependencies removed to allow running with ActiveSupport 3.0.
|
32
|
+
|
33
|
+
2010-08-26 v0.10 Tags and better messages
|
34
|
+
|
35
|
+
Activities can now include tags.
|
36
|
+
|
37
|
+
Improvement all around to all the HTML messages.
|
38
|
+
|
39
|
+
2010-08-25 v0.9 Better Github commit message
|
40
|
+
|
41
|
+
2010-08-24 v0.8 Minor API change
|
42
|
+
|
43
|
+
Attribute :id is now :uid.
|
44
|
+
|
45
|
+
Activity content can be set using either :html or :text attribute.
|
46
|
+
2010-08-24 v0.7 Added test suite and resources
|
47
|
+
|
48
|
+
Each source can have an associated resources file (YAML), e.g. ruby_gems.rb
|
49
|
+
would have ruby_gems.yml. The default implementation of methods like name,
|
50
|
+
description and display pull content from the resource. Resources can support
|
51
|
+
multiple languages, but we're starting with just EN.
|
52
|
+
|
53
|
+
Some sources also need API keys. These are accessed using the method api_key
|
54
|
+
that returns the API key value for the current source (often a string, but can
|
55
|
+
also be hash or array). There's an api_keys.yml file which contains fake API
|
56
|
+
keys. You can put a real key in there while generating a cassette for your test
|
57
|
+
case.
|
58
|
+
|
59
|
+
Test suite is here, using WebMock and VCR to rest API calls. Cassettes go in
|
60
|
+
test/cassettes, fixtures in test/fixtures.
|
61
|
+
|
62
|
+
2010-08-19 v0.6 Added Backtweet
|
63
|
+
|
64
|
+
2010-08-19 v0.5 Added Github and Github issues
|
65
|
+
|
66
|
+
2010-08-18 v0.4 Metrics that set and increment
|
67
|
+
|
68
|
+
Revised setup method to change special values metric.name and metric.columns
|
69
|
+
(was name and column).
|
70
|
+
|
71
|
+
There are two types of metrics, those that collect totals and those that
|
72
|
+
collect daily/hourly values. The setup method indicates that by setting the
|
73
|
+
value metric.total (defaults to false).
|
74
|
+
|
75
|
+
Revised update method to allow either setting current value (:set) or
|
76
|
+
incrementing current value (:inc).
|
77
|
+
|
78
|
+
2010-08-11 v0.3 Always be sending changes
|
79
|
+
|
80
|
+
Changed: Collector update methods accepts inc and timestamp arguments (but set
|
81
|
+
is gone).
|
82
|
+
|
83
|
+
Fixed: Rubygems source captures most recent downloads count as meta-data,
|
84
|
+
updates collector with change since last update.
|
85
|
+
|
86
|
+
Fixed: Rubygems source can handle whatever name you throw at it and properly
|
87
|
+
escapes it.
|
88
|
+
|
89
|
+
2010-08-10 v0.2 Working Rubygems source
|
90
|
+
|
91
|
+
Fixed: Rubygems source not updating meta data like authors, project info, URL.
|
92
|
+
|
93
|
+
2010-08-09 v0.1 First release
|
data/Gemfile
ADDED
data/MIT-LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
Copyright (c) 2010 Assaf Arkin
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
21
|
+
|
data/README.rdoc
ADDED
@@ -0,0 +1,100 @@
|
|
1
|
+
{Dash-fu}[http://dash-fu.com] sources need to get their data somehow: enter
|
2
|
+
Marios. Marios are the brave workers that go out and collect data from vaious
|
3
|
+
data sources and report them back in the form of activities and metrics.
|
4
|
+
|
5
|
+
|
6
|
+
== Setup
|
7
|
+
|
8
|
+
A Mario is setup in four steps. First, the display method returns an HTML form
|
9
|
+
which will be displayed to the user. In fact, this method returns two values:
|
10
|
+
|
11
|
+
* inputs -- HTML input controls for setting up a new controller.
|
12
|
+
* notes -- Additional setup notes, e.g. other steps that need to be
|
13
|
+
followed, what values to supply, etc.
|
14
|
+
|
15
|
+
Wrap input controls within the label and use the source[..param..] notation for
|
16
|
+
the name attribute. For example, for Twitter:
|
17
|
+
|
18
|
+
<label>Screen name <input type="text" name="source[screen_name]" size="30"></label>
|
19
|
+
|
20
|
+
When the form is filled, the setup method is called with a context and values
|
21
|
+
from the form fields. Since the Mario needs to store state information, it uses
|
22
|
+
the context for that. The context is a Hash that can store basic Ruby values
|
23
|
+
(nil, String, boolean, Numeric, Array and Hash).
|
24
|
+
|
25
|
+
Some sources collect metrics. These sources must set three specific values
|
26
|
+
(during setup):
|
27
|
+
|
28
|
+
* metric.name -- The name of the metric, e.g. Twitter source might use the
|
29
|
+
name "Twitter mentions of @dash_fu".
|
30
|
+
* metric.columns -- Specifies the columns (at least one) that make up this
|
31
|
+
metric. The value if an array where each item describes a single column, see
|
32
|
+
below for more details.
|
33
|
+
* metric.totals -- True if this metric collects totals (life-time values,
|
34
|
+
e.g. downloads, user accounts), false if it only collects daily values (e.g.
|
35
|
+
average response time, number of instances in cluster).
|
36
|
+
|
37
|
+
For metric.columns, each item can use the following keys:
|
38
|
+
|
39
|
+
* id -- Column identifier (if missing, derived from column name)
|
40
|
+
* name -- Column name (required)
|
41
|
+
|
42
|
+
Shortly after setup, the validate method is called with the same context. If it
|
43
|
+
raises any exception, the error is displayed to the user and the source is
|
44
|
+
discarded. Otherwise, register is called with a Webhook URL. Some Marios use
|
45
|
+
that to register the Webhook with another service.
|
46
|
+
|
47
|
+
|
48
|
+
== Updates
|
49
|
+
|
50
|
+
Periodically, the Mario will be asked to update the source by calling the update
|
51
|
+
method. This method is called with the same context and a block. If data comes
|
52
|
+
from a webhook, then the second argument to update is a Rack::Request object.
|
53
|
+
|
54
|
+
The block passed to update can be used to update the source by yielding to it
|
55
|
+
with a hash of named arguments. A single update may yield any number of times
|
56
|
+
with any combination of arguments.
|
57
|
+
|
58
|
+
The named arguments are:
|
59
|
+
|
60
|
+
* set -- Columns to set (metric). Records the most recent value for this
|
61
|
+
metric. This is a hash where the keys are column ids (or indexes), the values
|
62
|
+
are integers or floats.
|
63
|
+
* inc -- Columns to increment (metric). Records a change in value which may
|
64
|
+
be positive or negative. This is a hash where the keys are column ids (or
|
65
|
+
indexes), the values are integers or floats.
|
66
|
+
* timestamp -- The Time (if missing, uses the current system time).
|
67
|
+
* activity -- Activity to show in the stream. See below.
|
68
|
+
|
69
|
+
Activity can specify the following attributes:
|
70
|
+
|
71
|
+
* uid -- Unique identifier (within the scope of this source). For example,
|
72
|
+
if activity is a release, this could be the version number.
|
73
|
+
* html -- HTML contents of the activity.
|
74
|
+
* text -- Text contents of the activity (can be used instead of html).
|
75
|
+
* url -- URL for original resource (e.g. blog post, tweet).
|
76
|
+
* tags -- Any number of tags for filtering activities like this (e.g.
|
77
|
+
twitter, mention). Tags are lowercased and can contain alphanumeric, dashes
|
78
|
+
and underscore.
|
79
|
+
* person -- Person who performed this activity. A hash with the (all
|
80
|
+
optional) values :name, :email, :url and :photo.
|
81
|
+
* timestamp -- Timestamp activity occurred.
|
82
|
+
|
83
|
+
HTML can contain links (HTTP/S and email), images, bold, italics, paragraphs,
|
84
|
+
block quotes, lists, tables, pre-formatted text, video and a few other elements.
|
85
|
+
Scripts, objects, styles are obviously not allowed.
|
86
|
+
|
87
|
+
Occasionally, the meta method is called. This method is used to display
|
88
|
+
meta-data from the most recent state (i.e. last update). It returns an array of
|
89
|
+
fields, each being a hash with the following values:
|
90
|
+
|
91
|
+
* title -- Title for this field (not required)
|
92
|
+
* text -- Text to show as value of the field
|
93
|
+
* url -- Link (not required)
|
94
|
+
|
95
|
+
|
96
|
+
== Teardown
|
97
|
+
|
98
|
+
Eventually the source is destroyed and the Webhook is unregistered by
|
99
|
+
calling unregister.
|
100
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
require "rake/testtask"
|
2
|
+
|
3
|
+
# -- Building stuff --
|
4
|
+
|
5
|
+
spec = Gem::Specification.load(Dir["*.gemspec"].first)
|
6
|
+
|
7
|
+
desc "Build the Gem"
|
8
|
+
task :build do
|
9
|
+
sh "gem build #{spec.name}.gemspec"
|
10
|
+
end
|
11
|
+
|
12
|
+
desc "Install #{spec.name} locally"
|
13
|
+
task :install=>:build do
|
14
|
+
sudo = "sudo" unless File.writable?( Gem::ConfigMap[:bindir])
|
15
|
+
sh "#{sudo} gem install #{spec.name}-#{spec.version}.gem"
|
16
|
+
end
|
17
|
+
|
18
|
+
desc "Push new release to gemcutter and git tag"
|
19
|
+
task :push=>["test", "build"] do
|
20
|
+
sh "git push"
|
21
|
+
puts "Tagging version #{spec.version} .."
|
22
|
+
sh "git tag v#{spec.version}"
|
23
|
+
sh "git push --tag"
|
24
|
+
puts "Building and pushing gem .."
|
25
|
+
sh "gem push #{spec.name}-#{spec.version}.gem"
|
26
|
+
end
|
27
|
+
|
28
|
+
|
29
|
+
task :default=>:test
|
30
|
+
Rake::TestTask.new do |task|
|
31
|
+
task.test_files = FileList['test/**/*_test.rb']
|
32
|
+
#task.warning = true
|
33
|
+
task.verbose = true
|
34
|
+
end
|
data/dash-mario.gemspec
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Gem::Specification.new do |spec|
|
2
|
+
spec.name = "dash-mario"
|
3
|
+
spec.version = "0.15"
|
4
|
+
spec.author = "Assaf Arkin"
|
5
|
+
spec.email = "assaf@labnotes.org"
|
6
|
+
spec.homepage = "http://dash-fu.com"
|
7
|
+
spec.summary = "Hopping around collecting data, keeping your dashes dashing"
|
8
|
+
|
9
|
+
spec.files = Dir["{bin,lib,test}/**/*", "CHANGELOG", "MIT-LICENSE", "README.rdoc", "Rakefile", "Gemfile", "*.gemspec"]
|
10
|
+
|
11
|
+
spec.has_rdoc = true
|
12
|
+
spec.extra_rdoc_files = "README.rdoc", "CHANGELOG"
|
13
|
+
spec.rdoc_options = "--title", "DashFu::Mario #{spec.version}", "--main", "README.rdoc",
|
14
|
+
"--webcvs", "http://github.com/assaf/#{spec.name}"
|
15
|
+
|
16
|
+
spec.required_ruby_version = '>= 1.8.7'
|
17
|
+
spec.add_dependency "activesupport"
|
18
|
+
spec.add_dependency "json"
|
19
|
+
spec.add_dependency "nokogiri"
|
20
|
+
spec.add_dependency "rack"
|
21
|
+
spec.add_dependency "i18n"
|
22
|
+
end
|
@@ -0,0 +1,154 @@
|
|
1
|
+
require "active_support"
|
2
|
+
require "json"
|
3
|
+
require "net/http"
|
4
|
+
require "rack"
|
5
|
+
require "uri"
|
6
|
+
|
7
|
+
# See http://dash-fu.com
|
8
|
+
module DashFu
|
9
|
+
|
10
|
+
# The README covers it all.
|
11
|
+
module Mario
|
12
|
+
|
13
|
+
class << self
|
14
|
+
attr_accessor :logger
|
15
|
+
|
16
|
+
# Returns all available marios.
|
17
|
+
def all
|
18
|
+
@marios ||= {}
|
19
|
+
end
|
20
|
+
|
21
|
+
# Returns Mario by its identifier.
|
22
|
+
def find(id)
|
23
|
+
all[id]
|
24
|
+
end
|
25
|
+
|
26
|
+
# Loads all the Marios from the given directory. The Mario identifier is
|
27
|
+
# derived from the filename (e.g. all/my_hero.rb becomes "my_hero"). The
|
28
|
+
# Mario class must map to the source identifier within the Mario module,
|
29
|
+
# e.g. DashFu::Mario::MyHero).
|
30
|
+
def load_marios(path = File.dirname(__FILE__) + "/marios")
|
31
|
+
Dir["#{path}/*.rb"].each do |file|
|
32
|
+
id = File.basename(file, ".rb")
|
33
|
+
fail "Mario #{id} already loaded" if all[id]
|
34
|
+
load file
|
35
|
+
klass = Mario.const_get(id.camelize)
|
36
|
+
all[id] = klass.new
|
37
|
+
logger.info "Loaded Mario #{id}: #{klass}"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
# API keys (see instance method api_key).
|
42
|
+
attr_accessor :api_keys
|
43
|
+
|
44
|
+
def included(klass)
|
45
|
+
klass.extend ClassMethods
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
|
50
|
+
module ClassMethods
|
51
|
+
# Mario identifier.
|
52
|
+
def mario_id
|
53
|
+
@mario_id ||= name.demodulize.underscore
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
|
58
|
+
# Returns the display name for this Mario.
|
59
|
+
#
|
60
|
+
# Uses the resource 'name', and fallbacks on the class name (e.g
|
61
|
+
# Mario::OneUp becomes "One Up").
|
62
|
+
def name
|
63
|
+
resources["name"] || mario_id.titleize
|
64
|
+
end
|
65
|
+
|
66
|
+
# Returns additional information about this source.
|
67
|
+
#
|
68
|
+
# A good description helps the user identity source and decide whether or
|
69
|
+
# not to use it.
|
70
|
+
#
|
71
|
+
# Uses the resource 'description'.
|
72
|
+
def description
|
73
|
+
resources["description"]
|
74
|
+
end
|
75
|
+
|
76
|
+
# This method returns a hash with two values:
|
77
|
+
# * inputs -- HTML fragment for a setup form
|
78
|
+
# * notes -- HTML fragment for setup notes
|
79
|
+
#
|
80
|
+
# Uses the resources 'inputs' and 'notes'.
|
81
|
+
def display
|
82
|
+
{ :inputs=>resources["inputs"], :notes=>resources["notes"] }
|
83
|
+
end
|
84
|
+
|
85
|
+
# Called to setup a new source with parameters from the HTML form (see
|
86
|
+
# #display). If there are any missing values, report them when #validate is
|
87
|
+
# called.
|
88
|
+
def setup(source, params)
|
89
|
+
end
|
90
|
+
|
91
|
+
# Called to validate the source. If there are any error, raise an
|
92
|
+
# exception. A good error message will help the user understand which value
|
93
|
+
# is missing or invalid and how to correct that.
|
94
|
+
def validate(source)
|
95
|
+
end
|
96
|
+
|
97
|
+
# Called to register a Webhook (for sources that need it)
|
98
|
+
def register(source, url)
|
99
|
+
end
|
100
|
+
|
101
|
+
# Called to update the source. This method will be called periodically with
|
102
|
+
# a source and a block. When triggered by a Webhook, it will be called with
|
103
|
+
# source, Rack::Request and a block. It can yield to the block any number of
|
104
|
+
# times with any combination of the supported named arguments for updating
|
105
|
+
# the source.
|
106
|
+
def update(source, request, &block)
|
107
|
+
end
|
108
|
+
|
109
|
+
# Called to unregister a Webhook (for sources that don't need it).
|
110
|
+
def unregister(source, url)
|
111
|
+
end
|
112
|
+
|
113
|
+
# Returns meta-data to be displayed alongside any other data. This method
|
114
|
+
# should return an array of hashes, each with the keys title (optional),
|
115
|
+
# text and url (optional). Good meta-data provides timely and relevant
|
116
|
+
# information that is not available in the raw data.
|
117
|
+
def meta(source)
|
118
|
+
[]
|
119
|
+
end
|
120
|
+
|
121
|
+
protected
|
122
|
+
|
123
|
+
# Source identifier.
|
124
|
+
def mario_id
|
125
|
+
self.class.mario_id
|
126
|
+
end
|
127
|
+
|
128
|
+
# Logger. Dump messages that can help with troubleshooting.
|
129
|
+
def logger
|
130
|
+
DashFu::Mario.logger
|
131
|
+
end
|
132
|
+
|
133
|
+
# Returns I18n resources for this gem.
|
134
|
+
def resources
|
135
|
+
unless @resources
|
136
|
+
file_name = File.dirname(__FILE__) + "/marios/#{mario_id}.yml"
|
137
|
+
@resources = File.exist?(file_name) ? YAML.load_file(file_name)["en"] : {}
|
138
|
+
end
|
139
|
+
@resources
|
140
|
+
end
|
141
|
+
|
142
|
+
# Shortcut for Rack::Utils.escape_html
|
143
|
+
def escape_html(text)
|
144
|
+
Rack::Utils.escape_html(text.to_s)
|
145
|
+
end
|
146
|
+
alias :h :escape_html
|
147
|
+
|
148
|
+
# Returns API key for this source. May return string or hash, depending on
|
149
|
+
# the API.
|
150
|
+
def api_key
|
151
|
+
@api_key ||= DashFu::Mario.api_keys[mario_id] or raise "No API key for #{mario_id}"
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|