├── .rbenv-version ├── vendor ├── .require_paths ├── cache │ ├── amqp-0.6.7.gem │ ├── crack-0.1.8.gem │ ├── i18n-0.5.0.gem │ ├── json-1.6.1.gem │ ├── jwt-0.1.3.gem │ ├── mash-0.1.1.gem │ ├── oauth-0.4.4.gem │ ├── rack-1.3.0.gem │ ├── rake-0.8.7.gem │ ├── thin-1.2.2.gem │ ├── tilt-1.2.2.gem │ ├── xmpp4r-0.5.gem │ ├── builder-2.1.2.gem │ ├── daemons-1.1.0.gem │ ├── hashie-1.1.0.gem │ ├── sinatra-1.2.6.gem │ ├── tinder-1.7.0.gem │ ├── tmail-1.2.3.1.gem │ ├── httparty-0.7.4.gem │ ├── mime-types-1.16.gem │ ├── multi_json-1.0.3.gem │ ├── ruby-hmac-0.4.0.gem │ ├── yajl-ruby-0.8.3.gem │ ├── activemodel-3.0.10.gem │ ├── addressable-2.2.6.gem │ ├── faraday-0.7.5.pre.gem │ ├── simple_oauth-0.1.5.gem │ ├── twilio-ruby-3.4.2.gem │ ├── xml-simple-1.0.11.gem │ ├── activeresource-3.0.10.gem │ ├── activesupport-3.0.10.gem │ ├── eventmachine-0.12.10.gem │ ├── http_parser.rb-0.5.3.gem │ ├── multipart-post-1.1.3.gem │ ├── twitter-stream-0.1.14.gem │ ├── xmpp4r-simple-0.8.4.gem │ ├── faraday_middleware-0.7.0.gem │ └── statsd-ruby-0.3.0.github.1.gem └── internal-gems │ ├── yammer4r-0.1.5 │ ├── TODO │ ├── spec │ │ ├── spec_helper.rb │ │ └── yammer │ │ │ └── client_spec.rb │ ├── oauth.yml.template │ ├── Rakefile │ ├── lib │ │ ├── yammer │ │ │ ├── user.rb │ │ │ ├── message_list.rb │ │ │ └── message.rb │ │ ├── yammer4r.rb │ │ └── ext │ │ │ └── core_ext.rb │ ├── example.rb │ └── README │ └── rubyforge │ └── lib │ └── rubyforge.rb ├── config ├── email.yml └── secrets.yml.example ├── .gitignore ├── lib └── events │ ├── helpers │ ├── helpers_with_repo.rb │ └── helpers_with_actions.rb │ ├── issue_helpers.rb │ └── pull_request_helpers.rb ├── services ├── read_the_docs.rb ├── masterbranch.rb ├── rdocinfo.rb ├── gitlive.rb ├── sourcemint.rb ├── web_translate_it.rb ├── continuity_app.rb ├── geocommit.rb ├── boxcar.rb ├── acunote.rb ├── commitify.rb ├── bugherd.rb ├── codeclimate.rb ├── leanto.rb ├── redmine.rb ├── cube.rb ├── trac.rb ├── splendid_bacon.rb ├── planbox.rb ├── bugly.rb ├── zohoprojects.rb ├── kanbanery.rb ├── github_pages.rb ├── get_localization.rb ├── flowdock.rb ├── scrumdo.rb ├── mantis_bt.rb ├── friend_feed.rb ├── pachube.rb ├── jaconda.rb ├── grmble.rb ├── co_op.rb ├── pivotal_tracker.rb ├── teamcity.rb ├── gemnasium.rb ├── appharbor.rb ├── rubyforge.rb ├── prowl.rb ├── hipchat.rb ├── notifymyandroid.rb ├── freckle.rb ├── talker.rb ├── travis.rb ├── toggl.rb ├── kickoff.rb ├── statusnet.rb ├── presently.rb ├── notifo.rb ├── twilio.rb ├── ontime.rb ├── socialcast.rb ├── web.rb ├── jira.rb ├── twitter.rb ├── fog_bugz.rb ├── yammer.rb ├── active_collab.rb ├── bamboo.rb ├── harvest.rb ├── lighthouse.rb ├── campfire.rb ├── convore.rb ├── README.md └── jabber.rb ├── config.ru ├── docs ├── sourcemint ├── continuity_app ├── kanbanery ├── read_the_docs ├── planbox ├── kickoff ├── statusnet ├── github_pages ├── grmble ├── geocommit ├── web_translate_it ├── rdocinfo ├── codeclimate ├── mantis_bt ├── pivotal_tracker ├── harvest ├── toggl ├── flowdock ├── masterbranch ├── splendid_bacon ├── email ├── gitlive ├── presently ├── jabber ├── bugherd ├── convore ├── pachube ├── gemnasium ├── jaconda ├── get_localization ├── friend_feed ├── commitify ├── cia ├── talker ├── co_op ├── acunote ├── run_code_run ├── boxcar ├── cube ├── trac ├── lighthouse ├── socialcast ├── notifymyandroid ├── appharbor ├── prowl ├── campfire ├── twitter ├── unfuddle ├── hipchat ├── rubyforge ├── basecamp ├── scrumdo ├── freckle ├── zohoprojects ├── bamboo ├── twilio ├── travis ├── notifo ├── irc ├── active_collab ├── bugly ├── jira ├── redmine ├── yammer ├── teamcity ├── bugzilla ├── amqp ├── target_process ├── ontime └── you_track ├── test ├── grmble_test.rb ├── git_live_test.rb ├── leanto_test.rb ├── acunote_test.rb ├── planbox_test.rb ├── commitify_test.rb ├── friend_feed_test.rb ├── masterbranch_test.rb ├── sourcemint_test.rb ├── prowl_test.rb ├── rdocinfo_test.rb ├── geocommit_test.rb ├── kickoff_test.rb ├── notifymyandroid_test.rb ├── read_the_docs_test.rb ├── get_localization_test.rb ├── continuity_app_test.rb ├── ontime_test.rb ├── lighthouse_test.rb ├── hip_chat_test.rb ├── presently_test.rb ├── web_translate_it_test.rb ├── splendid_bacon_test.rb ├── boxcar_test.rb ├── rubyforge_test.rb ├── jira_test.rb ├── bugly_test.rb ├── statusnet_test.rb ├── redmine_test.rb ├── talker_test.rb ├── yammer_test.rb ├── trac_test.rb ├── kanbanery_test.rb ├── mantis_bt_test.rb ├── basecamp_test.rb ├── cia_test.rb ├── cube_test.rb ├── toggl_test.rb ├── convore_test.rb ├── jaconda_test.rb ├── scrumdo_test.rb ├── teamcity_test.rb ├── zohoprojects_test.rb ├── socialcast_test.rb ├── twitter_test.rb ├── flowdock_test.rb ├── bugherd_test.rb ├── notifo_test.rb ├── coop_test.rb ├── helper.rb ├── unfuddle_test.rb ├── appharbor_test.rb ├── pachube_test.rb ├── codeclimate_test.rb ├── service_test.rb ├── pivotal_tracker_test.rb ├── active_collab_test.rb ├── gemnasium_test.rb ├── email_test.rb ├── fog_bugz_test.rb ├── harvest_test.rb ├── youtrack_test.rb ├── jabber_test.rb ├── freckle_test.rb └── irc_test.rb ├── github-services.rb ├── script └── deliver_payload ├── Gemfile ├── Rakefile └── LICENSE /.rbenv-version: -------------------------------------------------------------------------------- 1 | 1.8.7-p352 2 | -------------------------------------------------------------------------------- /vendor/.require_paths: -------------------------------------------------------------------------------- 1 | lib 2 | ext/tmailscanner 3 | bin 4 | -------------------------------------------------------------------------------- /config/email.yml: -------------------------------------------------------------------------------- 1 | --- 2 | address: smtp1.rs.github.com 3 | port: 25 4 | domain: github.com 5 | -------------------------------------------------------------------------------- /vendor/cache/amqp-0.6.7.gem: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progrium/github-services/master/vendor/cache/amqp-0.6.7.gem -------------------------------------------------------------------------------- /vendor/cache/crack-0.1.8.gem: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progrium/github-services/master/vendor/cache/crack-0.1.8.gem -------------------------------------------------------------------------------- /vendor/cache/i18n-0.5.0.gem: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progrium/github-services/master/vendor/cache/i18n-0.5.0.gem -------------------------------------------------------------------------------- /vendor/cache/json-1.6.1.gem: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progrium/github-services/master/vendor/cache/json-1.6.1.gem -------------------------------------------------------------------------------- /vendor/cache/jwt-0.1.3.gem: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progrium/github-services/master/vendor/cache/jwt-0.1.3.gem -------------------------------------------------------------------------------- /vendor/cache/mash-0.1.1.gem: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progrium/github-services/master/vendor/cache/mash-0.1.1.gem -------------------------------------------------------------------------------- /vendor/cache/oauth-0.4.4.gem: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progrium/github-services/master/vendor/cache/oauth-0.4.4.gem -------------------------------------------------------------------------------- /vendor/cache/rack-1.3.0.gem: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progrium/github-services/master/vendor/cache/rack-1.3.0.gem -------------------------------------------------------------------------------- /vendor/cache/rake-0.8.7.gem: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progrium/github-services/master/vendor/cache/rake-0.8.7.gem -------------------------------------------------------------------------------- /vendor/cache/thin-1.2.2.gem: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progrium/github-services/master/vendor/cache/thin-1.2.2.gem -------------------------------------------------------------------------------- /vendor/cache/tilt-1.2.2.gem: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progrium/github-services/master/vendor/cache/tilt-1.2.2.gem -------------------------------------------------------------------------------- /vendor/cache/xmpp4r-0.5.gem: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progrium/github-services/master/vendor/cache/xmpp4r-0.5.gem -------------------------------------------------------------------------------- /vendor/cache/builder-2.1.2.gem: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progrium/github-services/master/vendor/cache/builder-2.1.2.gem -------------------------------------------------------------------------------- /vendor/cache/daemons-1.1.0.gem: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progrium/github-services/master/vendor/cache/daemons-1.1.0.gem -------------------------------------------------------------------------------- /vendor/cache/hashie-1.1.0.gem: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progrium/github-services/master/vendor/cache/hashie-1.1.0.gem -------------------------------------------------------------------------------- /vendor/cache/sinatra-1.2.6.gem: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progrium/github-services/master/vendor/cache/sinatra-1.2.6.gem -------------------------------------------------------------------------------- /vendor/cache/tinder-1.7.0.gem: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progrium/github-services/master/vendor/cache/tinder-1.7.0.gem -------------------------------------------------------------------------------- /vendor/cache/tmail-1.2.3.1.gem: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progrium/github-services/master/vendor/cache/tmail-1.2.3.1.gem -------------------------------------------------------------------------------- /vendor/cache/httparty-0.7.4.gem: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progrium/github-services/master/vendor/cache/httparty-0.7.4.gem -------------------------------------------------------------------------------- /vendor/cache/mime-types-1.16.gem: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progrium/github-services/master/vendor/cache/mime-types-1.16.gem -------------------------------------------------------------------------------- /vendor/cache/multi_json-1.0.3.gem: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progrium/github-services/master/vendor/cache/multi_json-1.0.3.gem -------------------------------------------------------------------------------- /vendor/cache/ruby-hmac-0.4.0.gem: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progrium/github-services/master/vendor/cache/ruby-hmac-0.4.0.gem -------------------------------------------------------------------------------- /vendor/cache/yajl-ruby-0.8.3.gem: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progrium/github-services/master/vendor/cache/yajl-ruby-0.8.3.gem -------------------------------------------------------------------------------- /vendor/cache/activemodel-3.0.10.gem: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progrium/github-services/master/vendor/cache/activemodel-3.0.10.gem -------------------------------------------------------------------------------- /vendor/cache/addressable-2.2.6.gem: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progrium/github-services/master/vendor/cache/addressable-2.2.6.gem -------------------------------------------------------------------------------- /vendor/cache/faraday-0.7.5.pre.gem: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progrium/github-services/master/vendor/cache/faraday-0.7.5.pre.gem -------------------------------------------------------------------------------- /vendor/cache/simple_oauth-0.1.5.gem: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progrium/github-services/master/vendor/cache/simple_oauth-0.1.5.gem -------------------------------------------------------------------------------- /vendor/cache/twilio-ruby-3.4.2.gem: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progrium/github-services/master/vendor/cache/twilio-ruby-3.4.2.gem -------------------------------------------------------------------------------- /vendor/cache/xml-simple-1.0.11.gem: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progrium/github-services/master/vendor/cache/xml-simple-1.0.11.gem -------------------------------------------------------------------------------- /vendor/cache/activeresource-3.0.10.gem: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progrium/github-services/master/vendor/cache/activeresource-3.0.10.gem -------------------------------------------------------------------------------- /vendor/cache/activesupport-3.0.10.gem: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progrium/github-services/master/vendor/cache/activesupport-3.0.10.gem -------------------------------------------------------------------------------- /vendor/cache/eventmachine-0.12.10.gem: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progrium/github-services/master/vendor/cache/eventmachine-0.12.10.gem -------------------------------------------------------------------------------- /vendor/cache/http_parser.rb-0.5.3.gem: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progrium/github-services/master/vendor/cache/http_parser.rb-0.5.3.gem -------------------------------------------------------------------------------- /vendor/cache/multipart-post-1.1.3.gem: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progrium/github-services/master/vendor/cache/multipart-post-1.1.3.gem -------------------------------------------------------------------------------- /vendor/cache/twitter-stream-0.1.14.gem: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progrium/github-services/master/vendor/cache/twitter-stream-0.1.14.gem -------------------------------------------------------------------------------- /vendor/cache/xmpp4r-simple-0.8.4.gem: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progrium/github-services/master/vendor/cache/xmpp4r-simple-0.8.4.gem -------------------------------------------------------------------------------- /vendor/cache/faraday_middleware-0.7.0.gem: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progrium/github-services/master/vendor/cache/faraday_middleware-0.7.0.gem -------------------------------------------------------------------------------- /vendor/cache/statsd-ruby-0.3.0.github.1.gem: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progrium/github-services/master/vendor/cache/statsd-ruby-0.3.0.github.1.gem -------------------------------------------------------------------------------- /config/secrets.yml.example: -------------------------------------------------------------------------------- 1 | # This is a placeholder for service secrets that gets written over on deploy. 2 | # THEY ARE SECRET, YOU CANNOT HAVE THEM 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | deploy.rb 3 | *~ 4 | config/secrets.yml 5 | config/services.json 6 | /bin 7 | vendor/gems 8 | .bundle 9 | docs/payload_data 10 | -------------------------------------------------------------------------------- /lib/events/helpers/helpers_with_repo.rb: -------------------------------------------------------------------------------- 1 | module Service::HelpersWithRepo 2 | def repo 3 | @repo ||= self.class.objectify(payload['repository']) 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /vendor/internal-gems/yammer4r-0.1.5/TODO: -------------------------------------------------------------------------------- 1 | Test! There are currently no tests for yammer4r, and that makes me very sad. 2 | Switch to HTTParty instead of yammer_request. 3 | -------------------------------------------------------------------------------- /vendor/internal-gems/yammer4r-0.1.5/spec/spec_helper.rb: -------------------------------------------------------------------------------- 1 | $LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__) + "/../lib")) 2 | require 'yammer4r' 3 | require 'spec' -------------------------------------------------------------------------------- /services/read_the_docs.rb: -------------------------------------------------------------------------------- 1 | class Service::ReadTheDocs < Service 2 | def receive_push 3 | http_post "http://readthedocs.org/github", :payload => JSON.generate(payload) 4 | end 5 | end 6 | 7 | -------------------------------------------------------------------------------- /vendor/internal-gems/yammer4r-0.1.5/oauth.yml.template: -------------------------------------------------------------------------------- 1 | consumer: 2 | key: CLIENT_KEY 3 | secret: CLIENT_SECRET 4 | 5 | access: 6 | token: CONSUMER_TOKEN 7 | secret: CONSUMER_SECRET 8 | -------------------------------------------------------------------------------- /services/masterbranch.rb: -------------------------------------------------------------------------------- 1 | class Service::Masterbranch < Service 2 | def receive_push 3 | http_post "http://webhooks.masterbranch.com/gh-hook", 4 | :payload => payload.to_json 5 | end 6 | end 7 | 8 | -------------------------------------------------------------------------------- /services/rdocinfo.rb: -------------------------------------------------------------------------------- 1 | class Service::RDocInfo < Service 2 | self.title = 'Rdocinfo' 3 | 4 | def receive_push 5 | http_post 'http://rubydoc.info/checkout', :payload => payload.to_json 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /config.ru: -------------------------------------------------------------------------------- 1 | require File.expand_path('../config/load', __FILE__) 2 | 3 | Service::App.set :environment => :production, 4 | :port => ARGV.first || 8080, 5 | :logging => true 6 | 7 | run Service::App 8 | -------------------------------------------------------------------------------- /lib/events/helpers/helpers_with_actions.rb: -------------------------------------------------------------------------------- 1 | module Service::HelpersWithActions 2 | def action 3 | payload['action'].to_s 4 | end 5 | 6 | def opened? 7 | action == 'opened' 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /services/gitlive.rb: -------------------------------------------------------------------------------- 1 | class Service::GitLive < Service 2 | self.title = 'gitlive' 3 | def receive_push 4 | http_post 'http://gitlive.com/hook', 5 | :payload => JSON.generate(payload) 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /services/sourcemint.rb: -------------------------------------------------------------------------------- 1 | class Service::Sourcemint < Service 2 | def receive_push 3 | http_post 'http://api.sourcemint.com/actions/post-commit', 4 | :payload => JSON.generate(payload) 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /docs/sourcemint: -------------------------------------------------------------------------------- 1 | Sourcemint 2 | ========== 3 | 4 | Notify the [Sourcemint](http://sourcemint.com/) package repository and build service when a new release has been tagged 5 | or changes have been pushed to a branch. 6 | -------------------------------------------------------------------------------- /services/web_translate_it.rb: -------------------------------------------------------------------------------- 1 | class Service::WebTranslateIt < Service 2 | string :api_key 3 | 4 | def receive_push 5 | http_post "https://webtranslateit.com/api/projects/#{data['api_key']}/refresh_files", 6 | :payload => JSON.generate(payload) 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /services/continuity_app.rb: -------------------------------------------------------------------------------- 1 | class Service::ContinuityApp < Service 2 | string :project_id 3 | 4 | def receive_push 5 | http_post "http://hooks.continuityapp.com/github_selfservice/v1/%d" % data['project_id'].to_i, 6 | :payload => JSON.generate(payload) 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /services/geocommit.rb: -------------------------------------------------------------------------------- 1 | class Service::GeoCommit < Service 2 | self.title = 'geocommit' 3 | def receive_push 4 | http.headers['Content-Type'] = 'application/githubpostreceive+json' 5 | http_post 'http://hook.geocommit.com/api/github', 6 | JSON.generate(payload) 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /docs/continuity_app: -------------------------------------------------------------------------------- 1 | ContinuityApp 2 | ======== 3 | 4 | ContinuityApp is a Hosted Continuous Integration Service. 5 | Signup at http://continuityapp.com 6 | 7 | Install Notes 8 | ------------- 9 | 10 | "Project Id" is your project identifier: you can find it after creating a new project at ContinuityApp. -------------------------------------------------------------------------------- /docs/kanbanery: -------------------------------------------------------------------------------- 1 | Kanbanery 2 | ====== 3 | 4 | Install Notes 5 | ------------- 6 | 7 | 1. project token - Your project GitHub token from Kanbanery 8 | 2. project id 9 | 10 | Developer Notes 11 | --------------- 12 | 13 | data 14 | - project_token 15 | - project_id 16 | 17 | payload 18 | - refer to docs/github_payload -------------------------------------------------------------------------------- /docs/read_the_docs: -------------------------------------------------------------------------------- 1 | ReadTheDocs 2 | =========== 3 | 4 | Automatically build documentation hosted on readthedocs.org. 5 | 6 | 7 | Developer Notes 8 | --------------- 9 | 10 | data 11 | - (no data required; payload is sent to http://readthedocs.org/github) 12 | 13 | payload 14 | - refer to docs/github_payload 15 | 16 | -------------------------------------------------------------------------------- /services/boxcar.rb: -------------------------------------------------------------------------------- 1 | class Service::Boxcar < Service 2 | string :subscribers 3 | 4 | def receive_push 5 | http_post \ 6 | "http://providers.boxcar.io/github/%s" % 7 | [secrets['boxcar']['apikey']], 8 | :emails => data['subscribers'], 9 | :payload => JSON.generate(payload) 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /services/acunote.rb: -------------------------------------------------------------------------------- 1 | class Service::Acunote < Service 2 | string :token 3 | 4 | def receive_push 5 | res = http_post "https://www.acunote.com/source_control/github/%s" % 6 | [ data['token'] ], 7 | {'payload' => payload.to_json} 8 | 9 | if res.status != 200 10 | raise_config_error 11 | end 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /services/commitify.rb: -------------------------------------------------------------------------------- 1 | class Service::Commitify < Service 2 | string :private_key 3 | 4 | def receive_push 5 | http_post "http://commitify.appspot.com/commit", 6 | # Private key (for private repositories, share with your developers) 7 | :key => data['private_key'], 8 | :payload => JSON.generate(payload) 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /docs/planbox: -------------------------------------------------------------------------------- 1 | Planbox 2 | ======= 3 | 4 | token is your Planbox Inititative Token. Find in on the Manage page. 5 | 6 | payload contains the commit data; same as you get when using API. See docs/github_payload. 7 | 8 | TEST 9 | ---- 10 | 11 | svc = Service::Planbox.new(:push, {'token' => '223cazxbs97de1ndj61d8aa435b0o9i05'}) 12 | svc.receive_push 13 | -------------------------------------------------------------------------------- /services/bugherd.rb: -------------------------------------------------------------------------------- 1 | class Service::Bugherd < Service 2 | string :project_key 3 | 4 | def receive_push 5 | if data['url'].present? 6 | url = data['url'] 7 | else 8 | url = "http://www.bugherd.com/github_web_hook/#{data['project_key']}" 9 | end 10 | http_post url, 11 | :payload => JSON.generate(payload) 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /services/codeclimate.rb: -------------------------------------------------------------------------------- 1 | class Service::CodeClimate < Service 2 | string :token 3 | 4 | def receive_push 5 | http.ssl[:verify] = false 6 | http.basic_auth "github", token 7 | http_post "https://codeclimate.com/github_pushes", :payload => payload.to_json 8 | end 9 | 10 | def token 11 | data["token"].to_s.strip 12 | end 13 | 14 | end 15 | -------------------------------------------------------------------------------- /services/leanto.rb: -------------------------------------------------------------------------------- 1 | class Service::Leanto < Service 2 | string :token 3 | 4 | self.title = 'Lean-To' 5 | 6 | def receive_push 7 | res = http_post "http://www.lean-to.com/api/%s/commit" % 8 | [ data['token'] ], 9 | {'payload' => payload.to_json} 10 | 11 | if res.status != 200 12 | raise_config_error 13 | end 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /vendor/internal-gems/yammer4r-0.1.5/Rakefile: -------------------------------------------------------------------------------- 1 | $:.unshift(File.join(File.dirname(__FILE__), 'lib')) 2 | 3 | require 'rubygems' 4 | require 'rake' 5 | require 'spec/rake/spectask' 6 | require 'yammer4r' 7 | 8 | desc "Run all specs" 9 | Spec::Rake::SpecTask.new('spec') do |t| 10 | t.spec_files = FileList['spec/**/*spec.rb'] 11 | end 12 | 13 | task :default => [:spec] -------------------------------------------------------------------------------- /docs/kickoff: -------------------------------------------------------------------------------- 1 | Kickoff 2 | ======== 3 | 4 | Install Notes 5 | ------------- 6 | 7 | 1. the project id and project token are available in the Kickoff app by right clicking on a project or through the API 8 | 9 | 10 | Developer Notes 11 | --------------- 12 | 13 | data 14 | - project_id 15 | - project_token 16 | 17 | payload 18 | - refer to docs/github_payload 19 | -------------------------------------------------------------------------------- /services/redmine.rb: -------------------------------------------------------------------------------- 1 | class Service::Redmine < Service 2 | string :address, :project, :api_key 3 | 4 | def receive_push 5 | http.ssl[:verify] = false 6 | http.url_prefix = data['address'] 7 | http_get "sys/fetch_changesets" do |req| 8 | req.params['key'] = data['api_key'] 9 | req.params['id'] = data['project'] 10 | end 11 | end 12 | end 13 | 14 | -------------------------------------------------------------------------------- /services/cube.rb: -------------------------------------------------------------------------------- 1 | class Service::Cube < Service 2 | string :domain, :project, :token 3 | 4 | def receive_push 5 | http_post "http://cube.bitrzr.com/integration/events/github/create", 6 | 'payload' => JSON.generate(payload), 7 | 'project_name' => data['project'], 8 | 'project_token' => data['token'], 9 | 'domain' => data['domain'] 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /services/trac.rb: -------------------------------------------------------------------------------- 1 | class Service::Trac < Service 2 | string :url, :token 3 | 4 | def receive_push 5 | http.ssl[:verify] = false 6 | http.url_prefix = data['url'] 7 | http_post "github/#{data['token']}", :payload => payload.to_json 8 | rescue Faraday::Error::ConnectionFailed 9 | raise_config_error "Connection refused. Invalid server URL." 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /vendor/internal-gems/yammer4r-0.1.5/lib/yammer/user.rb: -------------------------------------------------------------------------------- 1 | class Yammer::User 2 | extend Forwardable 3 | def_delegator :@user, :id 4 | 5 | def initialize(mash, client) 6 | @user = mash 7 | @client = client 8 | end 9 | 10 | def me? 11 | @user.id == @client.me.id 12 | end 13 | 14 | def method_missing(call, *args) 15 | @user.send(call, *args) 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /docs/statusnet: -------------------------------------------------------------------------------- 1 | Statusnet (laconica) 2 | ==================== 3 | 4 | Install Notes 5 | ------------- 6 | 7 | 1. the server field should be the server base URI.(eg. http://identi.ca or http://identi.ca/index.php) 8 | 9 | 10 | Developer Notes 11 | --------------- 12 | 13 | data 14 | - username 15 | - password 16 | - digest (boolean) 17 | - server 18 | 19 | payload 20 | - refer to docs/github_payload 21 | -------------------------------------------------------------------------------- /docs/github_pages: -------------------------------------------------------------------------------- 1 | GitHub Pages 2 | ============ 3 | 4 | GitHub Pages is a service hook that lets you trigger Pages rebuilds from repository events. Just pick the events you want to trigger a rebuild with. 5 | 6 | 7 | Developer Notes 8 | --------------- 9 | 10 | data 11 | - gollum 12 | - issues 13 | - issue_comment 14 | - push 15 | - commit_comment 16 | 17 | payload 18 | - refer to docs/github_payload 19 | -------------------------------------------------------------------------------- /docs/grmble: -------------------------------------------------------------------------------- 1 | Grmble 2 | ======== 3 | 4 | Install Notes 5 | ------------- 6 | 7 | 1. room_api_url should be your room's API url from your room's admin page 8 | Eg: http://grmble.com/api/room/ROOMKEY 9 | 2. token should be the API key from your room's admin page 10 | 11 | Developer Notes 12 | --------------- 13 | 14 | data 15 | - room_api_url 16 | - token 17 | 18 | payload 19 | - refer to docs/github_payload -------------------------------------------------------------------------------- /vendor/internal-gems/yammer4r-0.1.5/lib/yammer/message_list.rb: -------------------------------------------------------------------------------- 1 | class Yammer::MessageList < Array 2 | 3 | attr_reader :older_available, :ids 4 | 5 | def initialize(a, oa, c) 6 | super(a) 7 | @older_available = oa 8 | @client = c 9 | @ids = a.map {|m| m.id}.sort 10 | end 11 | 12 | def first 13 | self[0] 14 | end 15 | 16 | def last 17 | self[self.size - 1] 18 | end 19 | 20 | end -------------------------------------------------------------------------------- /docs/geocommit: -------------------------------------------------------------------------------- 1 | Geocommit 2 | ========== 3 | 4 | With this service you can send your commits to geocommit. Geocommit analyzes geographical geocommit information in git notes and allows you to visualize your contributions geographically. 5 | 6 | Install Notes 7 | ------------- 8 | 9 | 1. Profit! 10 | 11 | Developer Notes 12 | --------------- 13 | 14 | data 15 | - none 16 | 17 | payload 18 | - refer to docs/github_payload 19 | -------------------------------------------------------------------------------- /services/splendid_bacon.rb: -------------------------------------------------------------------------------- 1 | class Service::SplendidBacon < Service 2 | string :project_id, :token 3 | 4 | def receive_push 5 | token = data['token'] 6 | project_id = data['project_id'] 7 | http.url_prefix = 'https://splendidbacon.com' 8 | http_post "/api/v1/projects/#{project_id}/github" do |req| 9 | req.params[:token] = token 10 | req.body = {:payload => payload.to_json} 11 | end 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /services/planbox.rb: -------------------------------------------------------------------------------- 1 | class Service::Planbox < Service 2 | string :token 3 | 4 | def receive_push 5 | token = data['token'] 6 | res = http_post 'https://www.planbox.com/api/github_commits' do |req| 7 | req.params[:token] = data['token'] 8 | req.body = {:payload => payload.to_json} 9 | end 10 | 11 | if res.status < 200 || res.status > 299 12 | raise_config_error 13 | end 14 | end 15 | end 16 | 17 | -------------------------------------------------------------------------------- /vendor/internal-gems/yammer4r-0.1.5/example.rb: -------------------------------------------------------------------------------- 1 | require 'yammer4r' 2 | 3 | config_path = File.dirname(__FILE__) + 'oauth.yml' 4 | yammer = Yammer::Client.new(:config => config_path) 5 | 6 | # Get all messages 7 | messages = yammer.messages 8 | puts messages.size 9 | puts messages.last.body.plain 10 | puts messages.last.body.parsed 11 | 12 | # Print out all the users 13 | yammer.users.each do |u| 14 | puts "#{u.name} - #{u.me?}" 15 | end 16 | -------------------------------------------------------------------------------- /docs/web_translate_it: -------------------------------------------------------------------------------- 1 | Web Translate It 2 | ================ 3 | 4 | This service notify Web Translate It of pushes to your public repository. Web Translate It will then refresh the language file(s) if they have been updated. 5 | 6 | More info: https://webtranslateit.com/documentation/wikis/github-integration 7 | 8 | Install Notes 9 | ------------- 10 | 11 | API Key is your project API key 12 | (you can find it in the project settings) 13 | -------------------------------------------------------------------------------- /services/bugly.rb: -------------------------------------------------------------------------------- 1 | class Service::Bugly < Service 2 | string :project_id, :account_name, :token 3 | 4 | def receive_push 5 | http.ssl[:verify] = false # :( 6 | http_post "https://#{data['account_name']}.bug.ly/changesets.json?service=github&project_id=#{data['project_id']}", 7 | JSON.generate(payload), 8 | 'X-BuglyToken' => data['token'], 9 | 'Content-Type' => 'application/json' 10 | return 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /docs/rdocinfo: -------------------------------------------------------------------------------- 1 | rubydoc.info 2 | ========= 3 | 4 | This service allows you to auto-publish documentation for your Ruby gem or library. 5 | The resulting documentation will be hosted for you at http://rubydoc.info/github/your-name/your-project 6 | 7 | 8 | Developer Notes 9 | --------------- 10 | 11 | data 12 | - (no data is required, payload is simply posted to http://rubydoc.info/checkout) 13 | 14 | payload 15 | - refer to docs/github_payload 16 | -------------------------------------------------------------------------------- /services/zohoprojects.rb: -------------------------------------------------------------------------------- 1 | class Service::ZohoProjects < Service 2 | string :project_id, :token 3 | 4 | def receive_push 5 | res = http_post "https://projects.zoho.com/serviceHook", 6 | :pId => data['project_id'], 7 | :authtoken => data['token'], 8 | :scope => "projectsapi", 9 | :payload => JSON.generate(payload) 10 | if res.status != 200 11 | raise_config_error 12 | end 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /services/kanbanery.rb: -------------------------------------------------------------------------------- 1 | class Service::Kanbanery < Service 2 | string :project_id, :project_token 3 | 4 | def receive_push 5 | project_id = data['project_id'] 6 | token = data['project_token'] 7 | 8 | http_post "http://kanbanery.com/api/v1/projects/#{project_id}/git_commits", 9 | payload.to_json, 10 | 'X-Kanbanery-ProjectGitHubToken' => token, 11 | 'Content-Type' => 'application/json' 12 | 13 | end 14 | end 15 | 16 | -------------------------------------------------------------------------------- /docs/codeclimate: -------------------------------------------------------------------------------- 1 | Code Climate 2 | ============ 3 | 4 | Install Notes 5 | ------------- 6 | 7 | 1. Create an account at https://codeclimate.com 8 | 2. Enter your Token (see instructions below) 9 | 10 | To get your Token: Log into your Code Climate account, click the gear icon at the top-right, then click the Integration tab. 11 | 12 | Developer Notes 13 | --------------- 14 | 15 | data 16 | - token 17 | 18 | payload 19 | - refer to docs/github_payload 20 | -------------------------------------------------------------------------------- /services/github_pages.rb: -------------------------------------------------------------------------------- 1 | require 'uri' 2 | 3 | class Service::GitHubPages < Service 4 | default_events :commit_comment, :gollum, :issues, :issue_comment, :push 5 | boolean :gollum 6 | boolean :issues 7 | boolean :issue_comment 8 | boolean :push 9 | boolean :commit_comment 10 | 11 | def receive_event 12 | if data[event.to_s].to_i == 1 13 | http_post "https://api.github.com/secret/", JSON.generate(payload) 14 | end 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /docs/mantis_bt: -------------------------------------------------------------------------------- 1 | MantisBT 2 | ======== 3 | 4 | Install Notes 5 | ------------- 6 | 7 | Requires the Source Integration plugins from http://leetcode.net/projects/source-integration/ 8 | 9 | 1. Base URL to MantisBT install 10 | 2. Secret API Key set at http://yoursite/mantis/plugin.php?page=Source/manage_config_page 11 | 12 | 13 | Developer Notes 14 | --------------- 15 | 16 | data 17 | - url 18 | - api_key 19 | 20 | payload 21 | - refer to docs/github_payload 22 | 23 | -------------------------------------------------------------------------------- /docs/pivotal_tracker: -------------------------------------------------------------------------------- 1 | Pivotal Tracker 2 | =============== 3 | 4 | Install Notes 5 | ------------- 6 | 7 | 1. token is your Pivotal Tracker API Token. This is at the bottom of your 'My Profile' page. 8 | 2. branch is the name of the branch you want to listen for commits on. If none is provided it will listen on all branches. 9 | 10 | Developer Notes 11 | --------------- 12 | 13 | data 14 | - token 15 | - branch 16 | 17 | payload 18 | - refer to docs/github_payload 19 | -------------------------------------------------------------------------------- /docs/harvest: -------------------------------------------------------------------------------- 1 | Harvest 2 | ======== 3 | 4 | Install Notes 5 | ------------- 6 | 7 | 1. Applies the status to the currently clocked in project. Future updates are expected to include more versatility. 8 | 9 | Developer Notes 10 | --------------- 11 | 12 | data 13 | - username (your email address) 14 | - password (harvest password) 15 | - subdomain (subdomain for your business ex. {subdomain}.harvestapp.com) 16 | - ssl (boolean) 17 | 18 | payload 19 | - refer to docs/github_payload 20 | -------------------------------------------------------------------------------- /docs/toggl: -------------------------------------------------------------------------------- 1 | toggl 2 | ======== 3 | 4 | Install Notes 5 | ------------- 6 | 7 | 1. API Key: Your toggl api key. (Get it at https://www.toggl.com/user/edit) 8 | 2. Project: the id of the toggl project that this repo links to 9 | 3. Activate and go! 10 | 4. To track your time simply add t:number-of-minutes (integer) to your commit message 11 | 12 | Developer Notes 13 | --------------- 14 | 15 | data 16 | - api_key 17 | - project 18 | 19 | payload 20 | - refer to docs/github_payload 21 | -------------------------------------------------------------------------------- /docs/flowdock: -------------------------------------------------------------------------------- 1 | Flowdock 2 | ========== 3 | 4 | Broadcast this project's commits, pull requests, and issues and their 5 | respective comments to Flowdock. 6 | 7 | Install Notes 8 | ------------- 9 | 10 | API Token is a flow-specific token. You can find it either in the flow, or in Flowdock's Integrations help page at https://www.flowdock.com/help/integrations. 11 | 12 | 13 | Developer Notes 14 | --------------- 15 | 16 | data 17 | - token 18 | 19 | payload 20 | - refer to docs/github_payload 21 | -------------------------------------------------------------------------------- /docs/masterbranch: -------------------------------------------------------------------------------- 1 | Masterbranch 2 | ======== 3 | 4 | Install Notes 5 | ------------- 6 | 7 | With this service your commit's logs will be sent to Masterbranch.com . Masterbranch will proportionate you with an automatic-updated profile of your project. This profile will show the different technologies you are using, including some stats based on the contributors development. 8 | 9 | Developer Notes 10 | --------------- 11 | 12 | data 13 | - none 14 | 15 | payload 16 | - refer to docs/github_payload 17 | -------------------------------------------------------------------------------- /docs/splendid_bacon: -------------------------------------------------------------------------------- 1 | Splendid Bacon 2 | =============== 3 | 4 | Install Notes 5 | ------------- 6 | 7 | 1. Token is your project token from Splendid Bacon. This is found on the project edit page on http://splendidbacon.com 8 | 2. Project ID is a unique identifier for your project. This is found on the project edit page or in any URL for the project. 9 | 10 | Developer Notes 11 | --------------- 12 | 13 | data 14 | - token 15 | - project_id 16 | 17 | payload 18 | - refer to docs/github_payload 19 | -------------------------------------------------------------------------------- /test/grmble_test.rb: -------------------------------------------------------------------------------- 1 | require File.expand_path('../helper', __FILE__) 2 | 3 | class GrmbleTest < Service::TestCase 4 | def setup 5 | @stubs = Faraday::Adapter::Test::Stubs.new 6 | end 7 | 8 | def test_push 9 | svc = service({'room_api_url' => 'http://abc.com/foo'}, payload) 10 | 11 | @stubs.post "/foo/msg" do |env| 12 | [200, {}, ''] 13 | end 14 | 15 | svc.receive_push 16 | end 17 | 18 | def service(*args) 19 | super Service::Grmble, *args 20 | end 21 | end 22 | 23 | -------------------------------------------------------------------------------- /vendor/internal-gems/yammer4r-0.1.5/lib/yammer4r.rb: -------------------------------------------------------------------------------- 1 | require 'forwardable' 2 | require 'rubygems' 3 | require 'date' 4 | require 'yaml' 5 | require 'open-uri' 6 | 7 | #gem 'json', '>= 1.1.7' 8 | #require 'json' 9 | 10 | #gem 'oauth', '>=0.3.5' 11 | require 'oauth' 12 | 13 | #gem 'mash', '>=0.0.3' 14 | require 'mash' 15 | 16 | $:.unshift(File.dirname(__FILE__)) 17 | require 'ext/core_ext' 18 | require 'yammer/client' 19 | require 'yammer/message' 20 | require 'yammer/message_list' 21 | require 'yammer/user' 22 | -------------------------------------------------------------------------------- /services/get_localization.rb: -------------------------------------------------------------------------------- 1 | class Service::GetLocalization < Service 2 | string :project_name, :project_token 3 | 4 | def receive_push 5 | project_name = data['project_name'] 6 | project_token = data['project_token'] 7 | 8 | res = http_post "https://www.getlocalization.com/services/github/notify/#{project_name}/#{project_token}/", 9 | :payload => payload.to_json 10 | 11 | if res.status < 200 || res.status > 299 12 | raise_config_error 13 | end 14 | end 15 | end 16 | 17 | 18 | -------------------------------------------------------------------------------- /docs/email: -------------------------------------------------------------------------------- 1 | Email 2 | ======== 3 | 4 | Install Notes 5 | ------------- 6 | 7 | 1. `address` (only one is allowed) 8 | 2. `secret` fills out the Approved header to automatically approve the message 9 | in a read-only or moderated mailing list. 10 | 3. `send_from_author` uses the commit author email address in the From address of the email. 11 | 12 | Developer Notes 13 | --------------- 14 | 15 | data 16 | - address 17 | - secret 18 | - send_from_author 19 | 20 | payload 21 | - refer to docs/github_payload 22 | -------------------------------------------------------------------------------- /docs/gitlive: -------------------------------------------------------------------------------- 1 | gitlive 2 | ======= 3 | 4 | gitlive displays your GitHub pushes in realtime on your project homepage. See http://gitlive.com/ for mort information. 5 | 6 | Install Notes 7 | ------------- 8 | 9 | 1. Activate service 10 | 11 | 2. Generate widget at http://gitlive.com/ for embedding on your project page. 12 | 13 | Note: Service is active after first push on GitHub. 14 | 15 | Developer Notes 16 | --------------- 17 | 18 | data 19 | - none 20 | 21 | payload 22 | - refer to docs/github_payload 23 | -------------------------------------------------------------------------------- /docs/presently: -------------------------------------------------------------------------------- 1 | Present.ly 2 | ========== 3 | 4 | Install Notes 5 | ------------- 6 | 7 | 1. subdomain (for a Present.ly account) 8 | 2. group_name (OPTIONAL; will broadcast as a group or as the system if group is 'system') 9 | 3. username (user must be a manager of the specified group or admin for 'system') 10 | 11 | Developer Notes 12 | --------------- 13 | 14 | data 15 | - subdomain 16 | - group_name (optional) 17 | - username 18 | - password 19 | 20 | payload 21 | - refer to docs/github_payload 22 | -------------------------------------------------------------------------------- /github-services.rb: -------------------------------------------------------------------------------- 1 | require File.expand_path('../config/load', __FILE__) 2 | 3 | Service::App.set :run => true, 4 | :environment => :production, 5 | :port => ARGV.first || 8080, 6 | :logging => true 7 | 8 | begin 9 | require 'mongrel' 10 | Service::App.set :server, 'mongrel' 11 | rescue LoadError 12 | begin 13 | require 'thin' 14 | Service::App.set :server, 'thin' 15 | rescue LoadError 16 | Service::App.set :server, 'webrick' 17 | end 18 | end 19 | 20 | Service::App.run! 21 | 22 | -------------------------------------------------------------------------------- /docs/jabber: -------------------------------------------------------------------------------- 1 | Jabber 2 | ====== 3 | 4 | Install Notes 5 | ------------- 6 | 7 | 1. user is the Jabber ID (e.g.: myusername@jabber.org). Multiple users can be added by separating them with commas. Currently, there is a maximum of 25 users. 8 | 2. muc is the Jabber ID (e.g.: talks@conference.jabber.org/Nick). Multiple conferences can be added by separating them with commas. 9 | 10 | Developer Notes 11 | --------------- 12 | 13 | data 14 | - user 15 | - muc 16 | 17 | payload 18 | - refer to docs/github_payload 19 | -------------------------------------------------------------------------------- /docs/bugherd: -------------------------------------------------------------------------------- 1 | BugHerd 2 | ======= 3 | 4 | BugHerd is the world's simplest bug tracker for the web. See: http://www.bugherd.com 5 | 6 | BugHerd allows you to visually track issues on your website. Using the GitHub integration you can update tasks directly from GitHub commit messages. 7 | 8 | 9 | Install Notes 10 | ------------- 11 | 12 | 1. project key -- you will find this key in BugHerd as you setup a GitHub integration in your project. For more info, see https://bugherd.tenderapp.com/kb/third-party-integrations/github 13 | -------------------------------------------------------------------------------- /docs/convore: -------------------------------------------------------------------------------- 1 | Convore 2 | ======== 3 | 4 | Install Notes 5 | ------------- 6 | 7 | 1. `topic_id` is the topic you'd like to post into. You'll need to use the 8 | API to walk down through your groups, then your desired group's topics. 9 | 10 | 2. `username` and `password` should come from a user you create just for 11 | this service hook. 12 | 13 | 14 | Developer Notes 15 | --------------- 16 | 17 | data 18 | - topic 19 | - username 20 | - password 21 | 22 | payload 23 | - refer to docs/github_payload 24 | -------------------------------------------------------------------------------- /docs/pachube: -------------------------------------------------------------------------------- 1 | Pachube 2 | ======= 3 | 4 | Publishes number of distinct commits per push to a [Pachube](https://pachube.com/) feed. 5 | Datastreams are created / updated for each repository name. 6 | 7 | Install Notes 8 | ------------- 9 | 10 | 1. Create a feed on [Pachube](https://pachube.com/). 11 | 2. Create an api key that has PUT permissions on the feed. 12 | 13 | 14 | Developer Notes 15 | --------------- 16 | 17 | data 18 | - api_key 19 | - feed_id 20 | 21 | payload 22 | - refer to docs/github_payload 23 | 24 | -------------------------------------------------------------------------------- /vendor/internal-gems/yammer4r-0.1.5/README: -------------------------------------------------------------------------------- 1 | = Yammer4R 2 | 3 | == Developers 4 | * {Jim Patterson} 5 | 6 | == Description 7 | Yammer4R provides an object based API to query or update your Yammer account via pure Ruby. It hides the ugly HTTP/REST code from your code. 8 | 9 | == External Dependencies 10 | * Ruby 1.8 (tested with 1.8.7) 11 | * JSON gem (tested with versions: 1.1.3) 12 | * OAuth gem (tested with versions: 0.2.7) 13 | * RSpec gem (tested with versions: 1.1.11) 14 | 15 | == Usage Examples 16 | Coming soon... -------------------------------------------------------------------------------- /test/git_live_test.rb: -------------------------------------------------------------------------------- 1 | require File.expand_path('../helper', __FILE__) 2 | 3 | class GitLiveTest < Service::TestCase 4 | def setup 5 | @stubs = Faraday::Adapter::Test::Stubs.new 6 | end 7 | 8 | def test_push 9 | svc = service({}, 'a' => 1) 10 | 11 | @stubs.post "/hook" do |env| 12 | assert_match /(^|\&)payload=%7B%22a%22%3A1%7D($|\&)/, env[:body] 13 | [200, {}, ''] 14 | end 15 | 16 | svc.receive_push 17 | end 18 | 19 | def service(*args) 20 | super Service::GitLive, *args 21 | end 22 | end 23 | 24 | 25 | -------------------------------------------------------------------------------- /docs/gemnasium: -------------------------------------------------------------------------------- 1 | Gemnasium 2 | ========= 3 | 4 | Install Notes 5 | ------------- 6 | 7 | Gemnasium notifies you when new versions are released for your GitHub repositories' gem dependencies. 8 | 9 | ---- 10 | 11 | 1. Enter your GitHub name 12 | 2. Create an account on [gemnasium.com](http://gemnasium.com/) 13 | 3. Enter your API key (from [gemnasium.com/account](http://gemnasium.com/account)) 14 | 4. Check "Active" 15 | 5. Click "Update Settings" 16 | 17 | Developer Notes 18 | --------------- 19 | 20 | data 21 | - name 22 | - token 23 | -------------------------------------------------------------------------------- /docs/jaconda: -------------------------------------------------------------------------------- 1 | Jaconda 2 | ======== 3 | 4 | Install Notes 5 | ------------- 6 | 7 | Using the following url as an example: 8 | https://bigbang.jaconda.im/rooms/galaxo 9 | 10 | 1. Subdomain is bigbang 11 | 2. Room ID is galaxo 12 | 3. Room token can be found on the Room Integration page 13 | 4. if Digest is checked, all commits will be compressed in one message 14 | 15 | Developer Notes 16 | --------------- 17 | 18 | data 19 | - subdomain 20 | - room_id 21 | - room_token 22 | - digest (boolean) 23 | 24 | payload 25 | - refer to docs/github_payload -------------------------------------------------------------------------------- /test/leanto_test.rb: -------------------------------------------------------------------------------- 1 | require File.expand_path('../helper', __FILE__) 2 | 3 | class LeantoTest < Service::TestCase 4 | def setup 5 | @stubs = Faraday::Adapter::Test::Stubs.new 6 | end 7 | 8 | def test_push 9 | url = "/api/abc/commit" 10 | @stubs.post url do |env| 11 | assert_equal "payload=%22payload%22", env[:body] 12 | [200, {}, ''] 13 | end 14 | 15 | svc = service :push, {'token' => 'abc'}, 'payload' 16 | svc.receive 17 | end 18 | 19 | def service(*args) 20 | super Service::Leanto, *args 21 | end 22 | end 23 | -------------------------------------------------------------------------------- /docs/get_localization: -------------------------------------------------------------------------------- 1 | Get Localization 2 | =============== 3 | 4 | Install Notes 5 | ------------- 6 | 7 | 1. Project name is your project name in Get Localization URL e.g: 8 | 9 | Given this URL: 10 | 11 | http://www.getlocalization.com/Example/ 12 | 13 | Your project name is "Example" 14 | 15 | 2. Project token is available at your project settings if you've GitHub support enabled. 16 | 17 | Developer Notes 18 | --------------- 19 | 20 | data 21 | - project_name 22 | - project_token 23 | 24 | payload 25 | - refer to docs/github_payload 26 | -------------------------------------------------------------------------------- /docs/friend_feed: -------------------------------------------------------------------------------- 1 | FriendFeed 2 | ========== 3 | 4 | This service lets your broadcast your commits on FriendFeed. A simple post is made to http://www.friendfeed.com/api/share with your commits. 5 | 6 | Example: 'Arun Thampi just pushed 56436bcdef2342ddfca234234 to github-services on GitHub' 7 | with the comment set as 'Integrated FriendFeed in github-services' 8 | 9 | 10 | Developer Notes 11 | --------------- 12 | 13 | data 14 | - nickname 15 | - remotekey [As specified by http://www.friendfeed.com/remotekey] 16 | 17 | payload 18 | - refer to docs/github_payload 19 | -------------------------------------------------------------------------------- /docs/commitify: -------------------------------------------------------------------------------- 1 | Commitify 2 | ======== 3 | 4 | Install Notes 5 | ------------- 6 | 7 | More info at http://commitify.appspot.com 8 | 9 | 1. private key (optional) -- Only necessary for private repositories; it prevents the public from subscribing to your notices. Can be any arbitrary string; if you're feeling uncreative, Commitify will generate one for you. Share it with your developers so they can subscribe to notifications. 10 | 11 | 12 | Developer Notes 13 | --------------- 14 | 15 | data 16 | - private_key 17 | 18 | payload 19 | - refer to docs/github_payload 20 | -------------------------------------------------------------------------------- /services/flowdock.rb: -------------------------------------------------------------------------------- 1 | require 'uri' 2 | 3 | class Service::Flowdock < Service 4 | default_events :commit_comment, :gollum, :issues, :issue_comment, :pull_request, :push 5 | string :token 6 | 7 | def receive_event 8 | raise_config_error "Missing token" if data['token'].to_s.empty? 9 | 10 | token = URI.escape(data['token'].to_s.gsub(/\s/, '')) 11 | 12 | http.headers['X-GitHub-Event'] = event.to_s 13 | http.headers['content-type'] = 'application/json' 14 | http_post "https://api.flowdock.com/v1/github/#{token}", JSON.generate(payload) 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /services/scrumdo.rb: -------------------------------------------------------------------------------- 1 | class Service::ScrumDo < Service 2 | string :username 3 | string :password 4 | string :project_slug 5 | 6 | def receive_push 7 | username = data["username"] 8 | password = data["password"] 9 | 10 | url = "http://www.scrumdo.com/hooks/github/#{data["project_slug"]}" 11 | res = http_post url do |req| 12 | req.body = {:payload => payload.to_json, :username=>username, :password=>password} 13 | end 14 | 15 | if res.status < 200 || res.status > 299 16 | raise_config_error 17 | end 18 | 19 | end 20 | end 21 | 22 | -------------------------------------------------------------------------------- /test/acunote_test.rb: -------------------------------------------------------------------------------- 1 | require File.expand_path('../helper', __FILE__) 2 | 3 | class AcunoteTest < Service::TestCase 4 | def setup 5 | @stubs = Faraday::Adapter::Test::Stubs.new 6 | end 7 | 8 | def test_push 9 | url = "/source_control/github/abc" 10 | @stubs.post url do |env| 11 | assert_equal "payload=%22payload%22", env[:body] 12 | [200, {}, ''] 13 | end 14 | 15 | svc = service :push, {'token' => 'abc'}, 'payload' 16 | svc.receive 17 | end 18 | 19 | def service(*args) 20 | super Service::Acunote, *args 21 | end 22 | end 23 | 24 | -------------------------------------------------------------------------------- /docs/cia: -------------------------------------------------------------------------------- 1 | CIA.vc 2 | ======== 3 | 4 | Install Notes 5 | ------------- 6 | 7 | 1. Disable multiple messages if more than 5 commits are pushed. Instead announce the last commit with "(+## more commits...)" appended to the note. 8 | 9 | 10 | Developer Notes 11 | --------------- 12 | 13 | data 14 | - no_spam 15 | - project - Optional project name, defaults to the Repository name. 16 | - address - Optional CIA address, defaults to http://cia.vc 17 | - branch - Optional branch template, use %s to include the real branch name 18 | 19 | payload 20 | - refer to docs/github_payload 21 | -------------------------------------------------------------------------------- /docs/talker: -------------------------------------------------------------------------------- 1 | Talker 2 | ======== 3 | 4 | Install Notes 5 | ------------- 6 | 7 | 1. url should be your room url, for example https://youraccount.talkerapp.com/rooms/ROOM_ID 8 | 2. token should be on your settings page 9 | 3. if digest is checked, all commits will be compressed in one message 10 | 11 | Note: replace https with http on the url if you're on the Free plan as it doesn't include enhanced security (SSL). 12 | 13 | Developer Notes 14 | --------------- 15 | 16 | data 17 | - url 18 | - token 19 | - digest (boolean) 20 | 21 | payload 22 | - refer to docs/github_payload -------------------------------------------------------------------------------- /test/planbox_test.rb: -------------------------------------------------------------------------------- 1 | require File.expand_path('../helper', __FILE__) 2 | 3 | class PlanboxTest < Service::TestCase 4 | def setup 5 | @stubs = Faraday::Adapter::Test::Stubs.new 6 | end 7 | 8 | def test_push 9 | @stubs.post "/api/github_commits" do |env| 10 | assert_equal 'www.planbox.com', env[:url].host 11 | assert_match 'payload=%7B%22a%22%3A1%7D', env[:body] 12 | [200, {}, ''] 13 | end 14 | 15 | svc = service({}, :a => 1) 16 | svc.receive_push 17 | end 18 | 19 | def service(*args) 20 | super Service::Planbox, *args 21 | end 22 | end 23 | 24 | -------------------------------------------------------------------------------- /test/commitify_test.rb: -------------------------------------------------------------------------------- 1 | require File.expand_path('../helper', __FILE__) 2 | 3 | class CommitifyTest < Service::TestCase 4 | def setup 5 | @stubs = Faraday::Adapter::Test::Stubs.new 6 | end 7 | 8 | def test_push 9 | svc = service({'private_key' => 'abc'}, 'a' => 1) 10 | 11 | @stubs.post "/commit" do |env| 12 | assert_match "key=abc", env[:body] 13 | [200, {}, ''] 14 | end 15 | 16 | svc.receive_push 17 | 18 | @stubs.verify_stubbed_calls 19 | end 20 | 21 | def service(*args) 22 | super Service::Commitify, *args 23 | end 24 | end 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /test/friend_feed_test.rb: -------------------------------------------------------------------------------- 1 | require File.expand_path('../helper', __FILE__) 2 | 3 | class FriendFeedTest < Service::TestCase 4 | def setup 5 | @stubs = Faraday::Adapter::Test::Stubs.new 6 | end 7 | 8 | def test_push 9 | svc = service({'nickname' => 'n', 'remotekey' => 'r'}, payload) 10 | 11 | @stubs.post "/api/share" do |env| 12 | assert_equal basic_auth(:n, :r), env[:request_headers][:authorization] 13 | [200, {}, ''] 14 | end 15 | 16 | svc.receive_push 17 | end 18 | 19 | def service(*args) 20 | super Service::FriendFeed, *args 21 | end 22 | end 23 | 24 | -------------------------------------------------------------------------------- /docs/co_op: -------------------------------------------------------------------------------- 1 | Co-op 2 | ======== 3 | 4 | Install Notes 5 | ------------- 6 | 7 | 1. group_id is in the URL for your group, for example if your URL is "http://coopapp.com/groups/1066", your group_id is 1066 8 | 9 | 2. token is your API token. You can find this token in the group management panel as the group administrator, eg: "http://coopapp.com/groups/1066/edit" 10 | 11 | 3. Commit messages show up as being from Cobot, the Co-op message robot 12 | 13 | 14 | Developer Notes 15 | --------------- 16 | 17 | data 18 | - group_id 19 | - token 20 | 21 | payload 22 | - refer to docs/github_payload 23 | -------------------------------------------------------------------------------- /docs/acunote: -------------------------------------------------------------------------------- 1 | Acunote 2 | ======= 3 | 4 | Acunote is an online project management and Scrum software. Integrating it with GitHub lets you see commits in the Timeline, perform code review on commits and create code inspection tasks. See http://www.acunote.com/ for more information. 5 | 6 | 7 | Install Notes 8 | ------------- 9 | 10 | 1. Token - GitHub Service Hook Token for your Acunote organization. Get it from "Edit Organization" > "Repositories" page in Acunote. 11 | 12 | 13 | Developer Notes 14 | --------------- 15 | 16 | data 17 | - token 18 | 19 | payload 20 | - refer to docs/github_payload 21 | -------------------------------------------------------------------------------- /services/mantis_bt.rb: -------------------------------------------------------------------------------- 1 | class Service::MantisBT < Service 2 | string :url, :api_key 3 | 4 | def receive_push 5 | http.ssl[:verify] = false 6 | http.url_prefix = data['url'] 7 | res = http_post 'plugin.php', :payload => payload.to_json do |req| 8 | req.params.update \ 9 | :page => "Source/checkin", 10 | :api_key => data['api_key'] 11 | end 12 | 13 | if res.status < 200 || res.status > 299 14 | raise_config_error 15 | end 16 | rescue Faraday::Error::ConnectionFailed 17 | raise_config_error "Connection refused. Invalid server URL." 18 | end 19 | end 20 | -------------------------------------------------------------------------------- /test/masterbranch_test.rb: -------------------------------------------------------------------------------- 1 | require File.expand_path('../helper', __FILE__) 2 | 3 | class MasterbranchTest < Service::TestCase 4 | def setup 5 | @stubs = Faraday::Adapter::Test::Stubs.new 6 | end 7 | 8 | def test_push 9 | @stubs.post "/gh-hook" do |env| 10 | assert_equal 'webhooks.masterbranch.com', env[:url].host 11 | assert_match 'payload=%7B%22a%22%3A1%7D', env[:body] 12 | [200, {}, ''] 13 | end 14 | 15 | svc = service({}, :a => 1) 16 | svc.receive_push 17 | end 18 | 19 | def service(*args) 20 | super Service::Masterbranch, *args 21 | end 22 | end 23 | 24 | -------------------------------------------------------------------------------- /test/sourcemint_test.rb: -------------------------------------------------------------------------------- 1 | require File.expand_path('../helper', __FILE__) 2 | 3 | class SourcemintTest < Service::TestCase 4 | def setup 5 | @stubs = Faraday::Adapter::Test::Stubs.new 6 | end 7 | 8 | def test_push 9 | url = "/actions/post-commit" 10 | @stubs.post url do |env| 11 | assert_equal 'api.sourcemint.com', env[:url].host 12 | assert_equal "payload=%22payload%22", env[:body] 13 | [200, {}, ''] 14 | end 15 | 16 | svc = service :push, {}, 'payload' 17 | svc.receive 18 | end 19 | 20 | def service(*args) 21 | super Service::Sourcemint, *args 22 | end 23 | end 24 | 25 | -------------------------------------------------------------------------------- /test/prowl_test.rb: -------------------------------------------------------------------------------- 1 | require File.expand_path('../helper', __FILE__) 2 | 3 | class ProwlTest < Service::TestCase 4 | def setup 5 | @stubs = Faraday::Adapter::Test::Stubs.new 6 | end 7 | 8 | def test_push 9 | @stubs.post "/publicapi/add" do |env| 10 | assert_equal 'api.prowlapp.com', env[:url].host 11 | data = Rack::Utils.parse_query(env[:body]) 12 | assert_equal 'a', data['apikey'] 13 | [200, {}, ''] 14 | end 15 | 16 | svc = service({'apikey' => 'a'}, payload) 17 | svc.receive_push 18 | end 19 | 20 | def service(*args) 21 | super Service::Prowl, *args 22 | end 23 | end 24 | 25 | -------------------------------------------------------------------------------- /test/rdocinfo_test.rb: -------------------------------------------------------------------------------- 1 | require File.expand_path('../helper', __FILE__) 2 | 3 | class RDocInfoTest < Service::TestCase 4 | def setup 5 | @stubs = Faraday::Adapter::Test::Stubs.new 6 | end 7 | 8 | def test_push 9 | @stubs.post "/checkout" do |env| 10 | assert_equal 'rubydoc.info', env[:url].host 11 | data = Rack::Utils.parse_query(env[:body]) 12 | assert_equal 1, JSON.parse(data['payload'])['a'] 13 | [200, {}, ''] 14 | end 15 | 16 | svc = service({}, :a => 1) 17 | svc.receive_push 18 | end 19 | 20 | def service(*args) 21 | super Service::RDocInfo, *args 22 | end 23 | end 24 | 25 | -------------------------------------------------------------------------------- /script/deliver_payload: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | $LOAD_PATH.unshift *Dir["#{File.dirname(__FILE__)}/../vendor/**/lib"] 4 | 5 | require "json" 6 | 7 | unless ARGV[0] 8 | puts "Usage: ./script/deliver_payload [service-name]" 9 | exit 1 10 | end 11 | 12 | payload_file = File.new("docs/github_payload") 13 | hash = eval(payload_file.read) 14 | 15 | data_json = JSON.generate(hash["data"]) 16 | payload_json = JSON.generate(hash["payload"]) 17 | 18 | File.open( "docs/payload_data", 'w' ) { |f| f.write( "data=#{data_json}&payload=#{payload_json}" ) } 19 | exec "curl --data-binary @docs/payload_data http://localhost:8080/#{ARGV[0]}/push" 20 | -------------------------------------------------------------------------------- /docs/run_code_run: -------------------------------------------------------------------------------- 1 | RunCodeRun 2 | ========== 3 | 4 | RunCodeRun is a hosted continuous integration service. It is free for public 5 | projects. For private project plans, see http://runcoderun.com/plans. 6 | 7 | Install Notes 8 | ------------- 9 | 10 | 1. Check the "Active" checkbox and click "Update Settings". 11 | 2. Click on the "RunCodeRun" service name and then click the "Test Hook" link. 12 | 3. You should receive an email from RunCodeRun letting you know your 13 | project was setup. 14 | 4. If this is a private project, add the rcr-private user as a collaborator. 15 | 16 | For more details, go to http://runcoderun.com/github 17 | -------------------------------------------------------------------------------- /test/geocommit_test.rb: -------------------------------------------------------------------------------- 1 | require File.expand_path('../helper', __FILE__) 2 | 3 | class GeoCommitTest < Service::TestCase 4 | def setup 5 | @stubs = Faraday::Adapter::Test::Stubs.new 6 | end 7 | 8 | def test_push 9 | svc = service({}, 'a' => 1) 10 | 11 | @stubs.post "/api/github" do |env| 12 | assert_equal 'application/githubpostreceive+json', 13 | env[:request_headers]['Content-Type'] 14 | assert_equal 1, JSON.parse(env[:body])['a'] 15 | [200, {}, ''] 16 | end 17 | 18 | svc.receive_push 19 | end 20 | 21 | def service(*args) 22 | super Service::GeoCommit, *args 23 | end 24 | end 25 | 26 | -------------------------------------------------------------------------------- /test/kickoff_test.rb: -------------------------------------------------------------------------------- 1 | require File.expand_path('../helper', __FILE__) 2 | 3 | class KickoffTest < Service::TestCase 4 | def setup 5 | @stubs = Faraday::Adapter::Test::Stubs.new 6 | end 7 | 8 | def test_push 9 | @stubs.post "/projects/a/chat" do |env| 10 | assert_equal 'api.kickoffapp.com', env[:url].host 11 | assert_equal 'token=b', env[:url].query 12 | [200, {}, ''] 13 | end 14 | 15 | svc = service( 16 | {'project_id' => 'a', 'project_token' => 'b' }, 17 | payload) 18 | svc.receive_push 19 | end 20 | 21 | def service(*args) 22 | super Service::Kickoff, *args 23 | end 24 | end 25 | 26 | -------------------------------------------------------------------------------- /test/notifymyandroid_test.rb: -------------------------------------------------------------------------------- 1 | require File.expand_path('../helper', __FILE__) 2 | 3 | class NMATest < Service::TestCase 4 | def setup 5 | @stubs = Faraday::Adapter::Test::Stubs.new 6 | end 7 | 8 | def test_push 9 | @stubs.post "/publicapi/notify" do |env| 10 | assert_equal 'www.notifymyandroid.com', env[:url].host 11 | data = Rack::Utils.parse_query(env[:body]) 12 | assert_equal 'a', data['apikey'] 13 | [200, {}, ''] 14 | end 15 | 16 | svc = service({'apikey' => 'a'}, payload) 17 | svc.receive_push 18 | end 19 | 20 | def service(*args) 21 | super Service::NMA, *args 22 | end 23 | end 24 | 25 | -------------------------------------------------------------------------------- /test/read_the_docs_test.rb: -------------------------------------------------------------------------------- 1 | require File.expand_path('../helper', __FILE__) 2 | 3 | class ReadTheDocsTest < Service::TestCase 4 | def setup 5 | @stubs = Faraday::Adapter::Test::Stubs.new 6 | end 7 | 8 | def test_push 9 | @stubs.post "/github" do |env| 10 | assert_equal 'readthedocs.org', env[:url].host 11 | data = Rack::Utils.parse_query(env[:body]) 12 | assert_equal 1, JSON.parse(data['payload'])['a'] 13 | [200, {}, ''] 14 | end 15 | 16 | svc = service({}, :a => 1) 17 | svc.receive_push 18 | end 19 | 20 | def service(*args) 21 | super Service::ReadTheDocs, *args 22 | end 23 | end 24 | 25 | -------------------------------------------------------------------------------- /test/get_localization_test.rb: -------------------------------------------------------------------------------- 1 | require File.expand_path('../helper', __FILE__) 2 | 3 | class GetLocalizationTest < Service::TestCase 4 | def setup 5 | @stubs = Faraday::Adapter::Test::Stubs.new 6 | end 7 | 8 | def test_push 9 | svc = service({ 10 | 'project_name' => 'n', 11 | 'project_token' => 't'}, 'a' => 1) 12 | 13 | @stubs.post "/services/github/notify/n/t/" do |env| 14 | assert_match /payload=%7B%22a%22%3A1%7D($|\&)/, env[:body] 15 | [200, {}, ''] 16 | end 17 | 18 | svc.receive_push 19 | end 20 | 21 | def service(*args) 22 | super Service::GetLocalization, *args 23 | end 24 | end 25 | 26 | -------------------------------------------------------------------------------- /docs/boxcar: -------------------------------------------------------------------------------- 1 | Boxcar 2 | ========== 3 | 4 | Send your commits to Boxcar, a messaging platform. Get instant commit messages on your desktop and mobile devices. 5 | 6 | Install Notes 7 | ------------- 8 | 9 | 1. Download and install Boxcar from http://boxcar.io 10 | 2. Type in the Boxcar e-mail addresses of the users wanting to be notified of commits to this repository. 11 | 3. If the user does not yet have Boxcar, we'll send them an e-mail to let them know where they can get it. 12 | 13 | 14 | Developer Notes 15 | --------------- 16 | 17 | data 18 | - subscribers (csv list of e-mail addresses) 19 | 20 | payload 21 | - refer to docs/github_payload 22 | -------------------------------------------------------------------------------- /test/continuity_app_test.rb: -------------------------------------------------------------------------------- 1 | require File.expand_path('../helper', __FILE__) 2 | 3 | class ContinuityAppTest < Service::TestCase 4 | def setup 5 | @stubs = Faraday::Adapter::Test::Stubs.new 6 | end 7 | 8 | def test_push 9 | svc = service({'project_id' => '55'}, 'a' => 1) 10 | 11 | @stubs.post "/github_selfservice/v1/55" do |env| 12 | assert_match /(^|\&)payload=%7B%22a%22%3A1%7D($|\&)/, env[:body] 13 | [200, {}, ''] 14 | end 15 | 16 | svc.receive_push 17 | 18 | @stubs.verify_stubbed_calls 19 | end 20 | 21 | def service(*args) 22 | super Service::ContinuityApp, *args 23 | end 24 | end 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /services/friend_feed.rb: -------------------------------------------------------------------------------- 1 | class Service::FriendFeed < Service 2 | string :nickname, :remotekey 3 | 4 | def receive_push 5 | repository = payload['repository']['name'] 6 | friendfeed_url = "http://friendfeed.com/api/share" 7 | 8 | payload['commits'].each do |commit| 9 | title = "#{commit['author']['name']} just committed a change to #{repository} on GitHub" 10 | comment = "#{commit['message']} (#{commit['id']})" 11 | 12 | http.basic_auth data['nickname'], data['remotekey'] 13 | http_post friendfeed_url, 14 | :title => title, :link => commit['url'], :comment => comment, :via => :github 15 | end 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /docs/cube: -------------------------------------------------------------------------------- 1 | Cube 2 | ========== 3 | 4 | Cube is a timetracking app for individuals or companies; for more details see http://cube.bitrzr.com 5 | This service lets your broadcast commits on Cube so they can be seen in the unified project log. 6 | 7 | Install Notes 8 | ------------- 9 | 10 | 1. domain (company domain for Google Apps account or user email address for individual accounts) 11 | 2. project (project name) 12 | 3. token (project integration token as seen in the project's Settings tab) 13 | 14 | Developer Notes 15 | --------------- 16 | 17 | data 18 | - domain 19 | - project 20 | - token 21 | 22 | payload 23 | - refer to docs/github_payload 24 | -------------------------------------------------------------------------------- /test/ontime_test.rb: -------------------------------------------------------------------------------- 1 | require 'cgi' 2 | 3 | class OnTimeTest < Service::TestCase 4 | def setup 5 | @stubs = Faraday::Adapter::Test::Stubs.new 6 | end 7 | 8 | def test_push 9 | @stubs.get "/api/version" do |env| 10 | assert_equal 'www.example.com', env[:url].host 11 | [200, {}, '{"data":{"major":12,"minor":0,"build":2}}'] 12 | end 13 | 14 | @stubs.post "/api/github" do |env| 15 | [200, {}, ''] 16 | end 17 | 18 | svc = service({'ontime_url' => 'http://www.example.com/', 'api_key' => 'test_api_key'}, payload) 19 | svc.receive_push 20 | end 21 | 22 | def service(*args) 23 | super Service::OnTime, *args 24 | end 25 | end 26 | -------------------------------------------------------------------------------- /docs/trac: -------------------------------------------------------------------------------- 1 | Trac 2 | ==== 3 | 4 | Install the following plugin on your Trac server before proceeding: http://github.com/davglass/github-trac/ 5 | 6 | 1. url field is your Trac install's url 7 | 2. token (this needs to be the same token you put in your trac.ini installed via the plugin) 8 | 9 | 10 | The plugin searches commit messages for text in the form of: 11 | command #1 12 | command #1, #2 13 | command #1 & #2 14 | command #1 and #2 15 | 16 | Instead of the short-hand syntax "#1", "ticket:1" can be used as well, e.g.: 17 | command ticket:1 18 | command ticket:1, ticket:2 19 | command ticket:1 & ticket:2 20 | command ticket:1 and ticket:2 21 | -------------------------------------------------------------------------------- /test/lighthouse_test.rb: -------------------------------------------------------------------------------- 1 | require File.expand_path('../helper', __FILE__) 2 | 3 | class LighthouseTest < Service::TestCase 4 | def setup 5 | @stubs = Faraday::Adapter::Test::Stubs.new 6 | end 7 | 8 | def test_push 9 | @stubs.post "/projects/1/changesets.xml" do |env| 10 | assert_equal 'application/xml', env[:request_headers]['Content-Type'] 11 | assert_equal 's.lighthouseapp.com', env[:url].host 12 | [200, {}, ''] 13 | end 14 | 15 | svc = service( 16 | {'subdomain' => 's', 'project_id' => '1'}, payload) 17 | svc.receive_push 18 | end 19 | 20 | def service(*args) 21 | super Service::Lighthouse, *args 22 | end 23 | end 24 | 25 | -------------------------------------------------------------------------------- /services/pachube.rb: -------------------------------------------------------------------------------- 1 | class Service::Pachube < Service 2 | string :api_key 3 | string :feed_id 4 | 5 | def receive_push 6 | raise_config_error "Missing api_key" if data['api_key'].to_s.empty? 7 | raise_config_error "Missing feed_id" if data['feed_id'].to_s.empty? 8 | 9 | http_method :put, "https://api.pachube.com/v2/feeds/#{data['feed_id']}.json" do |req| 10 | req.headers['X-PachubeApiKey'] = data['api_key'] 11 | req.body = { 12 | :version => '1.0.0', 13 | :datastreams => [ 14 | { 15 | :id => repo_name, 16 | :current_value => distinct_commits.size 17 | } 18 | ]}.to_json 19 | end 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /test/hip_chat_test.rb: -------------------------------------------------------------------------------- 1 | require File.expand_path('../helper', __FILE__) 2 | 3 | class HipChatTest < Service::TestCase 4 | def setup 5 | @stubs = Faraday::Adapter::Test::Stubs.new 6 | end 7 | 8 | def test_push 9 | @stubs.post "/v1/webhooks/github" do |env| 10 | assert_match /(^|\&)payload=%7B%22a%22%3A1%7D($|\&)/, env[:body] 11 | assert_match "auth_token=a", env[:body] 12 | assert_match "room_id=r", env[:body] 13 | [200, {}, ''] 14 | end 15 | 16 | svc = service( 17 | {'auth_token' => 'a', 'room' => 'r'}, 'a' => 1) 18 | svc.receive_event 19 | end 20 | 21 | def service(*args) 22 | super Service::HipChat, *args 23 | end 24 | end 25 | 26 | -------------------------------------------------------------------------------- /test/presently_test.rb: -------------------------------------------------------------------------------- 1 | require File.expand_path('../helper', __FILE__) 2 | 3 | class PresentlyTest < Service::TestCase 4 | def setup 5 | @stubs = Faraday::Adapter::Test::Stubs.new 6 | end 7 | 8 | def test_push 9 | @stubs.post "/api/twitter/statuses/update.xml" do |env| 10 | assert_equal 's.presently.com', env[:url].host 11 | assert_equal basic_auth(:u, :p), env[:request_headers]['authorization'] 12 | [200, {}, ''] 13 | end 14 | 15 | svc = service({'subdomain' => 's', 16 | 'username' => 'u', 'password' => 'p'}, payload) 17 | svc.receive_push 18 | end 19 | 20 | def service(*args) 21 | super Service::Presently, *args 22 | end 23 | end 24 | 25 | -------------------------------------------------------------------------------- /test/web_translate_it_test.rb: -------------------------------------------------------------------------------- 1 | require File.expand_path('../helper', __FILE__) 2 | 3 | class WebTranslateItTest < Service::TestCase 4 | def setup 5 | @stubs = Faraday::Adapter::Test::Stubs.new 6 | end 7 | 8 | def test_push 9 | @stubs.post "/api/projects/a/refresh_files" do |env| 10 | assert_equal 'webtranslateit.com', env[:url].host 11 | data = Rack::Utils.parse_nested_query(env[:body]) 12 | assert_equal 1, JSON.parse(data['payload'])['a'] 13 | [200, {}, ''] 14 | end 15 | 16 | svc = service({'api_key' => 'a'}, :a => 1) 17 | svc.receive_push 18 | end 19 | 20 | def service(*args) 21 | super Service::WebTranslateIt, *args 22 | end 23 | end 24 | 25 | -------------------------------------------------------------------------------- /docs/lighthouse: -------------------------------------------------------------------------------- 1 | Lighthouse 2 | ======== 3 | 4 | Install Notes 5 | ------------- 6 | 7 | Using the following url as an example: 8 | http://logicalawesome.lighthouseapp.com/projects/8570-github/overview 9 | 10 | 1. subdomain is logicalawesome 11 | 2. project_id is 8570 12 | 3. this service only supports project tokens 13 | (accepting patches for user-based tokens) 14 | 4. 'private' determines whether changed files 15 | should be displayed (useful for public LH 16 | accounts and private GH repos) 17 | 18 | 19 | Developer Notes 20 | --------------- 21 | 22 | data 23 | - subdomain 24 | - project_id 25 | - token 26 | - private 27 | 28 | payload 29 | - refer to docs/github_payload 30 | -------------------------------------------------------------------------------- /docs/socialcast: -------------------------------------------------------------------------------- 1 | Socialcast 2 | ========== 3 | 4 | Install Notes 5 | ------------- 6 | 7 | You should already have a Socialcast community. For the group_id you'll need to call the 8 | API to figure out the underlying integer group id for a group. 9 | 10 | 11 | 1. api_domain (e.g. foo-com.socialcast.com) 12 | 2. username (user to post message on behalf of) 13 | 3. password (password of user to post message on behalf of) 14 | 4. group_id (OPTIONAL Id of a Socialcast group to post the message into) 15 | 16 | Developer Notes 17 | --------------- 18 | 19 | data 20 | - api_domain 21 | - username 22 | - password 23 | - group_id (optional) 24 | 25 | payload 26 | - refer to docs/github_payload 27 | -------------------------------------------------------------------------------- /services/jaconda.rb: -------------------------------------------------------------------------------- 1 | class Service::Jaconda < Service 2 | string :subdomain, :room_id, :room_token 3 | boolean :digest 4 | 5 | def receive_push 6 | raise_config_error "Missing 'subdomain'" if data['subdomain'].to_s == '' 7 | raise_config_error "Missing 'room_id'" if data['room_id'].to_s == '' 8 | 9 | http.basic_auth data['room_token'], 'X' 10 | 11 | res = http_post "https://#{data['subdomain']}.jaconda.im/api/v2/rooms/#{data['room_id']}/notify/github.json", 12 | :payload => JSON.generate(payload), 13 | :digest => data['digest'] 14 | 15 | if res.status < 200 || res.status > 299 16 | raise_config_error "#{res.status}: #{res.body}" 17 | end 18 | end 19 | end 20 | -------------------------------------------------------------------------------- /test/splendid_bacon_test.rb: -------------------------------------------------------------------------------- 1 | require File.expand_path('../helper', __FILE__) 2 | 3 | class SplendidBaconTest < Service::TestCase 4 | def setup 5 | @stubs = Faraday::Adapter::Test::Stubs.new 6 | end 7 | 8 | def test_push 9 | @stubs.post "/api/v1/projects/p/github" do |env| 10 | assert_equal 'splendidbacon.com', env[:url].host 11 | data = Rack::Utils.parse_nested_query(env[:body]) 12 | assert_equal 1, JSON.parse(data['payload'])['a'] 13 | [200, {}, ''] 14 | end 15 | 16 | svc = service({'token' => 't', 'project_id' => 'p'}, :a => 1) 17 | svc.receive_push 18 | end 19 | 20 | def service(*args) 21 | super Service::SplendidBacon, *args 22 | end 23 | end 24 | 25 | -------------------------------------------------------------------------------- /docs/notifymyandroid: -------------------------------------------------------------------------------- 1 | Notify My Android 2 | ========== 3 | 4 | With NotifyMyAndroid (NMA) you can push notifications to your Android devices 5 | through Google's C2DM notification system. The [public Web API](http://www.notifymyandroid.com/api.php) 6 | can be used by virtually any application to delivery push notifications to 7 | your Android. 8 | 9 | Install Notes 10 | ------------- 11 | 12 | 1. Register at https://www.notifymyandroid.com/register.php. 13 | 14 | 2. Generate an API key at https://www.notifymyandroid.com/account.php to be used on GitHub. 15 | 16 | Developer Notes 17 | --------------- 18 | 19 | apikey 20 | - Your NMA API Key, or a CSV list of API Keys. 21 | 22 | payload 23 | - refer to docs/github_payload 24 | -------------------------------------------------------------------------------- /test/boxcar_test.rb: -------------------------------------------------------------------------------- 1 | require File.expand_path('../helper', __FILE__) 2 | 3 | class BoxcarTest < Service::TestCase 4 | def setup 5 | @stubs = Faraday::Adapter::Test::Stubs.new 6 | end 7 | 8 | def test_push 9 | svc = service :push, {'subscribers' => 'abc'}, 'a' => 1 10 | svc.secrets = {'boxcar' => {'apikey' => 'key'}} 11 | 12 | @stubs.post "/github/key" do |env| 13 | assert_match /(^|\&)emails=abc($|\&)/, env[:body] 14 | assert_match /(^|\&)payload=%7B%22a%22%3A1%7D($|\&)/, env[:body] 15 | [200, {}, ''] 16 | end 17 | 18 | svc.receive 19 | 20 | @stubs.verify_stubbed_calls 21 | end 22 | 23 | def service(*args) 24 | super Service::Boxcar, *args 25 | end 26 | end 27 | 28 | -------------------------------------------------------------------------------- /test/rubyforge_test.rb: -------------------------------------------------------------------------------- 1 | require File.expand_path('../helper', __FILE__) 2 | 3 | class RubyforgeTest < Service::TestCase 4 | def setup 5 | @stubs = Faraday::Adapter::Test::Stubs.new 6 | end 7 | 8 | def test_push 9 | svc = service({'groupid' => 'g'}, payload) 10 | def svc.news 11 | @news ||= [] 12 | end 13 | 14 | def svc.post_news(*args) 15 | news << args 16 | end 17 | 18 | svc.receive_push 19 | assert news = svc.news.shift 20 | assert_equal 'g', news[0] 21 | assert_match '06f63b43050935962f84fe54473a7c5de7977325', news[1] 22 | assert_match 'stub git call', news[2] 23 | end 24 | 25 | def service(*args) 26 | super Service::Rubyforge, *args 27 | end 28 | end 29 | 30 | -------------------------------------------------------------------------------- /test/jira_test.rb: -------------------------------------------------------------------------------- 1 | require File.expand_path('../helper', __FILE__) 2 | 3 | class JiraTest < Service::TestCase 4 | def setup 5 | @stubs = Faraday::Adapter::Test::Stubs.new 6 | end 7 | 8 | def test_push 9 | @stubs.post "/a/rest/api/a/issue/1/transitions" do |env| 10 | assert_equal 'application/json', env[:request_headers]['Content-Type'] 11 | assert_equal 'foo.com', env[:url].host 12 | [200, {}, ''] 13 | end 14 | 15 | svc = service( 16 | {'server_url' => 'http://foo.com/a', 'username' => 'u', 'password' => 'p', 17 | 'api_version' => 'a'}, 18 | payload) 19 | svc.receive_push 20 | end 21 | 22 | def service(*args) 23 | super Service::Jira, *args 24 | end 25 | end 26 | 27 | -------------------------------------------------------------------------------- /vendor/internal-gems/yammer4r-0.1.5/lib/ext/core_ext.rb: -------------------------------------------------------------------------------- 1 | class String 2 | def to_boolean 3 | case self 4 | when 'true' 5 | true 6 | when 'false' 7 | false 8 | else 9 | nil 10 | end 11 | end 12 | end 13 | 14 | class Hash 15 | def symbolize_keys 16 | inject({}) do |options, (key, value)| 17 | options[(key.to_sym rescue key) || key] = value 18 | options 19 | end 20 | end 21 | 22 | def symbolize_keys! 23 | self.replace(self.symbolize_keys) 24 | end 25 | 26 | def assert_has_keys(*valid_keys) 27 | missing_keys = [valid_keys].flatten - keys 28 | raise(ArgumentError, "Missing Option(s): #{missing_keys.join(", ")}") unless missing_keys.empty? 29 | end 30 | end 31 | -------------------------------------------------------------------------------- /services/grmble.rb: -------------------------------------------------------------------------------- 1 | class Service::Grmble < Service 2 | string :room_api_url, :token 3 | 4 | def receive_push 5 | http.url_prefix = data['room_api_url'].to_s 6 | repository = payload[ 'repository' ][ 'name' ] 7 | branch = branch_name 8 | commits = payload[ 'commits' ] 9 | 10 | commits.each do |commit| 11 | message = { 12 | 'nickname' => 'github', 13 | 'content' => "[#{repository}/#{branch}] #{commit['message']} - #{commit['author']['name']} #{commit['url']}", 14 | 'apiKey' => data[ 'token' ], 15 | 'type' => 'message', 16 | } 17 | 18 | http_post 'msg', :message => JSON.generate(message) 19 | end 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /test/bugly_test.rb: -------------------------------------------------------------------------------- 1 | require File.expand_path('../helper', __FILE__) 2 | 3 | class BuglyTest < Service::TestCase 4 | def setup 5 | @stubs = Faraday::Adapter::Test::Stubs.new 6 | end 7 | 8 | def test_push 9 | svc = service :push, {'token' => 'abc'}, 'a' => 1 10 | 11 | @stubs.post "/changesets.json" do |env| 12 | assert_equal %({"a":1}), env[:body] 13 | assert_equal 'abc', env[:request_headers]['X-BuglyToken'] 14 | assert_equal 'application/json', env[:request_headers]['Content-Type'] 15 | [200, {}, ''] 16 | end 17 | 18 | svc.receive 19 | 20 | @stubs.verify_stubbed_calls 21 | end 22 | 23 | def service(*args) 24 | super Service::Bugly, *args 25 | end 26 | end 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /docs/appharbor: -------------------------------------------------------------------------------- 1 | AppHarbor 2 | ======= 3 | 4 | AppHarbor is a .NET Platform as a Service. Use this service to automatically trigger build, test run and deployment of your AppHarbor application when you push to GitHub. 5 | 6 | Install Notes 7 | ------------- 8 | 9 | 1. Go to your application's main page on AppHarbor and find the "Create build URL". Example: https://appharbor.com/application/{application_slug}/build?authorization={token} 10 | 11 | 2. "token" is the value of the "authorization" parameter. 12 | 13 | 3. "application_slug" is your application's unique identifier. 14 | 15 | 4. If your GitHub repository is private you need to add the "apphb" GitHub user as a collaborator. This enables AppHarbor to download the source code. 16 | -------------------------------------------------------------------------------- /test/statusnet_test.rb: -------------------------------------------------------------------------------- 1 | require File.expand_path('../helper', __FILE__) 2 | 3 | class StatusNetTest < Service::TestCase 4 | def setup 5 | @stubs = Faraday::Adapter::Test::Stubs.new 6 | end 7 | 8 | def test_push 9 | @stubs.post "/api/statuses/update.xml" do |env| 10 | assert_equal 's.com', env[:url].host 11 | data = Rack::Utils.parse_nested_query(env[:body]) 12 | assert_equal 'github', data['source'] 13 | [200, {}, ''] 14 | end 15 | 16 | svc = service({'server' => 'http://s.com'}, payload) 17 | 18 | def svc.shorten_url(*args) 19 | 'short' 20 | end 21 | 22 | svc.receive_push 23 | end 24 | 25 | def service(*args) 26 | super Service::StatusNet, *args 27 | end 28 | end 29 | 30 | -------------------------------------------------------------------------------- /docs/prowl: -------------------------------------------------------------------------------- 1 | Prowl 2 | ========== 3 | 4 | Prowl is an iPhone App+Web Service for arbitrary Push Notifications. After installing the app and registering the device, you receive an API key and can send notifications from your computer via Growl (with the Prowl GrowlStyle installed) or from any server with very little work (at least as far as the Push submission is concerned). 5 | 6 | To get started, create a user account for Prowl at https://www.prowlapp.com/. 7 | 8 | Install Notes 9 | ------------- 10 | 11 | 1. Create a new API key for GitHub at the Prowl website https://www.prowlapp.com/api_settings.php. 12 | 13 | Developer Notes 14 | --------------- 15 | 16 | apikey 17 | - Your Prowl API key. 18 | 19 | payload 20 | - refer to docs/github_payload 21 | -------------------------------------------------------------------------------- /test/redmine_test.rb: -------------------------------------------------------------------------------- 1 | require File.expand_path('../helper', __FILE__) 2 | 3 | class RedmineTest < Service::TestCase 4 | def setup 5 | @stubs = Faraday::Adapter::Test::Stubs.new 6 | end 7 | 8 | def test_push 9 | @stubs.get "/a/sys/fetch_changesets" do |env| 10 | assert_equal 'r.com', env[:url].host 11 | data = Rack::Utils.parse_nested_query(env[:body]) 12 | assert_equal 'a', env[:params]['key'] 13 | assert_equal 'p', env[:params]['id'] 14 | [200, {}, ''] 15 | end 16 | 17 | svc = service({'address' => 'http://r.com/a/', 18 | 'api_key' => 'a', 'project' => 'p'}, :a => 1) 19 | svc.receive_push 20 | end 21 | 22 | def service(*args) 23 | super Service::Redmine, *args 24 | end 25 | end 26 | 27 | -------------------------------------------------------------------------------- /test/talker_test.rb: -------------------------------------------------------------------------------- 1 | require File.expand_path('../helper', __FILE__) 2 | 3 | class TalkerTest < Service::TestCase 4 | def setup 5 | @stubs = Faraday::Adapter::Test::Stubs.new 6 | end 7 | 8 | def test_push 9 | @stubs.post "/room/1/messages.json" do |env| 10 | assert_equal 's.talkerapp.com', env[:url].host 11 | assert_equal 't', env[:request_headers]['x-talker-token'] 12 | data = Rack::Utils.parse_nested_query(env[:body]) 13 | assert data.key?('message') 14 | [200, {}, ''] 15 | end 16 | 17 | svc = service({'url' => 'https://s.talkerapp.com/room/1', 'token' => 't'}, payload) 18 | svc.receive_push 19 | end 20 | 21 | def service(*args) 22 | super Service::Talker, *args 23 | end 24 | end 25 | 26 | -------------------------------------------------------------------------------- /test/yammer_test.rb: -------------------------------------------------------------------------------- 1 | require File.expand_path('../helper', __FILE__) 2 | 3 | class YammerTest < Service::TestCase 4 | def setup 5 | @stubs = Faraday::Adapter::Test::Stubs.new 6 | end 7 | 8 | def test_push 9 | svc = service({'group_id' => 'g'}, payload) 10 | 11 | def svc.messages 12 | @messages ||= [] 13 | end 14 | 15 | def svc.send_message(params) 16 | messages << params 17 | end 18 | 19 | def svc.shorten_url(*args) 20 | 'short' 21 | end 22 | 23 | svc.receive_push 24 | 25 | assert_equal 3, svc.messages.size 26 | assert_equal %w(g g g), svc.messages.map { |m| m['group_id'] } 27 | end 28 | 29 | def service(*args) 30 | super Service::Yammer, *args 31 | end 32 | end 33 | 34 | 35 | -------------------------------------------------------------------------------- /test/trac_test.rb: -------------------------------------------------------------------------------- 1 | require File.expand_path('../helper', __FILE__) 2 | 3 | class TracTest < Service::TestCase 4 | def setup 5 | @stubs = Faraday::Adapter::Test::Stubs.new 6 | end 7 | 8 | def test_push 9 | @stubs.post "/s/github/t" do |env| 10 | assert_equal 's.trac.com', env[:url].host 11 | assert_equal basic_auth(:u, :p), env[:request_headers]['authorization'] 12 | data = Rack::Utils.parse_nested_query(env[:body]) 13 | assert_equal 1, JSON.parse(data['payload'])['a'] 14 | [200, {}, ''] 15 | end 16 | 17 | svc = service({'url' => 'http://u:p@s.trac.com/s', 'token' => 't'}, :a => 1) 18 | svc.receive_push 19 | end 20 | 21 | def service(*args) 22 | super Service::Trac, *args 23 | end 24 | end 25 | 26 | -------------------------------------------------------------------------------- /test/kanbanery_test.rb: -------------------------------------------------------------------------------- 1 | require File.expand_path('../helper', __FILE__) 2 | 3 | class KanbaneryTest < Service::TestCase 4 | def setup 5 | @stubs = Faraday::Adapter::Test::Stubs.new 6 | end 7 | 8 | def test_push 9 | url = '/api/v1/projects/123/git_commits' 10 | @stubs.post url do |env| 11 | assert_equal %({"a":1}), env[:body] 12 | assert_equal 'a1b2c3', env[:request_headers]['X-Kanbanery-ProjectGitHubToken'] 13 | assert_equal 'application/json', env[:request_headers]['Content-Type'] 14 | [200, {}, ''] 15 | end 16 | 17 | svc = service({'project_id' => '123', 'project_token' => 'a1b2c3'}, 'a' => 1) 18 | svc.receive_push 19 | end 20 | 21 | def service(*args) 22 | super Service::Kanbanery, *args 23 | end 24 | end 25 | -------------------------------------------------------------------------------- /test/mantis_bt_test.rb: -------------------------------------------------------------------------------- 1 | require File.expand_path('../helper', __FILE__) 2 | 3 | class MantisBTTest < Service::TestCase 4 | def setup 5 | @stubs = Faraday::Adapter::Test::Stubs.new 6 | end 7 | 8 | def test_push 9 | @stubs.post "/abc/plugin.php" do |env| 10 | assert_equal 'abc.com', env[:url].host 11 | assert_equal 'Source/checkin', env[:params]['page'] 12 | assert_equal 'key', env[:params]['api_key'] 13 | assert_match 'payload=%7B%22a%22%3A1%7D', env[:body] 14 | [200, {}, ''] 15 | end 16 | 17 | svc = service( 18 | {'url' => 'http://abc.com/abc/', 'api_key' => 'key'}, 19 | :a => 1) 20 | svc.receive_push 21 | end 22 | 23 | def service(*args) 24 | super Service::MantisBT, *args 25 | end 26 | end 27 | 28 | -------------------------------------------------------------------------------- /docs/campfire: -------------------------------------------------------------------------------- 1 | Campfire 2 | ======== 3 | 4 | Install Notes 5 | ------------- 6 | 7 | 1. subdomain is your campfire subdomain 8 | (ie 'your-subdomain' if you visit 'https://your-subdomain.campfirenow.com') 9 | 10 | 2. room is the actual room name, not the id 11 | 12 | 3. token is your API token. get it from campfire's "Edit my Campfire 13 | account" screen 14 | 15 | 4. master_only is a boolean flag indicating whether only commits to master 16 | should be announced 17 | 18 | 5. play_sound is a boolean flag indicating whether a sound should be played 19 | 20 | 21 | Developer Notes 22 | --------------- 23 | 24 | data 25 | - subdomain 26 | - token 27 | - room 28 | - master_only 29 | - play_sound 30 | 31 | payload 32 | - refer to docs/github_payload 33 | -------------------------------------------------------------------------------- /docs/twitter: -------------------------------------------------------------------------------- 1 | Twitter 2 | ======== 3 | 4 | Install Notes 5 | ------------- 6 | 7 | 1. Get an OAuth Token for Your Twitter Account from the services hooks edit page for your repo. 8 | 2. You're going to be redirected to twitter to allow GitHub to tweet on your behalf. 9 | 3. Be sure that you're logged in as the twitter user you would like to tweet from. 10 | 11 | Developer Notes 12 | --------------- 13 | 14 | data 15 | - token 16 | - secret 17 | - digest (boolean) 18 | 19 | payload 20 | - refer to docs/github_payload 21 | 22 | Deployment Notes 23 | ---------------- 24 | 25 | The secrets.yml file should include an entry for the consumer keys github needs to post for people. 26 | 27 | twitter: 28 | key: 29 | secret: 30 | -------------------------------------------------------------------------------- /test/basecamp_test.rb: -------------------------------------------------------------------------------- 1 | require File.expand_path('../helper', __FILE__) 2 | 3 | class BasecampTest < Service::TestCase 4 | def test_receives_push 5 | svc = service :push, {'url' => 'https://foo.com', 'username' => 'monkey', 'password' => 'abc'}, payload 6 | svc.receive 7 | 8 | assert msg = svc.messages.shift 9 | assert_equal 2, msg.category_id 10 | assert msg.title.present? 11 | assert msg.body.present? 12 | end 13 | 14 | def service(*args) 15 | svc = super Service::Basecamp, *args 16 | 17 | svc.project_id = 1 18 | svc.category_id = 2 19 | 20 | def svc.messages 21 | @messages ||= [] 22 | end 23 | 24 | def svc.post_message(options = {}) 25 | messages << build_message(options) 26 | end 27 | 28 | svc 29 | end 30 | end 31 | -------------------------------------------------------------------------------- /services/co_op.rb: -------------------------------------------------------------------------------- 1 | class Service::CoOp < Service 2 | string :group_id, :token 3 | 4 | self.title = 'Co-Op' 5 | 6 | def receive_push 7 | repository = payload['repository']['name'] 8 | payload['commits'].each do |commit| 9 | status = "#{commit['author']['name']} just committed a change to #{repository} on GitHub: #{commit['message']} (#{commit['url']})" 10 | res = http_post "http://coopapp.com/groups/%s/notes" % [data['group_id']], 11 | {:status => status, :key => data['token']}.to_json, 12 | 'Accept' => 'application/json', 13 | 'Content-Type' => 'application/json; charset=utf-8', 14 | 'User-Agent' => 'GitHub Notifier' 15 | 16 | if res.status >= 400 17 | raise_config_error 18 | end 19 | end 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /test/cia_test.rb: -------------------------------------------------------------------------------- 1 | require File.expand_path('../helper', __FILE__) 2 | 3 | class CIATest < Service::TestCase 4 | def setup 5 | @messages = [] 6 | @server = lambda do |method, message| 7 | @messages << [method, message] 8 | end 9 | end 10 | 11 | def test_push 12 | svc = service({'project' => 'abc', 'long_url'=>1}, payload) 13 | svc.xmlrpc_server = @server 14 | svc.receive_push 15 | 16 | assert msg = @messages.shift 17 | assert_equal 'hub.deliver', msg.first 18 | assert_match '06f63b43050935962f84fe54473a7c5de7977325', msg.last 19 | assert msg = @messages.shift 20 | assert msg = @messages.shift 21 | assert_nil @messages.shift 22 | end 23 | 24 | def service(*args) 25 | super Service::CIA, *args 26 | end 27 | end 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /test/cube_test.rb: -------------------------------------------------------------------------------- 1 | require File.expand_path('../helper', __FILE__) 2 | 3 | class CubeTest < Service::TestCase 4 | def setup 5 | @stubs = Faraday::Adapter::Test::Stubs.new 6 | end 7 | 8 | def test_push 9 | url = "/integration/events/github/create" 10 | @stubs.post url do |env| 11 | assert_match /(^|\&)payload=%7B%22a%22%3A1%7D($|\&)/, env[:body] 12 | assert_match "project_name=p", env[:body] 13 | assert_match "project_token=t", env[:body] 14 | assert_match "domain=d", env[:body] 15 | [200, {}, ''] 16 | end 17 | 18 | svc = service( 19 | {'project' => 'p', 'token' => 't', 'domain' => 'd'}, 20 | 'a' => 1) 21 | svc.receive_push 22 | end 23 | 24 | def service(*args) 25 | super Service::Cube, *args 26 | end 27 | end 28 | 29 | 30 | -------------------------------------------------------------------------------- /services/pivotal_tracker.rb: -------------------------------------------------------------------------------- 1 | class Service::PivotalTracker < Service 2 | string :token, :branch 3 | 4 | def receive_push 5 | token = data['token'] 6 | branch = data['branch'].to_s 7 | ref = payload["ref"].to_s 8 | 9 | if branch.empty? || branch == ref.split("/").last 10 | notifier.call 11 | end 12 | end 13 | 14 | attr_writer :notifier 15 | 16 | def notifier 17 | @notifier ||= Proc.new { notify } 18 | end 19 | 20 | private 21 | def notify 22 | res = http_post 'https://www.pivotaltracker.com/services/v3/github_commits' do |req| 23 | req.params[:token] = data['token'] 24 | req.body = {:payload => payload.to_json} 25 | end 26 | 27 | if res.status < 200 || res.status > 299 28 | raise_config_error 29 | end 30 | end 31 | end 32 | 33 | -------------------------------------------------------------------------------- /docs/unfuddle: -------------------------------------------------------------------------------- 1 | Unfuddle 2 | ======== 3 | 4 | Unfuddle is a lovely ticket management, time tracking, project hosting service. 5 | 6 | Install Notes 7 | --------------- 8 | 9 | Create a new Git repository in your Unfuddle project. 10 | Once created, edit the repository settings. Check the 11 | "Changesets Managed Manually" checkbox. 12 | 13 | Make note of the following from the URL: 14 | 15 | http://example.unfuddle.com/a#/projects/32429/repositories/28573/browse 16 | 17 | In the above, the data you need for configuration is: 18 | 19 | - subdomain: example 20 | - repo_id: 28573 21 | 22 | Developer Notes 23 | --------------- 24 | 25 | data 26 | - repo_id (Unfuddle respository ID) 27 | - subdomain 28 | - username (Unfuddle API account holder) 29 | - password (Unfuddle API account password) 30 | -------------------------------------------------------------------------------- /test/toggl_test.rb: -------------------------------------------------------------------------------- 1 | require File.expand_path('../helper', __FILE__) 2 | 3 | class TogglTest < Service::TestCase 4 | def setup 5 | @stubs = Faraday::Adapter::Test::Stubs.new 6 | end 7 | 8 | def test_push 9 | url = "/api/v5/tasks.json" 10 | @stubs.post url do |env| 11 | assert_equal 'www.toggl.com', env[:url].host 12 | assert_equal basic_auth(:a, :api_token), env[:request_headers]['authorization'] 13 | assert_equal 900, JSON.parse(env[:body])['task']['duration'] 14 | [200, {}, ''] 15 | end 16 | 17 | modified = payload.dup 18 | modified['commits'].first['message'].sub! /f:/, 't:' 19 | svc = service({'api_token' => 'a'}, modified) 20 | svc.receive_push 21 | end 22 | 23 | def service(*args) 24 | super Service::Toggl, *args 25 | end 26 | end 27 | 28 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source "http://rubygems.org" 2 | 3 | gem "activeresource", "~> 3.0.0" 4 | gem "amqp", "0.6.7", :require => 'mq' 5 | gem "httparty", "0.7.4" 6 | gem 'yajl-ruby', '0.8.3', :require => 'yajl/json_gem' 7 | gem "mash", "~> 0.1.1" 8 | gem "mime-types", "~> 1.15", :require => 'mime/types' 9 | gem "oauth", "0.4.4" 10 | gem "sinatra", "~> 1.2.6" 11 | gem "tilt", "~> 1.2.1" 12 | gem "tinder", "1.7.0" 13 | gem "tmail", "1.2.3.1" 14 | gem "xml-simple", "1.0.11", :require => 'xmlsimple' 15 | gem "xmpp4r-simple", "0.8.4" 16 | #gem "yammer4r", "0.1.5" 17 | gem "ruby-hmac", "0.4.0" 18 | gem "thin", "1.2.2" 19 | gem "faraday", "0.7.5.pre" 20 | gem "rake", "0.8.7" 21 | gem "statsd-ruby", "0.3.0.github.1" 22 | gem "twilio-ruby", "3.4.2" 23 | -------------------------------------------------------------------------------- /docs/hipchat: -------------------------------------------------------------------------------- 1 | HipChat 2 | ======= 3 | 4 | Note: This service currently enables all of the available hook events including 5 | commit comments, downloads, forks, fork applies, wiki updates, issues, issue 6 | comments, member adds, pull requests, pushes, and watches. A full list with 7 | descriptions can be found here: http://developer.github.com/v3/repos/hooks/ 8 | 9 | Install Notes 10 | ------------- 11 | 12 | 1. Auth token - One of your group's API tokens. See: http://www.hipchat.com/docs/api/auth 13 | 2. Room - The full name of the room to send the message to. The room's room_id will also work. 14 | 3. Notify - Whether or not to notify room members. 15 | 16 | Developer Notes 17 | --------------- 18 | 19 | data 20 | - auth_token 21 | - room 22 | - notify (boolean) 23 | 24 | payload 25 | - refer to docs/github_payload 26 | -------------------------------------------------------------------------------- /services/teamcity.rb: -------------------------------------------------------------------------------- 1 | class Service::TeamCity < Service 2 | string :base_url, :build_type_id, :username 3 | password :password 4 | 5 | def receive_push 6 | # :( 7 | http.ssl[:verify] = false 8 | 9 | http.url_prefix = data['base_url'] 10 | http.basic_auth data['username'], data['password'] 11 | res = http_get "httpAuth/action.html", :add2Queue => data['build_type_id'] 12 | case res.status 13 | when 200..299 14 | when 403, 401, 422 then raise_config_error("Invalid credentials") 15 | when 404, 301, 302 then raise_config_error("Invalid TeamCity URL") 16 | else raise_config_error("HTTP: #{res.status}") 17 | end 18 | rescue SocketError => e 19 | raise_config_error "Invalid TeamCity host name" if e.to_s =~ /getaddrinfo: Name or service not known/ 20 | raise 21 | end 22 | end 23 | -------------------------------------------------------------------------------- /test/convore_test.rb: -------------------------------------------------------------------------------- 1 | require File.expand_path('../helper', __FILE__) 2 | 3 | class ConvoreTest < Service::TestCase 4 | def setup 5 | @stubs = Faraday::Adapter::Test::Stubs.new 6 | end 7 | 8 | def test_push 9 | url = "/api/topics/1/messages/create.json" 10 | @stubs.post url do |env| 11 | assert_equal 'application/x-www-form-urlencoded', env[:request_headers]["Content-Type"] 12 | assert_equal basic_auth(:rick, :monkey), env[:request_headers]['authorization'] 13 | assert_match /grit/, env[:body] 14 | [200, {}, '{}'] 15 | end 16 | 17 | svc = service({ 18 | 'topic_id' => '1', 19 | 'username' => 'rick', 20 | 'password' => 'monkey' 21 | }, payload) 22 | svc.receive_push 23 | end 24 | 25 | def service(*args) 26 | super Service::Convore, *args 27 | end 28 | end 29 | 30 | -------------------------------------------------------------------------------- /test/jaconda_test.rb: -------------------------------------------------------------------------------- 1 | require File.expand_path('../helper', __FILE__) 2 | 3 | class JacondaTest < Service::TestCase 4 | def setup 5 | @stubs = Faraday::Adapter::Test::Stubs.new 6 | end 7 | 8 | def test_push 9 | @stubs.post "/api/v2/rooms/r/notify/github.json" do |env| 10 | assert_equal 's.jaconda.im', env[:url].host 11 | assert_equal basic_auth(:rt, :X), env[:request_headers]['authorization'] 12 | assert_match /(^|\&)payload=%7B%22a%22%3A1%7D($|\&)/, env[:body] 13 | assert_match "digest=d", env[:body] 14 | [200, {}, ''] 15 | end 16 | 17 | svc = service( 18 | { 'subdomain' => 's', 'digest' => 'd', 19 | 'room_id' => 'r', 'room_token' => 'rt'}, 'a' => 1) 20 | svc.receive_push 21 | end 22 | 23 | def service(*args) 24 | super Service::Jaconda, *args 25 | end 26 | end 27 | 28 | -------------------------------------------------------------------------------- /test/scrumdo_test.rb: -------------------------------------------------------------------------------- 1 | require File.expand_path('../helper', __FILE__) 2 | 3 | class ScrumDoTest < Service::TestCase 4 | def setup 5 | @stubs = Faraday::Adapter::Test::Stubs.new 6 | end 7 | 8 | def test_push 9 | @stubs.post "/hooks/github/slug" do |env| 10 | assert_equal 'www.scrumdo.com', env[:url].host 11 | data = Rack::Utils.parse_query(env[:body]) 12 | assert_equal 'rick', data['username'] 13 | assert_equal 'monkey', data['password'] 14 | assert data['payload'] 15 | [200, {}, '{}'] 16 | end 17 | 18 | svc = service({ 19 | 'username' => 'rick', 20 | 'password' => 'monkey', 21 | 'project_slug' => 'slug' 22 | }, payload) 23 | 24 | svc.receive_push 25 | end 26 | 27 | def service(*args) 28 | super Service::ScrumDo, *args 29 | end 30 | end 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /test/teamcity_test.rb: -------------------------------------------------------------------------------- 1 | require File.expand_path('../helper', __FILE__) 2 | 3 | class TeamCityTest < Service::TestCase 4 | def setup 5 | @stubs = Faraday::Adapter::Test::Stubs.new 6 | end 7 | 8 | def test_push 9 | url = "/abc/httpAuth/action.html" 10 | @stubs.get url do |env| 11 | assert_equal 'teamcity.com', env[:url].host 12 | assert_equal 'btid', env[:params]['add2Queue'] 13 | assert_equal basic_auth(:u, :p), env[:request_headers]['authorization'] 14 | [200, {}, ''] 15 | end 16 | 17 | svc = service({ 18 | 'base_url' => 'http://teamcity.com/abc', 19 | 'build_type_id' => 'btid', 20 | 'username' => 'u', 21 | 'password' => 'p' 22 | }, 'payload') 23 | svc.receive_push 24 | end 25 | 26 | def service(*args) 27 | super Service::TeamCity, *args 28 | end 29 | end 30 | 31 | -------------------------------------------------------------------------------- /vendor/internal-gems/yammer4r-0.1.5/lib/yammer/message.rb: -------------------------------------------------------------------------------- 1 | class Yammer::Message 2 | 3 | attr_reader :id, :url, :web_url, :replied_to_id, :thread_id, 4 | :body_plain, :body_parsed, :message_type, :client_type, 5 | :sender_id, :sender_type 6 | 7 | def initialize(m) 8 | @id = m['id'] 9 | @url = m['url'] 10 | @web_url = m['web_url'] 11 | @replied_to_id = m['replied_to_id'] 12 | @thread_id = m['thread_id'] 13 | @body_plain = m['body']['plain'] 14 | @body_parsed = m['body']['parsed'] 15 | @message_type = m['message_type'] 16 | @client_type = m['client_type'] 17 | @sender_id = m['sender_id'] 18 | @sender_type = m['sender_type'] 19 | begin 20 | @created_at = m['created_at'] 21 | rescue ArgumentError => e 22 | @created_at = nil 23 | end 24 | end 25 | 26 | end 27 | -------------------------------------------------------------------------------- /services/gemnasium.rb: -------------------------------------------------------------------------------- 1 | class Service::Gemnasium < Service 2 | string :user, :token 3 | 4 | def receive_push 5 | http.basic_auth(user, signature) 6 | http_post(url, body, headers) 7 | end 8 | 9 | def http(*) 10 | super.tap{|h| h.builder.delete(Faraday::Request::UrlEncoded) } 11 | end 12 | 13 | def user 14 | data["user"].strip 15 | rescue 16 | raise_config_error "Invalid user value" 17 | end 18 | 19 | def signature 20 | Digest::SHA2.hexdigest(token + body) 21 | end 22 | 23 | def token 24 | data["token"].strip.downcase 25 | rescue 26 | raise_config_error "Invalid token value" 27 | end 28 | 29 | def body 30 | payload.to_json 31 | end 32 | 33 | def url 34 | "https://gemnasium.com/repositories/hook" 35 | end 36 | 37 | def headers 38 | {:content_type => "application/json"} 39 | end 40 | end 41 | -------------------------------------------------------------------------------- /docs/rubyforge: -------------------------------------------------------------------------------- 1 | RubyForge 2 | ========= 3 | 4 | Special Thanks 5 | ------------- 6 | 7 | Would like to notice Ara Howard and his RubyForge gem, from which I copied most of the code 8 | used in this service. Would also like to notice the author of the Basecamp service, since 9 | I used that service as a template for the RubyForge service. 10 | 11 | This service simply posts a new NewsByte to the RubyForge project (as specified by the groupid). 12 | 13 | Install Notes 14 | ------------- 15 | 16 | 1. username should be the username of a user that has access to the RubyForge project 17 | 2. password should be the password of the given user 18 | 3. groupid should be the group id of the RubyForge project 19 | 20 | 21 | Developer Notes 22 | --------------- 23 | 24 | data 25 | - username 26 | - password 27 | - groupid 28 | 29 | payload 30 | - refer to docs/github_payload 31 | -------------------------------------------------------------------------------- /services/appharbor.rb: -------------------------------------------------------------------------------- 1 | class Service::AppHarbor < Service 2 | string :application_slug, :token 3 | 4 | def receive_push 5 | slug = data['application_slug'] 6 | token = data['token'] 7 | 8 | raise_config_error 'Missing application slug' if slug.to_s.empty? 9 | raise_config_error 'Missing token' if token.to_s.empty? 10 | 11 | create_build_url = "https://appharbor.com/application/#{slug}/build?authorization=#{token}" 12 | 13 | commit = distinct_commits.last 14 | appharbor_message = { 15 | :branches => { 16 | ref_name => { 17 | :commit_id => commit['id'], 18 | :commit_message => commit['message'], 19 | :download_url => commit['url'].sub('commit', 'tarball') 20 | } 21 | } 22 | } 23 | 24 | http_post create_build_url, appharbor_message.to_json, 'Accept' => 'application/json' 25 | end 26 | end 27 | -------------------------------------------------------------------------------- /services/rubyforge.rb: -------------------------------------------------------------------------------- 1 | class Service::Rubyforge < Service 2 | string :groupid, :username 3 | password :password 4 | def receive_push 5 | repository = payload['repository']['name'] 6 | branch = ref_name 7 | payload['commits'].each do |commit| 8 | id = commit['id'] 9 | group_id = data['groupid'] 10 | subject = "Commit Notification (#{repository}/#{branch}): #{id}" 11 | body = "`#{commit['message']}`, pushed by #{commit['author']['name']} (#{commit['author']['email']}). View more details for this change at #{commit['url']}." 12 | 13 | post_news(group_id, subject, body) 14 | end 15 | end 16 | 17 | def post_news(group_id, subject, body) 18 | rubyforge.post_news(group_id, subject, body) 19 | end 20 | 21 | def rubyforge 22 | @rubyforge ||= RubyForge.new(data['username'], data['password']) 23 | end 24 | end 25 | -------------------------------------------------------------------------------- /services/prowl.rb: -------------------------------------------------------------------------------- 1 | class Service::Prowl < Service 2 | string :apikey 3 | 4 | def receive_push 5 | url = URI.parse('https://api.prowlapp.com/publicapi/add') 6 | repository = payload['repository']['url'].split("/") 7 | event = [repository[-2], repository[-1]].join('/') 8 | application = "GitHub" 9 | description = "#{payload['commits'].length} commits pushed to #{application} (#{payload['commits'][-1]['id'][0..7]}..#{payload['commits'][0]['id'][0..7]}) 10 | 11 | Latest Commit by #{payload['commits'][-1]['author']['name']} 12 | #{payload['commits'][-1]['id'][0..7]} #{payload['commits'][-1]['message']}" 13 | 14 | http_post 'https://api.prowlapp.com/publicapi/add', 15 | :apikey => data['apikey'], 16 | :application => application, 17 | :event => event, 18 | :description => description, 19 | :url => payload['compare'] 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /test/zohoprojects_test.rb: -------------------------------------------------------------------------------- 1 | require File.expand_path('../helper', __FILE__) 2 | 3 | class ZohoProjectsTest < Service::TestCase 4 | def setup 5 | @stubs = Faraday::Adapter::Test::Stubs.new 6 | end 7 | 8 | def data 9 | { 10 | "project_id" => "1234", 11 | "token" => "a13d", 12 | } 13 | end 14 | 15 | def test_push 16 | url = "/serviceHook" 17 | @stubs.post url do |env| 18 | assert_equal 'projects.zoho.com', env[:url].host 19 | params = Rack::Utils.parse_query env[:body] 20 | assert_equal '1234', params['pId'] 21 | assert_equal 'a13d', params['authtoken'] 22 | assert_equal payload.to_json, params['payload'] 23 | [200, {}, ''] 24 | end 25 | 26 | svc = service :push, data , payload 27 | svc.receive 28 | end 29 | 30 | def service(*args) 31 | super Service::ZohoProjects, *args 32 | end 33 | end 34 | 35 | -------------------------------------------------------------------------------- /services/hipchat.rb: -------------------------------------------------------------------------------- 1 | class Service::HipChat < Service 2 | string :auth_token, :room 3 | boolean :notify 4 | 5 | default_events :commit_comment, :download, :fork, :fork_apply, :gollum, 6 | :issues, :issue_comment, :member, :public, :pull_request, :push, :watch 7 | 8 | def receive_event 9 | # make sure we have what we need 10 | raise_config_error "Missing 'auth_token'" if data['auth_token'].to_s == '' 11 | raise_config_error "Missing 'room'" if data['room'].to_s == '' 12 | 13 | http.headers['X-GitHub-Event'] = event.to_s 14 | 15 | res = http_post "https://api.hipchat.com/v1/webhooks/github", 16 | :auth_token => data['auth_token'], 17 | :room_id => data['room'], 18 | :payload => JSON.generate(payload), 19 | :notify => data['notify'] ? 1 : 0 20 | if res.status < 200 || res.status > 299 21 | raise_config_error 22 | end 23 | end 24 | end 25 | -------------------------------------------------------------------------------- /docs/basecamp: -------------------------------------------------------------------------------- 1 | Basecamp 2 | ======== 3 | 4 | Install Notes 5 | ------------- 6 | 7 | 1. url should be your Basecamp url 8 | 2. username should be the username or API token of the user that you want to use to post messages into your Basecamp - you can setup a user just for this purpose 9 | 3. password should be the password of the user that you want to use to post the messages. If username is an API token, set password to 'x'. 10 | 4. project should be the name of the project that you want to post the message into (not the id) 11 | 5. category should be the name of the category that you want to post the message using (not the id) 12 | 6. ssl should be enabled for accounts that need SSL. 13 | 14 | 15 | Developer Notes 16 | --------------- 17 | 18 | data 19 | - url 20 | - username 21 | - password 22 | - project 23 | - category 24 | - ssl 25 | 26 | payload 27 | - refer to docs/github_payload -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require 'rake/testtask' 2 | Rake::TestTask.new(:test) do |test| 3 | test.libs << 'lib' << 'test' 4 | test.pattern = 'test/**/*_test.rb' 5 | test.verbose = true 6 | end 7 | 8 | task :default => :test 9 | 10 | task :console do 11 | sh "irb -r ./config/load" 12 | end 13 | 14 | namespace :services do 15 | desc "Writes a JSON config to FILE || config/services.json" 16 | task :config do 17 | file = ENV["FILE"] || File.expand_path("../config/services.json", __FILE__) 18 | require File.expand_path("../config/load", __FILE__) 19 | services = [] 20 | Service.services.each do |svc| 21 | services << {:name => svc.hook_name, :events => svc.default_events, 22 | :title => svc.title, :schema => svc.schema} 23 | end 24 | services.sort! { |x, y| x[:name] <=> y[:name] } 25 | File.open file, 'w' do |io| 26 | io << Yajl.dump(services, :pretty => true) 27 | end 28 | end 29 | end 30 | -------------------------------------------------------------------------------- /docs/scrumdo: -------------------------------------------------------------------------------- 1 | ScrumDo 2 | ======= 3 | 4 | ScrumDo is an agile/scrum project management site found at http://www.scrumdo.com 5 | Integrating Github with ScrumDo lets you see commits in your project newsfeed, and allows you to update stories via commit messages. 6 | 7 | To update a story, type Story #(num) Status as part of your commit message. Examples: 8 | 9 | * Story #13 Done 10 | * Story #5 Doing 11 | * Story #3 Reviewing 12 | 13 | Install Notes 14 | ------------- 15 | 16 | 1. Username and Password are your ScrumDo.com credentials. 17 | 2. The project slug can be found in the URL of your project. 18 | 19 | Given this URL: 20 | 21 | http://www.scrumdo.com/projects/project/acme-project/ 22 | 23 | Your project slug is `acme-project` 24 | 25 | Developer Notes 26 | --------------- 27 | 28 | data 29 | - username 30 | - password 31 | - project_slug 32 | 33 | payload 34 | - refer to docs/github_payload 35 | -------------------------------------------------------------------------------- /test/socialcast_test.rb: -------------------------------------------------------------------------------- 1 | require File.expand_path('../helper', __FILE__) 2 | 3 | class SocialcastTest < Service::TestCase 4 | def setup 5 | @stubs = Faraday::Adapter::Test::Stubs.new 6 | end 7 | 8 | def test_push 9 | @stubs.post "/api/messages.xml" do |env| 10 | assert_equal 'd', env[:url].host 11 | assert_equal basic_auth(:u, :p), env[:request_headers]['authorization'] 12 | data = Rack::Utils.parse_nested_query(env[:body]) 13 | msg = data['message'] 14 | assert_match 'Tom Preston-Werner', msg['body'] 15 | assert_match '3 commits', msg['title'] 16 | assert_equal 'g', msg['group_id'] 17 | [200, {}, ''] 18 | end 19 | 20 | svc = service({'username' => 'u', 'password' => 'p', 21 | 'group_id' => 'g', 'api_domain' => 'd'}, payload) 22 | svc.receive_push 23 | end 24 | 25 | def service(*args) 26 | super Service::Socialcast, *args 27 | end 28 | end 29 | 30 | -------------------------------------------------------------------------------- /services/notifymyandroid.rb: -------------------------------------------------------------------------------- 1 | class Service::NMA < Service 2 | string :apikey 3 | self.title = 'Notify My Android' 4 | 5 | def receive_push 6 | url = URI.parse('https://www.notifymyandroid.com/publicapi/notify') 7 | repository = payload['repository']['url'].split("/") 8 | event = [repository[-2], repository[-1]].join('/') 9 | application = "GitHub" 10 | description = "#{payload['commits'].length} commits pushed to #{application} (#{payload['commits'][-1]['id'][0..7]}..#{payload['commits'][0]['id'][0..7]}) 11 | 12 | Latest Commit by #{payload['commits'][-1]['author']['name']} 13 | #{payload['commits'][-1]['id'][0..7]} #{payload['commits'][-1]['message']}" 14 | 15 | http_post 'https://www.notifymyandroid.com/publicapi/notify', 16 | :apikey => data['apikey'], 17 | :application => application, 18 | :event => event, 19 | :description => description, 20 | :url => payload['compare'] 21 | end 22 | end 23 | -------------------------------------------------------------------------------- /test/twitter_test.rb: -------------------------------------------------------------------------------- 1 | require File.expand_path('../helper', __FILE__) 2 | 3 | class TwitterTest < Service::TestCase 4 | def test_push 5 | svc = service({'token' => 't', 'secret' => 's'}, payload) 6 | 7 | def svc.shorten_url(*args) 'short' end 8 | def svc.statuses 9 | @statuses ||= [] 10 | end 11 | 12 | def svc.post(status) 13 | statuses << status 14 | end 15 | 16 | svc.receive_push 17 | assert_equal 3, svc.statuses.size 18 | svc.statuses.each do |st| 19 | assert_match 'grit', st 20 | end 21 | end 22 | 23 | def test_oauth_consumer 24 | svc = service({'token' => 't', 'secret' => 's'}, payload) 25 | 26 | svc.secrets = {'twitter' => {'key' => 'ck', 'secret' => 'cs'}} 27 | assert_equal 'ck', svc.consumer_key 28 | assert_equal 'cs', svc.consumer_secret 29 | assert svc.consumer 30 | end 31 | 32 | def service(*args) 33 | super Service::Twitter, *args 34 | end 35 | end 36 | 37 | 38 | -------------------------------------------------------------------------------- /test/flowdock_test.rb: -------------------------------------------------------------------------------- 1 | require File.expand_path('../helper', __FILE__) 2 | 3 | class FlowdockTest < Service::TestCase 4 | def setup 5 | @stubs = Faraday::Adapter::Test::Stubs.new 6 | @token = "token" 7 | end 8 | 9 | def test_push 10 | @stubs.post "/v1/github/#{@token}" do |env| 11 | assert_match /json/, env[:request_headers]['content-type'] 12 | assert_equal push_payload, JSON.parse(env[:body]) 13 | [200, {}, ''] 14 | end 15 | 16 | svc = service( 17 | {'token' => @token}, push_payload) 18 | svc.receive_event 19 | end 20 | 21 | def test_token_sanitization 22 | @stubs.post "/v1/github/#{@token}" do |env| 23 | assert_equal payload, JSON.parse(env[:body]) 24 | [200, {}, ''] 25 | end 26 | 27 | svc = service( 28 | {'token' => " " + @token + " "}, payload) 29 | svc.receive_event 30 | end 31 | 32 | def service(*args) 33 | super Service::Flowdock, *args 34 | end 35 | end 36 | 37 | -------------------------------------------------------------------------------- /services/freckle.rb: -------------------------------------------------------------------------------- 1 | class Service::Freckle < Service 2 | string :subdomain, :project, :token 3 | 4 | def receive_push 5 | entries, subdomain, token, project = 6 | [], data['subdomain'].strip, data['token'].strip, data['project'].strip 7 | 8 | payload['commits'].each do |commit| 9 | minutes = (commit["message"].split(/\s/).find { |item| /^f:/ =~ item } || '')[2,100] 10 | next unless minutes 11 | entries << { 12 | :date => commit["timestamp"], 13 | :minutes => minutes, 14 | :description => commit["message"].gsub(/(\s|^)f:.*(\s|$)/, '').strip, 15 | :url => commit['url'], 16 | :project_name => project, 17 | :user => commit['author']['email'] 18 | } 19 | end 20 | 21 | http.headers['Content-Type'] = 'application/json' 22 | http_post "http://#{data['subdomain']}.letsfreckle.com/api/entries/import", 23 | {:entries => entries, :token => data['token']}.to_json 24 | end 25 | end 26 | -------------------------------------------------------------------------------- /docs/freckle: -------------------------------------------------------------------------------- 1 | freckle 2 | ======== 3 | 4 | Install Notes 5 | ------------- 6 | 7 | Using the following URL as an example: 8 | https://nutsnbolts.letsfreckle.com 9 | 10 | 1. Account name: subdomain of the freckle account (nutsnbolts) 11 | 2. Token: the API token for an individual freckle user who is associated with the target freckle account (see instructions below) 12 | 3. Project name: the exact name of the target freckle project to log time for this repo 13 | 14 | To get your API token: log into your freckle account, click Settings at the top right, then click the Integration (API) tab. 15 | 16 | Note about email addresses: the email address on a committer's Github account should match his/her email address on his/her freckle account. Otherwise, we can't identify the person who is logging time. 17 | 18 | Developer Notes 19 | --------------- 20 | 21 | data 22 | - subdomain 23 | - token 24 | - project name 25 | 26 | payload 27 | - refer to docs/github_payload 28 | -------------------------------------------------------------------------------- /docs/zohoprojects: -------------------------------------------------------------------------------- 1 | ZohoProjects 2 | ============ 3 | 4 | Install Notes 5 | ------------- 6 | 7 | Project ID and Token is required for 8 | configuration which will be available 9 | under "Dashboard" --> "Project Settings" 10 | --> "Service Hooks". 11 | 12 | This service hook allows you to associate 13 | changeset(s) with bug(s) in Zoho Projects. 14 | To associate changeset(s) with bug(s) in 15 | ZohoProjects you will need to give the 16 | BUG ID in in your commit message. 17 | 18 | Syntax : OPEN SQUARE BRACKET #BUGID CLOSE SQUARE BRACKET followed by commit message 19 | 20 | Ex : [#SDP-23] fixed the memory leak issue. 21 | 22 | This will associate the changeset with bug with ID SDP-23. 23 | 24 | For more than one bugs, provide the BUG IDS separated by comma. 25 | 26 | Ex : [#SDP-24,#SDP-25] UI alignment fix done. 27 | 28 | Developer Notes 29 | --------------- 30 | 31 | data 32 | - project_id 33 | - token 34 | 35 | payload 36 | - refer to docs/github_payload 37 | 38 | 39 | -------------------------------------------------------------------------------- /services/talker.rb: -------------------------------------------------------------------------------- 1 | class Service::Talker < Service 2 | string :url, :token 3 | boolean :digest 4 | 5 | def receive_push 6 | repository = payload['repository']['name'] 7 | branch = branch_name 8 | commits = payload['commits'] 9 | token = data['token'] 10 | 11 | http.ssl[:verify] = false 12 | http.headers["X-Talker-Token"] = token 13 | http.url_prefix = data['url'] 14 | 15 | if data['digest'].to_i == 1 and commits.size > 1 16 | commit = commits.last 17 | message = "#{commit['author']['name']} pushed #{commits.size} commits to [#{repository}/#{branch}] #{payload['compare']}" 18 | http_post 'messages.json', :message => message 19 | else 20 | commits.each do |commit| 21 | message = "#{commit['author']['name']} pushed \"#{commit['message'].split("\n").first}\" - #{commit['url']} to [#{repository}/#{branch}]" 22 | http_post 'messages.json', :message => message 23 | end 24 | end 25 | end 26 | end 27 | -------------------------------------------------------------------------------- /docs/bamboo: -------------------------------------------------------------------------------- 1 | Bamboo 2 | ======= 3 | 4 | Bamboo is a continuous integration server that automates the building and testing of your software. 5 | The github Bamboo service can be used to trigger builds after code has been pushed to your git repository. 6 | 7 | Install Notes 8 | ------------- 9 | 10 | 1. Your Bamboo server must be accessible from the internet. 11 | 12 | 2. "base_url" is the URL to your Bamboo server 13 | Example: https://bamboo.example.com/ or http://bamboo.example.com/bamboo/ 14 | 15 | 3. "build_key" is the identifier of the plan you want to trigger 16 | Example: "BAM-TRUNK", where BAM = project key, TRUNK = plan key 17 | 18 | 4. "username" and "password" - username and password of a Bamboo user that can 19 | trigger a manual build of the Bamboo plan defined in "build_key" 20 | 21 | Developer Notes 22 | --------------- 23 | 24 | data 25 | - base_url 26 | - build_key 27 | - username 28 | - password 29 | 30 | payload 31 | - refer to docs/github_payload 32 | -------------------------------------------------------------------------------- /services/travis.rb: -------------------------------------------------------------------------------- 1 | class Service::Travis < Service 2 | string :domain, :user, :token 3 | 4 | def receive_push 5 | http.ssl[:verify] = false 6 | http.basic_auth user, token 7 | http_post travis_url, :payload => payload.to_json 8 | end 9 | 10 | def travis_url 11 | "#{scheme}://#{domain}/builds" 12 | end 13 | 14 | def user 15 | if data['user'].to_s == '' 16 | payload['repository']['owner']['name'] 17 | else 18 | data['user'] 19 | end.strip 20 | end 21 | 22 | def token 23 | data['token'].strip 24 | end 25 | 26 | def scheme 27 | domain_parts.size == 1 ? 'http' : domain_parts.first 28 | end 29 | 30 | def domain 31 | domain_parts.last 32 | end 33 | 34 | protected 35 | 36 | def full_domain 37 | if data['domain'].to_s == '' 38 | 'http://travis-ci.org' 39 | else 40 | data['domain'] 41 | end.strip 42 | end 43 | 44 | def domain_parts 45 | @domain_parts ||= full_domain.split('://') 46 | end 47 | end 48 | 49 | -------------------------------------------------------------------------------- /docs/twilio: -------------------------------------------------------------------------------- 1 | Twilio 2 | ====== 3 | 4 | Allows you to setup a GitHub repository to send out SMS messages on git pushes. 5 | Currently the SMS message is built to say: 6 | 7 | [pusher name] has pushed [# commits] commit(s) to [repository name] 8 | 9 | Install Notes 10 | ------------- 11 | 12 | 1. Signup for a Twilio account at http://www.twilio.com/try-twilio?home-page 13 | 2. You can find your account_sid and auth_token on your account page at https://www.twilio.com/user/account 14 | 3. from_phone must be a "Twilio phone number enabled for SMS. Only phone numbers or short codes purchased from Twilio work here" 15 | 4. to_phone is the "destination phone number. Format with a '+' and country code e.g., +16175551212 (E.164 format)." 16 | 5. Check master_only if you only want to recieve updates for master 17 | 18 | Developer Notes 19 | --------------- 20 | 21 | data 22 | - account_sid 23 | - auth_token 24 | - from_phone 25 | - to_phone 26 | - master_only 27 | 28 | payload 29 | - refer to docs/github_payload 30 | -------------------------------------------------------------------------------- /services/toggl.rb: -------------------------------------------------------------------------------- 1 | class Service::Toggl < Service 2 | string :project, :api_token 3 | 4 | def receive_push 5 | http.url_prefix = "https://www.toggl.com/api/v5" 6 | http.basic_auth data['api_token'], 'api_token' 7 | http.headers['Content-Type'] = 'application/json' 8 | 9 | payload["commits"].each do |commit| 10 | duration = (commit["message"].split(/\s/).find { |item| /t:/ =~ item } || "")[2,100] 11 | next unless duration 12 | 13 | # Toggl wants it in seconds. Commits should be in seconds 14 | duration = duration.to_i * 60 15 | 16 | http_post "tasks.json", { 17 | :task => { 18 | :duration => duration.to_i, 19 | :description => commit["message"].strip, 20 | :project => data["project"], 21 | :start => (Time.now - duration.to_i).iso8601, 22 | :billable => true, 23 | :created_with => "github", 24 | :stop => Time.now.iso8601 25 | } 26 | }.to_json 27 | 28 | end 29 | end 30 | end 31 | -------------------------------------------------------------------------------- /test/bugherd_test.rb: -------------------------------------------------------------------------------- 1 | class BugherdTest < Service::TestCase 2 | def setup 3 | @stubs = Faraday::Adapter::Test::Stubs.new 4 | end 5 | 6 | def test_push 7 | @stubs.post "/custom" do |env| 8 | assert_equal 'www.example.com', env[:url].host 9 | assert_equal 'application/x-www-form-urlencoded', 10 | env[:request_headers]['content-type'] 11 | [200, {}, ''] 12 | end 13 | 14 | svc = service :push, 15 | {'url' => 'http://www.example.com/custom', 'project_key' => 'KEY'}, payload 16 | svc.receive_push 17 | 18 | @stubs.post "/github_web_hook/KEY" do |env| 19 | assert_equal 'www.bugherd.com', env[:url].host 20 | assert_equal 'application/x-www-form-urlencoded', 21 | env[:request_headers]['content-type'] 22 | [200, {}, ''] 23 | end 24 | 25 | svc = service :push, 26 | {'url' => '', 'project_key' => 'KEY'}, payload 27 | svc.receive_push 28 | end 29 | 30 | def service(*args) 31 | super Service::Bugherd, *args 32 | end 33 | end 34 | -------------------------------------------------------------------------------- /test/notifo_test.rb: -------------------------------------------------------------------------------- 1 | require File.expand_path('../helper', __FILE__) 2 | 3 | class NotifoTest < Service::TestCase 4 | def setup 5 | @stubs = Faraday::Adapter::Test::Stubs.new 6 | end 7 | 8 | def test_push 9 | subscribed = %w(a b) 10 | notified = %w(a b) 11 | @stubs.post "/v1/subscribe_user" do |env| 12 | assert_equal 'api.notifo.com', env[:url].host 13 | data = Rack::Utils.parse_nested_query(env[:body]) 14 | assert_equal subscribed.shift, data['username'] 15 | [200, {}, ''] 16 | end 17 | 18 | @stubs.post "/v1/send_notification" do |env| 19 | assert_equal 'api.notifo.com', env[:url].host 20 | data = Rack::Utils.parse_nested_query(env[:body]) 21 | assert_equal notified.shift, data['to'] 22 | [200, {}, ''] 23 | end 24 | 25 | svc = service({'subscribers' => 'a,b'}, payload) 26 | svc.secrets = {'notifo' => {'apikey' => 'a'}} 27 | svc.receive_push 28 | end 29 | 30 | def service(*args) 31 | super Service::Notifo, *args 32 | end 33 | end 34 | 35 | -------------------------------------------------------------------------------- /test/coop_test.rb: -------------------------------------------------------------------------------- 1 | require File.expand_path('../helper', __FILE__) 2 | 3 | class CoOpTest < Service::TestCase 4 | def setup 5 | @stubs = Faraday::Adapter::Test::Stubs.new 6 | end 7 | 8 | def test_push 9 | svc = service({'group_id' => 'abc', 'token' => 'def'}, payload) 10 | 11 | num = 0 12 | @stubs.post "/groups/abc/notes" do |env| 13 | data = JSON.parse env[:body] 14 | assert_match /tom/i, data['status'] 15 | assert_equal 'def', data['key'] 16 | 17 | assert_equal 'GitHub Notifier', env[:request_headers]['User-Agent'] 18 | assert_equal 'application/json; charset=utf-8', 19 | env[:request_headers]['Content-Type'] 20 | assert_equal 'application/json', 21 | env[:request_headers]['Accept'] 22 | 23 | num += 1 24 | 25 | [200, {}, ''] 26 | end 27 | 28 | svc.receive_push 29 | assert_equal 3, num 30 | 31 | @stubs.verify_stubbed_calls 32 | end 33 | 34 | def service(*args) 35 | super Service::CoOp, *args 36 | end 37 | end 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /lib/events/issue_helpers.rb: -------------------------------------------------------------------------------- 1 | module Service::IssueHelpers 2 | include Service::HelpersWithRepo, 3 | Service::HelpersWithActions 4 | 5 | def issue 6 | @issue ||= self.class.objectify(payload['issue']) 7 | end 8 | 9 | def summary_url 10 | issue.html_url 11 | end 12 | 13 | def summary_message 14 | "[%s] %s opened issue #%d: %s. %s" % [ 15 | repo.name, 16 | issue.user.login, 17 | issue.number, 18 | issue.title, 19 | issue.html_url] 20 | rescue 21 | raise_config_error "Unable to build message: #{$!.to_s}" 22 | end 23 | 24 | def self.sample_payload 25 | { 26 | "action" => "opened", 27 | "issue" => { 28 | "number" => 5, 29 | "state" => "open", 30 | "title" => "booya", 31 | "body" => "boom town", 32 | "user" => { "login" => "mojombo" } 33 | }, 34 | "repository" => { 35 | "name" => "grit", 36 | "url" => "http://github.com/mojombo/grit", 37 | "owner" => { "login" => "mojombo" } 38 | } 39 | } 40 | end 41 | end 42 | -------------------------------------------------------------------------------- /test/helper.rb: -------------------------------------------------------------------------------- 1 | require 'test/unit' 2 | require File.expand_path('../../config/load', __FILE__) 3 | 4 | class Service::TestCase < Test::Unit::TestCase 5 | def test_default 6 | end 7 | 8 | def service(klass, event_or_data, data, payload=nil) 9 | event = nil 10 | if event_or_data.is_a?(Symbol) 11 | event = event_or_data 12 | else 13 | payload = data 14 | data = event_or_data 15 | event = :push 16 | end 17 | 18 | service = klass.new(event, data, payload) 19 | service.http = Faraday.new do |b| 20 | b.request :url_encoded 21 | b.adapter :test, @stubs 22 | end 23 | service 24 | end 25 | 26 | def basic_auth(user, pass) 27 | "Basic " + ["#{user}:#{pass}"].pack("m*").strip 28 | end 29 | 30 | def push_payload 31 | Service::PushHelpers.sample_payload 32 | end 33 | alias payload push_payload 34 | 35 | def pull_payload 36 | Service::PullRequestHelpers.sample_payload 37 | end 38 | 39 | def issues_payload 40 | Service::IssueHelpers.sample_payload 41 | end 42 | end 43 | 44 | -------------------------------------------------------------------------------- /services/kickoff.rb: -------------------------------------------------------------------------------- 1 | class Service::Kickoff < Service 2 | string :project_id, :project_token 3 | 4 | def receive_push 5 | raise_config_error 'Missing project id' if data['project_id'].to_s.empty? 6 | raise_config_error 'Missing project token' if data['project_token'].to_s.empty? 7 | 8 | messages = [] 9 | messages << "#{summary_message}: #{summary_url}" 10 | messages += commit_messages.first(8) 11 | 12 | if messages.first =~ /pushed 1 new commit/ 13 | messages.shift # drop summary message 14 | messages.first << " (#{distinct_commits.first['url']})" 15 | end 16 | 17 | doc = REXML::Document.new("") 18 | e = REXML::Element.new("message") 19 | e.text = messages.join("\n") 20 | doc.root.add(e) 21 | e = REXML::Element.new("service") 22 | e.text = "github" 23 | doc.root.add(e) 24 | 25 | http_post "http://api.kickoffapp.com/projects/#{data['project_id']}/chat" do |req| 26 | req.params[:token] = data['project_token'] 27 | req.body = doc.to_s 28 | end 29 | end 30 | end 31 | -------------------------------------------------------------------------------- /docs/travis: -------------------------------------------------------------------------------- 1 | Travis 2 | ====== 3 | 4 | Travis – a distributed build server tool for the Ruby community 5 | 6 | 7 | Install Notes 8 | ------------- 9 | 10 | 1. Create an account (on travis-ci.org you can just sign in with GitHub) 11 | 2. Enter your credentials 12 | - The token which you can find on the Travis profile page 13 | Optional steps: 14 | - Enter the username who the travis-token belongs to (defaults to the repository owner) 15 | - Enter the host of your Travis installation (defaults to http://travis-ci.org), the protocol-prefix is optional and defaults to "http://". 16 | 17 | 3. Check the "Active" checkbox and click "Update Settings". 18 | 4. Click on the "Travis" service name and then click the "Test Hook" link. 19 | 5. You should receive an email from Travis once the build has completed 20 | 21 | For more details about Travis, go to http://github.com/travis-ci/travis-ci 22 | 23 | 24 | Developer Notes 25 | --------------- 26 | 27 | data 28 | - token 29 | - user 30 | - domain 31 | 32 | The token has to belong to the user, of course. 33 | -------------------------------------------------------------------------------- /test/unfuddle_test.rb: -------------------------------------------------------------------------------- 1 | require File.expand_path('../helper', __FILE__) 2 | 3 | class UnfuddleTest < Service::TestCase 4 | def setup 5 | @stubs = Faraday::Adapter::Test::Stubs.new 6 | end 7 | 8 | def test_push 9 | @stubs.get '/api/v1/people.json' do |env| 10 | assert_equal 's.unfuddle.com', env[:url].host 11 | assert_equal basic_auth(:u, :p), env[:request_headers]['authorization'] 12 | [200, {}, [{:email => 'tom@mojombo.com', :account_id => 1}].to_json] 13 | end 14 | 15 | @stubs.post '/api/v1/repositories/2/changesets.json' do |env| 16 | assert_equal 's.unfuddle.com', env[:url].host 17 | assert_equal basic_auth(:u, :p), env[:request_headers]['authorization'] 18 | [200, {'Location' => '/abc'}, ''] 19 | end 20 | 21 | @stubs.put '/abc' do 22 | [200, {}, ''] 23 | end 24 | 25 | svc = service({ 26 | 'repo_id' => '2.0', 'subdomain' => 's', 27 | 'username' => 'u', 'password' => 'p'}, payload) 28 | svc.receive_push 29 | end 30 | 31 | def service(*args) 32 | super Service::Unfuddle, *args 33 | end 34 | end 35 | 36 | -------------------------------------------------------------------------------- /docs/notifo: -------------------------------------------------------------------------------- 1 | Notifo 2 | ========== 3 | 4 | This service lets your broadcast your commits on Notifo, a mobile notifications platform. Get commit notifications on your iPhone and other mobile devices immediately via PUSH. Notifo also OS X, Linux and Windows notification apps. If multiple commits are in a push you will be shown the last with a message stating how many more exist, and a link to the compare url. 5 | 6 | Install Notes 7 | ------------- 8 | 9 | 1. Create a user account on Notifo at https://notifo.com/register 10 | 2. Type in your username and the usernames of others wanting to be notified of commits to this repository with Notifo into the subscribers field. 11 | 3. Enjoy. 12 | 13 | Notifications are only sent after the service (GitHub) has been approved to send you notifications on Notifo. This happens after the first commit after this service is enabled. You will begin receiving commit notifications from then on. 14 | 15 | 16 | Developer Notes 17 | --------------- 18 | 19 | data 20 | - subscribers (csv list of up to 25 Notifo usernames) 21 | 22 | payload 23 | - refer to docs/github_payload 24 | -------------------------------------------------------------------------------- /test/appharbor_test.rb: -------------------------------------------------------------------------------- 1 | require File.expand_path('../helper', __FILE__) 2 | 3 | class AppHarborTest < Service::TestCase 4 | def setup 5 | @stubs = Faraday::Adapter::Test::Stubs.new 6 | end 7 | 8 | def test_push 9 | application_slug = 'foo' 10 | token = 'bar' 11 | 12 | @stubs.post "/application/#{application_slug}/build" do |env| 13 | assert_equal token, env[:params]['authorization'] 14 | assert_equal 'application/json', env[:request_headers]['accept'] 15 | 16 | branches = JSON.parse(env[:body])['branches'] 17 | assert_equal 1, branches.size 18 | 19 | branch = branches[payload['ref'].sub(/\Arefs\/heads\//, '')] 20 | assert_not_nil branch 21 | assert_equal payload['after'], branch['commit_id'] 22 | assert_equal payload['commits'].select{|c| c['id'] == payload['after']}.first['message'], branch['commit_message'] 23 | end 24 | 25 | svc = service({'token' => token, 'application_slug' => application_slug}, payload) 26 | svc.receive_push 27 | end 28 | 29 | def service(*args) 30 | super Service::AppHarbor, *args 31 | end 32 | end 33 | -------------------------------------------------------------------------------- /docs/irc: -------------------------------------------------------------------------------- 1 | IRC 2 | ======== 3 | 4 | Install Notes 5 | ------------- 6 | 7 | 1. `server` (ie. irc.freenode.net) 8 | 2. `port` is normally 6667 / 9999 for ssl 9 | 3. the `room` field can support multiple rooms (comma separated) 10 | 4. the `password` field is for the server password 11 | 5. room passwords can be specified for each room like this: 12 | room_name::password 13 | 6. prefixing '#' to the room field is optional 14 | 7. `nick` is not required. If provided, the IRCBot will use that 15 | nick. 16 | 8. Enable `long_url` so that compare/commit url's are not passed 17 | through bit.ly. 18 | 9. Enable `message_without_join' to keep the GitHub IRC bot from 19 | joining and immediately leaving the channel for each push. 20 | 10. Enable `no_colors` to disable colors in the messages sent by the 21 | Github IRC bot. 22 | 23 | 24 | Developer Notes 25 | --------------- 26 | 27 | data 28 | - server 29 | - port 30 | - room 31 | - password 32 | - ssl 33 | - nick 34 | - long_url 35 | - message_without_join 36 | - no_colors 37 | 38 | payload 39 | - refer to docs/github_payload 40 | -------------------------------------------------------------------------------- /docs/active_collab: -------------------------------------------------------------------------------- 1 | ActiveCollab 2 | ======== 3 | 4 | Install Notes 5 | ------------- 6 | 7 | 1. Currently, you must specify in the configuration milestone and or category if you want the commits to be associated with them. 8 | In the future, I plan for this to have some form of configuration via tags / branches, or something like that. 9 | 2. URL, Project ID, and Token are required the others not so much. 10 | 11 | Developer Notes 12 | --------------- 13 | 14 | data 15 | - url (called URL in /activecollab/public/index.php?path_info=people/:company_id/users/:user_id/api) 16 | - token (called Key in /activecollab/public/index.php?path_info=people/:company_id/users/:user_id/api) 17 | - project_id (in URL for /activecollab/public/index.php?path_info=projects/:project_id) 18 | - milestone_id (*OPTIONAL* in URL for /activecollab/public/index.php?path_info=projects/:project_id/milestones/:milestone_id) 19 | - category_id (*OPTIONAL* in URL for /activecollab/public/index.php?path_info=projects/:project_id/discussions&category_id=:category_id) 20 | 21 | payload 22 | - refer to docs/github_payload 23 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2008 Logical Awesome, LLC 2 | 3 | Permission is hereby granted, free of charge, to any person 4 | obtaining a copy of this software and associated documentation 5 | files (the "Software"), to deal in the Software without 6 | restriction, including without limitation the rights to use, 7 | copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the 9 | Software is furnished to do so, subject to the following 10 | conditions: 11 | 12 | The above copyright notice and this permission notice shall be 13 | included in all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 17 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 19 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 20 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /test/pachube_test.rb: -------------------------------------------------------------------------------- 1 | require File.expand_path('../helper', __FILE__) 2 | 3 | class PachubeTest < Service::TestCase 4 | def setup 5 | @stubs = Faraday::Adapter::Test::Stubs.new 6 | end 7 | 8 | def test_require_api_key 9 | svc = service({}, payload) 10 | assert_raises Service::ConfigurationError do 11 | svc.receive_push 12 | end 13 | end 14 | 15 | def test_require_feed_id 16 | svc = service({'api_key' => 'abcd1234'}, payload) 17 | assert_raises Service::ConfigurationError do 18 | svc.receive_push 19 | end 20 | end 21 | 22 | def test_push 23 | @stubs.put "/v2/feeds/1234.json" do |env| 24 | assert_equal 'api.pachube.com', env[:url].host 25 | assert_equal 'https', env[:url].scheme 26 | parsed_body = JSON.parse(env[:body]) 27 | assert_equal '1.0.0', parsed_body['version'] 28 | assert_equal [{'current_value' => 3, 'id' => 'grit'}], parsed_body['datastreams'] 29 | [200, {}, ''] 30 | end 31 | 32 | svc = service({'api_key' => 'abcd1234', 'feed_id' => '1234'}, payload) 33 | svc.receive_push 34 | end 35 | 36 | def service(*args) 37 | super Service::Pachube, *args 38 | end 39 | end 40 | 41 | -------------------------------------------------------------------------------- /services/statusnet.rb: -------------------------------------------------------------------------------- 1 | class Service::StatusNet < Service 2 | string :server, :username 3 | password :password 4 | boolean :digest 5 | 6 | def receive_push 7 | repository = payload['repository']['name'] 8 | statuses = Array.new 9 | 10 | if data['digest'] == '1' 11 | commit = payload['commits'][-1] 12 | tiny_url = shorten_url("#{payload['repository']['url']}/commits/#{ref_name}") 13 | statuses.push "[#{repository}] #{tiny_url} #{commit['author']['name']} - #{payload['commits'].length} commits" 14 | else 15 | payload['commits'].each do |commit| 16 | tiny_url = shorten_url(commit['url']) 17 | statuses.push "[#{repository}] #{tiny_url} #{commit['author']['name']} - #{commit['message']}" 18 | end 19 | end 20 | 21 | http.ssl[:verify] = false 22 | http.url_prefix = data['server'] 23 | http.basic_auth(data['username'], data['password']) 24 | statuses.each do |status| 25 | http_post '/api/statuses/update.xml', 26 | 'status' => status, 'source' => 'github' 27 | end 28 | rescue Faraday::Error::ConnectionFailed 29 | raise_config_error "Connection refused. Invalid server configuration." 30 | end 31 | end 32 | -------------------------------------------------------------------------------- /services/presently.rb: -------------------------------------------------------------------------------- 1 | class Service::Presently < Service 2 | string :subdomain, :group_name, :username 3 | password :password 4 | 5 | def receive_push 6 | repository = payload['repository']['name'] 7 | 8 | prefix = (data['group_name'].nil? || data['group_name'] == '') ? '' : "b #{data['group_name']} " 9 | 10 | payload['commits'].each do |commit| 11 | status = "#{prefix}[#{repository}] #{commit['author']['name']} - #{commit['message']}" 12 | status = status[0...137] + '...' if status.length > 140 13 | 14 | paste = "\"Commit #{commit['id']}\":#{commit['url']}\n\n" 15 | paste << "#{commit['message']}\n\n" 16 | 17 | %w(added modified removed).each do |kind| 18 | commit[kind].each do |filename| 19 | paste << "* *#{kind.capitalize}* '#{filename}'\n" 20 | end 21 | end 22 | 23 | http.url_prefix = "https://#{data['subdomain']}.presently.com" 24 | http.basic_auth(data['username'], data['password']) 25 | http_post "/api/twitter/statuses/update.xml", 26 | 'status' => status, 27 | 'source' => 'GitHub', 28 | 'paste_format' => 'textile', 29 | 'paste_text' => paste 30 | end 31 | end 32 | end 33 | -------------------------------------------------------------------------------- /test/codeclimate_test.rb: -------------------------------------------------------------------------------- 1 | require File.expand_path('../helper', __FILE__) 2 | 3 | class CodeClimateTest < Service::TestCase 4 | def setup 5 | @stubs = Faraday::Adapter::Test::Stubs.new 6 | @svc = service(data, payload) 7 | end 8 | 9 | def test_reads_token_from_data 10 | assert_equal "5373dd4a3648b88fa9acb8e46ebc188a", @svc.token 11 | end 12 | 13 | def test_strips_whitespace_from_token 14 | svc = service({'token' => '5373dd4a3648b88fa9acb8e46ebc188a '}, payload) 15 | assert_equal '5373dd4a3648b88fa9acb8e46ebc188a', svc.token 16 | end 17 | 18 | def test_posts_payload 19 | @stubs.post '/github_pushes' do |env| 20 | assert_equal 'https', env[:url].scheme 21 | assert_equal 'codeclimate.com', env[:url].host 22 | assert_equal basic_auth('github', '5373dd4a3648b88fa9acb8e46ebc188a'), 23 | env[:request_headers]['authorization'] 24 | assert_equal payload, JSON.parse(Rack::Utils.parse_query(env[:body])['payload']) 25 | end 26 | 27 | @svc.receive_push 28 | end 29 | 30 | private 31 | 32 | def service(*args) 33 | super Service::CodeClimate, *args 34 | end 35 | 36 | def data 37 | { 'token' => '5373dd4a3648b88fa9acb8e46ebc188a' } 38 | end 39 | 40 | end 41 | -------------------------------------------------------------------------------- /services/notifo.rb: -------------------------------------------------------------------------------- 1 | class Service::Notifo < Service 2 | string :subscribers 3 | 4 | def receive_push 5 | subscribe_url = URI.parse('https://api.notifo.com/v1/subscribe_user') 6 | http.basic_auth 'github', secrets['notifo']['apikey'] 7 | http.url_prefix = "https://api.notifo.com/v1" 8 | 9 | data['subscribers'].gsub(/\s/, '').split(',').each do |subscriber| 10 | http_post "subscribe_user", :username => subscriber 11 | 12 | commit = payload['commits'].last; 13 | author = commit['author'] || {} 14 | 15 | if payload['commits'].length > 1 16 | extras = payload['commits'].length - 1 17 | http_post "send_notification", 18 | 'to' => subscriber, 19 | 'msg' => "#{author['name']}: \"#{commit['message'].slice(0,40)}\" (+#{extras} more commits)", 20 | 'title' => "#{payload['repository']['name']}/#{ref_name}", 21 | 'uri' => payload['compare'] 22 | else 23 | http_post "send_notification", 24 | 'to' => subscriber, 25 | 'msg' => "#{author['name']}: \"#{commit['message']}\"", 26 | 'title' => "#{payload['repository']['name']}/#{ref_name}", 27 | 'uri' => commit['url'] 28 | end 29 | end 30 | end 31 | end 32 | -------------------------------------------------------------------------------- /test/service_test.rb: -------------------------------------------------------------------------------- 1 | require File.expand_path('../helper', __FILE__) 2 | 3 | class ServiceTest < Service::TestCase 4 | class TestService < Service 5 | def receive_push 6 | end 7 | end 8 | 9 | def setup 10 | @stubs = Faraday::Adapter::Test::Stubs.new 11 | @service = service(:push, 'data', 'payload') 12 | end 13 | 14 | def test_receive_valid_event 15 | assert TestService.receive :push, {}, {} 16 | end 17 | 18 | def test_url_shorten 19 | url = "http://github.com" 20 | @stubs.post "/" do |env| 21 | assert_equal 'git.io', env[:url].host 22 | data = Rack::Utils.parse_query(env[:body]) 23 | assert_equal url, data['url'] 24 | [201, {'Location' => 'short'}, ''] 25 | end 26 | 27 | assert_equal 'short', @service.shorten_url(url) 28 | end 29 | 30 | def test_ssl_check 31 | http = @service.http 32 | def http.post 33 | raise OpenSSL::SSL::SSLError 34 | end 35 | 36 | @stubs.post "/" do |env| 37 | raise "This stub should not be called" 38 | end 39 | 40 | assert_raises Service::ConfigurationError do 41 | @service.http_post 'http://abc' 42 | end 43 | end 44 | 45 | def service(*args) 46 | super TestService, *args 47 | end 48 | end 49 | -------------------------------------------------------------------------------- /docs/bugly: -------------------------------------------------------------------------------- 1 | Bugly 2 | ===== 3 | 4 | Bugly is a hosted bug and issue tracker. Integrating it with GitHub 5 | allows you to associate commits with issues and see commits in all 6 | timelines. 7 | 8 | 9 | Install Notes 10 | ------------- 11 | 12 | 1. 'token' (REQUIRED) is an API token with read/write access to the 13 | account/project. Click the '+' sign in the lower left corner of 14 | your Bugly account, then click New token to create a new token 15 | for your user. Or click Quick Access, then the user you wish to 16 | create a token for, then click the API tokens tab, then click 17 | New API token. 18 | 19 | 2. 'account_name' (REQUIRED) is your Bugly account name. It would be 20 | 'foobar' in the following URL: http://foobar.bug.ly/ 21 | 22 | 3. 'project_id' (OPTIONAL) is the ID of the Bugly project to associate 23 | all commits with. If no project_id is provided, commits will only 24 | appear in the account-wide timeline, not project timelines. The ID 25 | would be '321' in this URL: http://foo.bug.ly/projects/321-MyProject 26 | 27 | 28 | Developer Notes 29 | --------------- 30 | 31 | data 32 | - token 33 | - account_name 34 | - project_id 35 | 36 | payload 37 | - refer to docs/github_payload 38 | -------------------------------------------------------------------------------- /test/pivotal_tracker_test.rb: -------------------------------------------------------------------------------- 1 | require File.expand_path('../helper', __FILE__) 2 | 3 | class PivotalTrackerTest < Service::TestCase 4 | 5 | def setup 6 | @stubs = Faraday::Adapter::Test::Stubs.new 7 | end 8 | 9 | def test_mismatched_branch 10 | svc = service({"branch" => "abc"}, payload) 11 | svc.notifier = Proc.new { raise } 12 | assert_nothing_raised { svc.receive_push } 13 | end 14 | 15 | def test_matching_branch 16 | payload = {"ref" => "refs/heads/master"} 17 | @stubs.post "/services/v3/github_commits" do |env| 18 | assert_equal 'www.pivotaltracker.com', env[:url].host 19 | assert_equal "payload=#{CGI.escape(payload.to_json)}", env[:body] 20 | [200, {}, ''] 21 | end 22 | 23 | svc = service({"branch" => "master"}, payload) 24 | svc.receive_push 25 | end 26 | 27 | def test_no_specified_branch 28 | @stubs.post "/services/v3/github_commits" do |env| 29 | assert_equal 'www.pivotaltracker.com', env[:url].host 30 | assert_equal 'payload=%7B%22a%22%3A1%7D', env[:body] 31 | [200, {}, ''] 32 | end 33 | 34 | svc = service({}, :a => 1) 35 | svc.receive_push 36 | end 37 | 38 | def service(*args) 39 | super Service::PivotalTracker, *args 40 | end 41 | end 42 | 43 | -------------------------------------------------------------------------------- /docs/jira: -------------------------------------------------------------------------------- 1 | Jira 2 | ======== 3 | 4 | This service hook allows you to transition Jira tickets using the REST API available in 5 | version 4.2+ of Jira. To interact with tickets in Jira you will need to place markup 6 | similar to Lighthouse's in your commit message. 7 | 8 | Fixed an annoying bug [#WEB-210 transition:31 resolution:1] 9 | 10 | This will perform transition 31 with a resolution code of 1 on the issue WEB-210. You can specify 11 | any key value pair with the `key:value` notation, but at the very least transition must be present. 12 | 13 | NOTE: As of 2.0.alpha1, the REST API will not automatically interpret strings into integers and vice 14 | versa. 15 | 16 | Install Notes 17 | ------------- 18 | A user in Jira will need to be created for GitHub. It should be given full 19 | access to all projects. 20 | 21 | Using the following url as an example: 22 | http://jira.enmasse.com/rest/2.0.alpha1/issue/WEB-249 23 | 24 | 1. http://jira.enmasse.com is the server_hostname 25 | 2. 2.0.alpha1 is the api_version 26 | 3. username of the GitHub user in Jira 27 | 4. password of the GitHub user in Jira 28 | 29 | 30 | Developer Notes 31 | --------------- 32 | 33 | data 34 | - server_url 35 | - api_version 36 | - username 37 | - password 38 | 39 | payload 40 | - refer to docs/github_payload 41 | -------------------------------------------------------------------------------- /test/active_collab_test.rb: -------------------------------------------------------------------------------- 1 | require File.expand_path('../helper', __FILE__) 2 | 3 | class ActiveCollabTest < Service::TestCase 4 | def setup 5 | @stubs = Faraday::Adapter::Test::Stubs.new 6 | end 7 | 8 | def test_push 9 | @stubs.post "/foo" do |env| 10 | query = Rack::Utils.parse_nested_query(env[:url].query) 11 | body = Rack::Utils.parse_nested_query(env[:body]) 12 | assert_equal '2', body['discussion']['milestone_id'] 13 | assert_equal '3', body['discussion']['parent_id'] 14 | assert_equal 'activecollab.com', env[:url].host 15 | assert_equal "projects/1/discussions/add", query['path_info'] 16 | assert_equal "token", query["token"] 17 | assert_equal 'application/xml', env[:request_headers]["Accept"] 18 | assert_match /grit/, env[:body] 19 | [200, {}, '{}'] 20 | end 21 | 22 | svc = service({ 23 | 'url' => 'http://activecollab.com/foo', 24 | 'token' => 'token', 25 | 'project_id' => '1', 26 | 'milestone_id' => '2', 27 | 'category_id' => '3' 28 | }, payload) 29 | 30 | def svc.shorten_url(*args) 31 | 'short' 32 | end 33 | 34 | svc.receive_push 35 | end 36 | 37 | def service(*args) 38 | super Service::ActiveCollab, *args 39 | end 40 | end 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /docs/redmine: -------------------------------------------------------------------------------- 1 | Redmine 2 | ========== 3 | 4 | Notifies an instance of Redmine, a project management tool, to fetch the new commits from GitHub. 5 | 6 | Install Notes 7 | ------------- 8 | 9 | 1. Download and install Redmine from http://redmine.org 10 | 2. Activate "Enable WS for repository management" in the global settings. While there, generate an API key (if neccessary) and copy it. 11 | 3. Set your github repository as git repository for a project. 12 | 4. Enter the full URL to your Redmine instance as well as the project's identifier and the API key. 13 | 5. We will then notify your Redmine whenever you do a "git push". 14 | 15 | Note: The GitHub servers need to have access to "sys/fetch_changesets". Some older tutorials have you add a rule to your server config to 16 | allow access to sys/ only from localhost. Since it is now possible to use an API key, this is no longer necessary. 17 | 18 | Notifies an instance of Redmine, a project management tool, to fetch the new commits from GitHub. 19 | 20 | Developer Notes 21 | --------------- 22 | 23 | data 24 | - address (full URL of the redmine instance) 25 | - api_key (the API key for using the webservice) 26 | - project (identifier of the project belonging to this repository) 27 | 28 | payload 29 | - refer to docs/github_payload (nothing is used by this script) 30 | -------------------------------------------------------------------------------- /docs/yammer: -------------------------------------------------------------------------------- 1 | Yammer 2 | ====== 3 | 4 | Install Notes 5 | ------------- 6 | 7 | 1. Create a new Yammer user that will post all of your commit messages by proxy (e.g. git@organization.tld) 8 | 9 | 2. Login as this user and go to https://www.yammer.com/client_applications/new 10 | 11 | 3. Create a new application, for example: 12 | 13 | Application name: organization-git 14 | Author: organization 15 | Author Email: git@organization.tld 16 | Main Application URL: http://organization.tld/ 17 | 18 | 4. Save the returned Consumer (Application) Key and Consumer (Application) Secret. You will need them for the next step. 19 | 20 | 5. Authorize the application. You can do this by using the yammer_create_oauth_yml.rb script of the yammer4r gem. 21 | 22 | *** Note: on my system (ruby 1.8.7 / OS X 10.6.4) I had to make a (very) small patch to this file to get it 23 | to complete. It may have been pulled into jstewart's master (http://github.com/jpatterson/yammer4r) by 24 | the time you read this -- but if not you can grab mine here at http://github.com/rboyd/yammer4r 25 | 26 | Don't worry, if it fails on the first attempt you can always try again without issue. *** 27 | 28 | 6. Enter the output of step 5 (consumer key+secret and access token+secret) into your github service hook form for yammer. 29 | 30 | 31 | -------------------------------------------------------------------------------- /docs/teamcity: -------------------------------------------------------------------------------- 1 | TeamCity 2 | ======= 3 | 4 | TeamCity is a continuous integration server that automates the building and testing of your software. 5 | The github TeamCity service can be used to trigger builds after code has been pushed to your git repository. 6 | 7 | Install Notes 8 | ------------- 9 | 10 | 1. Your TeamCity server must be accessible from the internet. 11 | 12 | 2. "base_url" is the URL to your TeamCity server 13 | Example: https://teamcity.example.com/ or http://teamcity.example.com/teamcity/ 14 | 15 | 3. "build_type_id" is the identifier of the build configuration you want to trigger 16 | Example: "bt123", which can be found in URL of the build configuration page ("...viewType.html?buildTypeId=bt123&...") 17 | 18 | 4. "username" and "password" - username and password of a TeamCity user that can 19 | trigger a manual build of the TeamCity build configuration defined in "build_type_id" 20 | 21 | 5. Since TeamCity uses BASIC authentication, it is highly recommended that the TeamCity server 22 | use HTTPS/SSL to protect the password that is passed unencrypted over the internet. 23 | 24 | 25 | Developer Notes 26 | --------------- 27 | 28 | data 29 | - base_url 30 | - build_type_id 31 | - username 32 | - password 33 | 34 | payload 35 | - unused by this service 36 | -------------------------------------------------------------------------------- /docs/bugzilla: -------------------------------------------------------------------------------- 1 | Bugzilla 2 | ======== 3 | 4 | This service hook posts comments on Bugzilla bugs when commit messages 5 | reference a bug by id number. 6 | 7 | Bugs are recognised by the following formats, which are case-insensitive: 8 | - Ticket 123 9 | - Bug 123 10 | - Tracker item 123 11 | 12 | Multiple bugs can also be specified by separating them with a comma, 13 | apersand, plus or "and": 14 | - Bug 123, 124 and 125 15 | 16 | If the central repository option is enabled and there is a "fix", 17 | "close", or "address" before the bug then that bug is closed. 18 | 19 | If a commit has already been mentioned in the bug comments when pushed 20 | by another user then a comment isn't made, unless the central repository 21 | option is enabled. In this case only the first line of the commit message 22 | is included in the bug comment. 23 | 24 | This hook requires Bugzilla version >= 3.4 to function correctly 25 | and >= 4.0 to be able to close bugs. 26 | 27 | Settings 28 | -------- 29 | 30 | - server_url - The URL for the Bugzilla installation, eg http://bugzilla.mozilla.org/ 31 | - username - Email address for Bugzilla user account 32 | - password - Password for the user account 33 | - central_repository - Set to true to enable closing bugs and commenting on commits that were 34 | already pushed to another user's repository 35 | -------------------------------------------------------------------------------- /services/twilio.rb: -------------------------------------------------------------------------------- 1 | class Service::Twilio < Service 2 | string :account_sid, :from_phone, :to_phone 3 | boolean :master_only 4 | password :auth_token 5 | 6 | def receive_push 7 | check_configuration_options(data) 8 | 9 | sms_body = "#{payload['pusher']['name']} has pushed #{payload['commits'].size} commit(s) to #{payload['repository']['name']}" 10 | send_message(data, sms_body) if send_notification?(data) 11 | end 12 | 13 | private 14 | 15 | def send_notification?(data) 16 | notify_user = true 17 | if data['master_only'].to_i == 1 && branch_name != 'master' 18 | notify_user = false 19 | end 20 | notify_user 21 | end 22 | 23 | def check_configuration_options(data) 24 | raise_config_error 'Account SID must be set' if data['account_sid'].blank? 25 | raise_config_error 'Authorization token must be set' if data['auth_token'].blank? 26 | raise_config_error 'Twilio-enabled phone number or short code must be set' if data['from_phone'].blank? 27 | raise_config_error 'Destination phone number must be set' if data['to_phone'].blank? 28 | end 29 | 30 | def send_message(data, message) 31 | client = ::Twilio::REST::Client.new(data['account_sid'], data['auth_token']) 32 | client.account.sms.messages.create( 33 | :from => data['from_phone'], 34 | :to => data['to_phone'], 35 | :body => message 36 | ) 37 | end 38 | end 39 | -------------------------------------------------------------------------------- /lib/events/pull_request_helpers.rb: -------------------------------------------------------------------------------- 1 | module Service::PullRequestHelpers 2 | include Service::HelpersWithRepo, 3 | Service::HelpersWithActions 4 | 5 | def pull 6 | @pull ||= self.class.objectify(payload['pull_request']) 7 | end 8 | 9 | def summary_url 10 | pull.html_url 11 | end 12 | 13 | def summary_message 14 | base_ref = pull.base.label.split(':').last 15 | head_ref = pull.head.label.split(':').last 16 | 17 | "[%s] %s opened pull request #%d (%s -> %s): %s. %s" % [ 18 | repo.name, 19 | pull.user.login, 20 | pull.number, 21 | base_ref, 22 | head_ref != base_ref ? head_ref : pull.head.label, 23 | pull.title, 24 | pull.html_url] 25 | rescue 26 | raise_config_error "Unable to build message: #{$!.to_s}" 27 | end 28 | 29 | def self.sample_payload 30 | { 31 | "action" => "opened", 32 | "pull_request" => { 33 | "number" => 5, 34 | "commits" => 1, 35 | "state" => "open", 36 | "title" => "booya", 37 | "body" => "boom town", 38 | "user" => { "login" => "mojombo" }, 39 | "head" => {"label" => "foo:feature"}, 40 | "base" => {"label" => "mojombo:master"} 41 | }, 42 | "repository" => { 43 | "name" => "grit", 44 | "url" => "http://github.com/mojombo/grit", 45 | "owner" => { "login" => "mojombo" } 46 | } 47 | } 48 | end 49 | end 50 | 51 | -------------------------------------------------------------------------------- /services/ontime.rb: -------------------------------------------------------------------------------- 1 | class Service::OnTime < Service 2 | string :ontime_url, :api_key 3 | 4 | self.title = 'OnTime' 5 | 6 | def receive_push 7 | if data['ontime_url'].to_s.empty? 8 | raise_config_error "No OnTime URL to connect to." 9 | elsif data['api_key'].to_s.empty? 10 | raise_config_error "No API Key." 11 | end 12 | 13 | # We're just going to send back the entire payload and process it in OnTime. 14 | http.url_prefix = data['ontime_url'] 15 | 16 | # Hash the data, it has to be hexdigest in order to have the same hash value in .NET 17 | hash_data = Digest::SHA256.hexdigest(payload.to_json + data['api_key']) 18 | 19 | resp = http_get "api/version" 20 | version = JSON.parse(resp.body)['data'] 21 | 22 | if (version['major'] == 11 and version['minor'] >= 1) or version['major'] > 11 23 | result = http_post "api/github", :payload => payload.to_json, :hash_data => hash_data, :source => :github 24 | else 25 | raise_config_error "Unexpected API version. Please update to the latest version of OnTime to use this service." 26 | end 27 | 28 | verify_response(result) 29 | end 30 | 31 | def verify_response(res) 32 | case res.status 33 | when 200..299 34 | when 403, 401, 422 then raise_config_error("Invalid Credentials") 35 | when 404, 301, 302 then raise_config_error("Invalid URL") 36 | else raise_config_error("HTTP: #{res.status}") 37 | end 38 | end 39 | end 40 | 41 | -------------------------------------------------------------------------------- /services/socialcast.rb: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | class Service::Socialcast < Service 3 | string :api_domain, :group_id, :username 4 | password :password 5 | def receive_push 6 | repository = payload['repository']['name'] 7 | group_id = (data['group_id'].nil? || data['group_id'] == '') ? '' : data['group_id'] 8 | kind_symbol = Hash["added" => "+", "modified" => "Δ", "removed" => "-"] 9 | s_if_plural = (payload['commits'].length > 1) ? 's' : '' 10 | title = "#{payload['commits'].length} commit#{s_if_plural} pushed to Github repo [#{repository}]" 11 | message = "" 12 | 13 | payload['commits'].each_with_index do |commit, i| 14 | timestamp = Date.parse(commit['timestamp']) 15 | heading = "√#{i+1} by #{commit['author']['name']} at #{timestamp}" 16 | message << "#{heading}\n" 17 | heading.length.times do 18 | message << "-" 19 | end 20 | message << "\n#{commit['url']}\n#{commit['message']}\n" 21 | 22 | %w(added modified removed).each do |kind| 23 | commit[kind].each do |filename| 24 | message << "#{kind_symbol[kind]} '#{filename}'\n" 25 | end 26 | end 27 | 28 | message << "\n" 29 | end 30 | 31 | http.ssl[:verify] = false 32 | http.basic_auth(data['username'], data['password']) 33 | http_post "https://#{data['api_domain']}/api/messages.xml", 34 | 'message[title]' => title, 35 | 'message[body]' => message, 36 | 'message[group_id]' => group_id 37 | end 38 | end 39 | 40 | -------------------------------------------------------------------------------- /docs/amqp: -------------------------------------------------------------------------------- 1 | AMQP 2 | ======== 3 | 4 | This service lets you publish push and commit messages to a message broker 5 | (like RabbitMQ) via the AMQP protocol. 6 | 7 | 8 | Install Notes 9 | ------------- 10 | 11 | 1. Host is the hostname of the AMQP broker 12 | 2. Port is the port to connect (AMQP default is 5672) 13 | 3. Vhost is the vhost to use while publishing (default is '/') 14 | 4. Exchange is the exchange to use while publishing 15 | * Note that the exchange is a durable topic exchange 16 | ** Future versions may allow you to configure this 17 | 5. Username is the user to use when publishing to the exchange 18 | 6. Password is the pasword to use when publishing to the exchange 19 | * Note that SSL isn't supported yet 20 | 21 | Messages are sent for a push with the following routing key format: 22 | "github.push.#{owner}.#{repo}.#{ref}" 23 | where: 24 | owner = payload['repository']['owner']['name'] 25 | repo = payload['repository']['name'] 26 | ref = payload['ref_name'] 27 | 28 | Messages are also sent for each commit in a push, with the following routing 29 | key format: 30 | "github.commit.#{owner}.#{repo}.#{ref}.#{author}" 31 | where: 32 | author = commit['author']['email'] 33 | (other fields are the same as above) 34 | 35 | 36 | Developer Notes 37 | --------------- 38 | 39 | data 40 | - host 41 | - port 42 | - vhost 43 | - exchange 44 | - username 45 | - password 46 | 47 | payload 48 | - refer to docs/github_payload 49 | -------------------------------------------------------------------------------- /test/gemnasium_test.rb: -------------------------------------------------------------------------------- 1 | require File.expand_path("../helper", __FILE__) 2 | 3 | class GemnasiumTest < Service::TestCase 4 | def setup 5 | @stubs = Faraday::Adapter::Test::Stubs.new 6 | end 7 | 8 | def test_stripped_user 9 | svc = service("user" => " laserlemon ") 10 | assert_equal "laserlemon", svc.user 11 | end 12 | 13 | def test_stripped_token 14 | svc = service("token" => " abc ") 15 | assert_equal "abc", svc.token 16 | end 17 | 18 | def test_downcased_token 19 | svc = service("token" => "ABC") 20 | assert_equal "abc", svc.token 21 | end 22 | 23 | def test_body 24 | svc = service({}, {"pay" => "load"}) 25 | assert_equal '{"pay":"load"}', svc.body 26 | end 27 | 28 | def test_signature 29 | svc = service({"token" => "abc"}, {"pay" => "load"}) 30 | assert_equal "f329edd3feef6b4504c15ee4af6cb65ba28de90ba690001e3a548c5dddf80990", svc.signature 31 | end 32 | 33 | def test_push 34 | svc = service({"user" => "laserlemon", "token" => "abc"}, {"pay" => "load"}) 35 | 36 | @stubs.post "/repositories/hook" do |env| 37 | assert_equal "gemnasium.com", env[:url].host 38 | assert_equal "application/json", env[:request_headers][:content_type] 39 | assert_equal "Basic bGFzZXJsZW1vbjpmMzI5ZWRkM2ZlZWY2YjQ1MDRjMTVlZTRhZjZjYjY1YmEyOGRlOTBiYTY5MDAwMWUzYTU0OGM1ZGRkZjgwOTkw", env[:request_headers][:authorization] 40 | assert_equal '{"pay":"load"}', env[:body] 41 | end 42 | 43 | svc.receive_push 44 | end 45 | 46 | private 47 | def service(data, payload = payload) 48 | super(Service::Gemnasium, data, payload) 49 | end 50 | end 51 | -------------------------------------------------------------------------------- /test/email_test.rb: -------------------------------------------------------------------------------- 1 | require File.expand_path('../helper', __FILE__) 2 | 3 | class EmailTest < Service::TestCase 4 | def test_push 5 | svc = service( 6 | {'address' => 'a'}, 7 | payload) 8 | 9 | svc.receive_push 10 | 11 | msg, from, to = svc.messages.shift 12 | assert_match "noreply@github.com", from 13 | assert_equal 'a', to 14 | 15 | assert_nil svc.messages.shift 16 | end 17 | 18 | def test_push_from_author 19 | svc = service( 20 | {'address' => 'a', 'send_from_author' => '1'}, 21 | payload) 22 | 23 | svc.receive_push 24 | 25 | msg, from, to = svc.messages.shift 26 | assert_match 'tom@mojombo.com', from 27 | assert_equal 'a', to 28 | 29 | assert_nil svc.messages.shift 30 | end 31 | 32 | def test_smtp_settings 33 | svc = service( 34 | {'address' => 'a'}, 35 | 'payload') 36 | svc.email_config = {'address' => 'a', 'port' => '1', 'domain' => 'd'} 37 | assert_equal ['a', 1, 'd'], svc.smtp_settings 38 | end 39 | 40 | def test_smtp_settings_with_auth 41 | svc = service( 42 | {'address' => 'a'}, 43 | 'payload') 44 | svc.email_config = {'address' => 'a', 'port' => '1', 'domain' => 'd', 45 | 'authentication' => 'au', 'user_name' => 'u', 'password' => 'p'} 46 | assert_equal ['a', 1, 'd', 'u', 'p', 'au'], svc.smtp_settings 47 | end 48 | 49 | def service(*args) 50 | svc = super Service::Email, *args 51 | def svc.messages 52 | @messages ||= [] 53 | end 54 | 55 | def svc.send_message(msg, from, to) 56 | messages << [msg, from, to] 57 | end 58 | svc 59 | end 60 | end 61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /services/web.rb: -------------------------------------------------------------------------------- 1 | class Service::Web < Service 2 | HMAC_DIGEST = OpenSSL::Digest::Digest.new('sha1') 3 | 4 | string :url, 5 | # adds a X-Hub-Signature of the body content 6 | # X-Hub-Signature: sha1=.... 7 | :secret, 8 | 9 | # old hooks send form params ?payload=JSON(...) 10 | # new hooks should set content_type == 'json' 11 | :content_type 12 | 13 | boolean :insecure_ssl # :( 14 | 15 | def receive_event 16 | url = data['url'].to_s 17 | url.gsub! /\s/, '' 18 | 19 | if url.empty? 20 | raise_config_error "Invalid URL: #{url.inspect}" 21 | end 22 | 23 | if url !~ /^https?\:\/\// 24 | url = "http://#{url}" 25 | end 26 | 27 | # set this so that basic auth is added, 28 | # and GET params are added to the POST body 29 | http.url_prefix = url 30 | http.headers['X-GitHub-Event'] = event.to_s 31 | 32 | if data['insecure_ssl'].to_i == 1 33 | http.ssl[:verify] = false 34 | end 35 | 36 | body = if data['content_type'] == 'json' 37 | http.headers['content-type'] = 'application/json' 38 | JSON.generate(payload) 39 | else 40 | http.headers['content-type'] = 'application/x-www-form-urlencoded' 41 | Faraday::Utils.build_nested_query( 42 | http.params.merge(:payload => JSON.generate(payload))) 43 | end 44 | 45 | if !(secret = data['secret'].to_s).empty? 46 | http.headers['X-Hub-Signature'] = 47 | 'sha1='+OpenSSL::HMAC.hexdigest(HMAC_DIGEST, secret, body) 48 | end 49 | 50 | http_post url, body 51 | rescue Addressable::URI::InvalidURIError => err 52 | raise_config_error err.to_s 53 | end 54 | end 55 | 56 | -------------------------------------------------------------------------------- /test/fog_bugz_test.rb: -------------------------------------------------------------------------------- 1 | require File.expand_path('../helper', __FILE__) 2 | 3 | class FogBugzTest < Service::TestCase 4 | def setup 5 | @stubs = Faraday::Adapter::Test::Stubs.new 6 | end 7 | 8 | def test_push 9 | url = "/fb?" 10 | url << "ixBug=1&" 11 | url << "ixRepository=r&" 12 | url << "sFile=master%2Flib%2Fgrit%2Fgrit.rb&" 13 | url << "sNew=06f63b43050935962f84fe54473a7c5de7977325&" 14 | url << "sPrev=4c8124ffcf4039d292442eeccabdeca5af5c5017" 15 | 16 | @stubs.get url do |env| 17 | [200, {}, ''] 18 | end 19 | 20 | svc = service( 21 | {'cvssubmit_url' => '/fb', 'fb_repoid' => 'r'}, 22 | modified_payload) 23 | svc.receive_push 24 | end 25 | 26 | def test_push_for_fogbugz_6 27 | @stubs.get '/fb' do |env| 28 | assert_equal '1', env[:params]['ixBug'] 29 | assert_equal 'master/lib/grit/grit.rb', env[:params]['sFile'] 30 | assert_equal '06f63b43050935962f84fe54473a7c5de7977325', env[:params]['sNew'] 31 | assert_equal '4c8124ffcf4039d292442eeccabdeca5af5c5017', env[:params]['sPrev'] 32 | assert_equal 'grit', env[:params]['sRepo'] 33 | [200, {}, ''] 34 | end 35 | 36 | svc = service( 37 | {'cvssubmit_url' => '/fb', 'fb_repoid' => 'r', 'fb_version' => '6'}, 38 | modified_payload) 39 | svc.receive_push 40 | end 41 | 42 | def service(*args) 43 | super Service::FogBugz, *args 44 | end 45 | 46 | def modified_payload 47 | pay = payload 48 | pay['commits'].pop 49 | pay['commits'].pop 50 | pay['commits'][0]['modified'].pop 51 | pay['commits'][0]['modified'].pop 52 | pay 53 | end 54 | end 55 | 56 | 57 | -------------------------------------------------------------------------------- /services/jira.rb: -------------------------------------------------------------------------------- 1 | class Service::Jira < Service 2 | string :server_url, :api_version, :username 3 | password :password 4 | 5 | def receive_push 6 | payload['commits'].each do |commit| 7 | next if commit['message'] =~ /^x / 8 | 9 | comment_body = "#{commit['message']}\n#{commit['url']}" 10 | 11 | commit['message'].match(/\[#(.+)\]/) 12 | # Don't need to continue if we don't have a commit message containing JIRA markup 13 | next unless $1 14 | 15 | jira_markup = $1.split 16 | issue_id = jira_markup.shift 17 | 18 | changeset = { :comment => { :body => comment_body } } 19 | 20 | jira_markup.each do |entry| 21 | key, value = entry.split(':') 22 | 23 | if key =~ /(?i)status|(?i)transition/ 24 | changeset.merge!(:transition => value.to_i) 25 | elsif key =~ /(?i)resolution/ 26 | changeset.merge!(:fields => { :resolution => value.to_i }) 27 | else 28 | changeset.merge!(:fields => { key.to_sym => "Resolved" }) 29 | end 30 | end 31 | 32 | # Don't need to continue if we don't have a transition to perform 33 | next unless changeset.has_key?(:transition) 34 | 35 | begin 36 | # :( 37 | http.ssl[:verify] = false 38 | 39 | http.basic_auth data['username'], data['password'] 40 | http.headers['Content-Type'] = 'application/json' 41 | res = http_post '%s/rest/api/%s/issue/%s/transitions' % [data['server_url'], data['api_version'], issue_id], 42 | changeset.to_json 43 | rescue URI::InvalidURIError 44 | raise_config_error "Invalid server_hostname: #{data['server_url']}" 45 | end 46 | end 47 | end 48 | end 49 | -------------------------------------------------------------------------------- /services/twitter.rb: -------------------------------------------------------------------------------- 1 | class Service::Twitter < Service 2 | string :token, :secret 3 | boolean :digest 4 | 5 | def receive_push 6 | statuses = [ ] 7 | repository = payload['repository']['name'] 8 | 9 | if data['digest'] == '1' 10 | commit = payload['commits'][-1] 11 | author = commit['author'] || {} 12 | tiny_url = shorten_url("#{payload['repository']['url']}/commits/#{ref_name}") 13 | status = "[#{repository}] #{tiny_url} #{author['name']} - #{payload['commits'].length} commits" 14 | status.length >= 140 ? statuses << status[0..136] + '...' : statuses << status 15 | else 16 | payload['commits'].each do |commit| 17 | author = commit['author'] || {} 18 | tiny_url = shorten_url(commit['url']) 19 | status = "[#{repository}] #{tiny_url} #{author['name']} - #{commit['message']}" 20 | status.length >= 140 ? statuses << status[0..136] + '...' : statuses << status 21 | end 22 | end 23 | 24 | statuses.each do |status| 25 | post(status) 26 | end 27 | end 28 | 29 | def post(status) 30 | params = { 'status' => status, 'source' => 'github' } 31 | 32 | access_token = ::OAuth::AccessToken.new(consumer, data['token'], data['secret']) 33 | consumer.request(:post, "/1/statuses/update.json", 34 | access_token, { :scheme => :query_string }, params) 35 | end 36 | 37 | def consumer_key 38 | secrets['twitter']['key'] 39 | end 40 | 41 | def consumer_secret 42 | secrets['twitter']['secret'] 43 | end 44 | 45 | def consumer 46 | @consumer ||= ::OAuth::Consumer.new(consumer_key, consumer_secret, 47 | {:site => "http://api.twitter.com"}) 48 | end 49 | end 50 | -------------------------------------------------------------------------------- /services/fog_bugz.rb: -------------------------------------------------------------------------------- 1 | class Service::FogBugz < Service 2 | string :cvssubmit_url, :fb_repoid, :fb_version 3 | 4 | def receive_push 5 | if (fb_url = data['cvssubmit_url']).blank? 6 | raise_config_error "Invalid FogBugz URL" 7 | end 8 | 9 | # FIXME 10 | http.ssl[:verify] = false 11 | 12 | repository = payload['repository']['name'] 13 | branch = branch_name 14 | before = payload['before'] 15 | 16 | payload['commits'].each do |commit| 17 | commit_id = commit['id'] 18 | message = commit["message"] 19 | files = commit["removed"] | commit["added"] | commit["modified"] 20 | 21 | # look for a bug id in each line of the commit message 22 | bug_list = [] 23 | message.split("\n").each do |line| 24 | # match variants of bugids or cases 25 | if (line =~ /\s*(?:Bug[zs]*\s*IDs*\s*|Case[s]*)[#:; ]+((\d+[ ,:;#]*)+)/i) 26 | bug_list << $1.to_i 27 | end 28 | end 29 | 30 | # for each found bugzid, submit the files to fogbugz. 31 | bug_list.each do |fb_bugzid| 32 | files.each do |f| 33 | # build the GET request, and send it to fogbugz 34 | params = {:ixBug => fb_bugzid, :sFile => "#{branch}/#{f}", :sPrev => before, :sNew => commit_id} 35 | if data['fb_version'] == '6' 36 | # FogBugz 6 created repositories automatically upon source checkin based on "sRepo" 37 | params[:sRepo] = repository 38 | else 39 | # FogBugz 7 and later requires you to create the repo in FogBugz and supply "ixRepository" here 40 | params[:ixRepository] = data['fb_repoid'] 41 | end 42 | 43 | http_get fb_url, params 44 | end 45 | end 46 | end 47 | end 48 | end 49 | -------------------------------------------------------------------------------- /test/harvest_test.rb: -------------------------------------------------------------------------------- 1 | require File.expand_path('../helper', __FILE__) 2 | 3 | class HarvestTest < Service::TestCase 4 | def setup 5 | @stubs = Faraday::Adapter::Test::Stubs.new 6 | end 7 | 8 | def test_push 9 | @stubs.get "/daily" do |env| 10 | assert_equal 'sub.harvestapp.com', env[:url].host 11 | assert_equal 'https', env[:url].scheme 12 | assert_equal 'application/xml', env[:request_headers]["Content-Type"] 13 | assert_equal 'application/xml', env[:request_headers]["Accept"] 14 | assert_equal basic_auth(:rick, :monkey), env[:request_headers]['authorization'] 15 | [200, {}, %( 16 | 17 | 18 | 19 | timer 20 | 21 | notes 22 | 1 23 | 24 | 25 | 26 | )] 27 | end 28 | 29 | @stubs.post "/daily/update/timer" do |env| 30 | assert_equal 'sub.harvestapp.com', env[:url].host 31 | assert_equal 'https', env[:url].scheme 32 | assert_equal 'application/xml', env[:request_headers]["Content-Type"] 33 | assert_equal 'application/xml', env[:request_headers]["Accept"] 34 | assert_equal basic_auth(:rick, :monkey), env[:request_headers]['authorization'] 35 | assert_match /grit/, env[:body] 36 | assert_match /hours>1<\/hours/, env[:body] 37 | [200, {}, '{}'] 38 | end 39 | 40 | svc = service({ 41 | 'subdomain' => 'sub', 42 | 'username' => 'rick', 43 | 'ssl' => 1, 44 | 'password' => 'monkey' 45 | }, payload) 46 | def svc.shorten_url(*args) 47 | 'short' 48 | end 49 | 50 | svc.receive_push 51 | end 52 | 53 | def service(*args) 54 | super Service::Harvest, *args 55 | end 56 | end 57 | 58 | 59 | -------------------------------------------------------------------------------- /services/yammer.rb: -------------------------------------------------------------------------------- 1 | class Service::Yammer < Service 2 | string :group_id, :consumer_key, :consumer_secret, 3 | :access_token, :access_secret 4 | boolean :digest 5 | 6 | def receive_push 7 | statuses = [ ] 8 | repository = payload['repository']['name'] 9 | 10 | if data['digest'] == '1' 11 | commit = payload['commits'][-1] 12 | tiny_url = shorten_url("#{payload['repository']['url']}/commits/#{ref_name}") 13 | statuses << "@#{commit['author']['name']} pushed #{payload['commits'].length}. #{tiny_url} \##{repository}" 14 | else 15 | payload['commits'].each do |commit| 16 | tiny_url = shorten_url(commit['url']) 17 | statuses << "#{commit['message']} (committer: @#{commit['author']['name']}) #{tiny_url} \##{repository}" 18 | end 19 | end 20 | 21 | statuses.each do |status| 22 | params = { :body => status } 23 | params['group_id'] = data['group_id'] unless data['group_id'].to_s.empty? 24 | begin 25 | send_message params 26 | rescue 27 | if $!.to_s =~ /authentication failed/i 28 | raise_config_error "Invalid username or password" 29 | else 30 | raise 31 | end 32 | end 33 | end 34 | end 35 | 36 | def send_message(params) 37 | yammer.message(:post, params) 38 | rescue RuntimeError => boom 39 | if boom.to_s =~ /Bad Request/i 40 | raise_config_error boom.to_s 41 | else 42 | raise 43 | end 44 | end 45 | 46 | def yammer 47 | @yammer ||= ::Yammer::Client.new \ 48 | :consumer => { 49 | :key => data['consumer_key'], 50 | :secret => data['consumer_secret']}, 51 | :access => { 52 | :token => data['access_token'], 53 | :secret => data['access_secret']} 54 | end 55 | end 56 | 57 | -------------------------------------------------------------------------------- /test/youtrack_test.rb: -------------------------------------------------------------------------------- 1 | require File.expand_path('../helper', __FILE__) 2 | 3 | class YouTrackTest < Service::TestCase 4 | def setup 5 | @stubs = Faraday::Adapter::Test::Stubs.new 6 | end 7 | 8 | def test_push 9 | @stubs.post "/abc/rest/user/login" do |env| 10 | assert_equal 'yt.com', env[:url].host 11 | assert_equal 'u', env[:params]["login"] 12 | assert_equal 'p', env[:params]["password"] 13 | [200, {'Set-Cookie' => 'sc'}, ''] 14 | end 15 | 16 | @stubs.get "/abc/rest/admin/user" do |env| 17 | assert_equal 'yt.com', env[:url].host 18 | assert_equal 'sc', env[:request_headers]['Cookie'] 19 | assert_equal 'tom@mojombo.com', env[:params]['q'] 20 | assert_equal 'c', env[:params]['group'] 21 | assert_equal '0', env[:params]['start'] 22 | [200, {}, %()] 23 | end 24 | 25 | @stubs.get "/abc/rest/admin/user/mojombo" do |env| 26 | assert_equal 'yt.com', env[:url].host 27 | assert_equal 'sc', env[:request_headers]['Cookie'] 28 | [200, {}, %()] 29 | end 30 | 31 | @stubs.post "/abc/rest/issue/case-1/execute" do |env| 32 | assert_equal 'yt.com', env[:url].host 33 | assert_equal 'sc', env[:request_headers]['Cookie'] 34 | assert_equal 'zomg omg', env[:params]['command'] 35 | assert_equal 'mojombo', env[:params]['runAs'] 36 | [200, {}, ''] 37 | end 38 | 39 | hash = payload 40 | hash['commits'].first['message'].sub! /Case#1/, '#case-1 zomg omg' 41 | 42 | svc = service({'base_url' => 'http://yt.com/abc', 'committers' => 'c', 43 | 'username' => 'u', 'password' => 'p'}, hash) 44 | svc.receive_push 45 | end 46 | 47 | def service(*args) 48 | super Service::YouTrack, *args 49 | end 50 | end 51 | 52 | -------------------------------------------------------------------------------- /test/jabber_test.rb: -------------------------------------------------------------------------------- 1 | require File.expand_path('../helper', __FILE__) 2 | require 'stringio' 3 | 4 | class JabberTest < Service::TestCase 5 | class FakeJabber 6 | class Client 7 | attr_reader :conference 8 | def initialize(conference) 9 | @conference = conference 10 | end 11 | def active?() true end 12 | end 13 | 14 | attr_accessor :accept_subscriptions 15 | attr_reader :delivered 16 | 17 | def initialize 18 | @delivered = [] 19 | end 20 | 21 | def deliver_deferred(*args) 22 | @delivered << args 23 | end 24 | end 25 | 26 | def test_push 27 | svc = service({'user' => 'a,b , c , b', 'muc' => 'e,f , g, f'}, payload) 28 | svc.im = FakeJabber.new 29 | svc.mucs['e'] = FakeJabber::Client.new('e') 30 | svc.mucs['f'] = FakeJabber::Client.new('f') 31 | svc.mucs['g'] = FakeJabber::Client.new('g') 32 | svc.receive_push 33 | 34 | assert svc.im.accept_subscriptions 35 | 36 | assert msg = svc.im.delivered.shift 37 | assert_equal 'a', msg[0] 38 | assert_equal :chat, msg[2] 39 | 40 | assert msg = svc.im.delivered.shift 41 | assert_equal 'b', msg[0] 42 | assert_equal :chat, msg[2] 43 | 44 | assert msg = svc.im.delivered.shift 45 | assert_equal 'c', msg[0] 46 | assert_equal :chat, msg[2] 47 | 48 | #assert msg = svc.im.delivered.shift 49 | #assert_equal 'e', msg[0] 50 | #assert_equal :groupchat, msg[2] 51 | 52 | #assert msg = svc.im.delivered.shift 53 | #assert_equal 'f', msg[0] 54 | #assert_equal :groupchat, msg[2] 55 | 56 | #assert msg = svc.im.delivered.shift 57 | #assert_equal 'g', msg[0] 58 | #assert_equal :groupchat, msg[2] 59 | 60 | assert_nil svc.im.delivered.shift 61 | end 62 | 63 | def service(*args) 64 | super Service::Jabber, *args 65 | end 66 | end 67 | 68 | 69 | -------------------------------------------------------------------------------- /services/active_collab.rb: -------------------------------------------------------------------------------- 1 | require 'bigdecimal' 2 | require 'date' 3 | require 'jcode' if RUBY_VERSION < '1.9' 4 | require 'net/http' 5 | require 'net/https' 6 | require 'time' 7 | require 'rexml/document' 8 | require 'uri' 9 | 10 | class Service::ActiveCollab < Service 11 | string :url, :token, :project_id, :milestone_id, :category_id 12 | 13 | def receive_push 14 | if data['url'].to_s.empty? 15 | raise_config_error "Need an activeCollab Url" 16 | end 17 | if data['token'].to_s.empty? 18 | raise_config_error "Need an API Token" 19 | end 20 | if data['project_id'].to_s.empty? 21 | raise_config_error "Need a Project ID" 22 | end 23 | 24 | statuses = [ ] 25 | repository = payload['repository']['name'] 26 | 27 | push_message = "New Commits made in #{payload['pusher']['name']} / #{repository}" 28 | 29 | payload['commits'].each do |commit| 30 | author = commit['author'] || {} 31 | tiny_url = shorten_url(commit['url']) 32 | statuses << "[#{repository}] #{tiny_url} #{author['name']} - #{commit['message']}" 33 | end 34 | 35 | build_message = statuses * "\n" 36 | 37 | http.url_prefix = data['url'] 38 | http.headers['Accept'] = 'application/xml' 39 | 40 | http.post do |req| 41 | req.params['path_info'] = "projects/#{data['project_id']}/discussions/add" 42 | req.params['token'] = data['token'] 43 | req.body = params(push_message, build_message) 44 | end 45 | end 46 | 47 | def params(name, message) 48 | { 49 | "submitted" => "submitted", 50 | "discussion[name]" => "#{name}", 51 | "discussion[body]" => "#{message}", 52 | "discussion[milestone_id]" => data['milestone_id'], 53 | "discussion[parent_id]" => data['category_id'], 54 | "discussion[visibility]" => 1, 55 | } 56 | end 57 | end 58 | -------------------------------------------------------------------------------- /docs/target_process: -------------------------------------------------------------------------------- 1 | TargetProcess 2 | ============= 3 | 4 | ------------------------------------------- 5 | TargetProcess - GitHub Integration Overview 6 | ------------------------------------------- 7 | 8 | Integration with TargetProcess allows GitHub user to change current entity states 9 | and add comments directly from their commit messages. 10 | 11 | -------------- 12 | Install Notes 13 | -------------- 14 | 15 | 1. TargetProcess Requirements 16 | 17 | - Requires TargetProcess version 2.22.4.19887 or newer. 18 | 19 | - Your TargetProcess must should be accessible from the internet. 20 | 21 | - Committer's email addresses in GitHub and TargetProcess should be the same. 22 | 23 | 2. Settings in GitHub 24 | 25 | In the GitHub integration config, the following settings should be provided: 26 | 27 | - TargetProcess Server URL 28 | 29 | - A project admin's account credentials to access your TargetProcess server. 30 | 31 | - The project id from your TargetProcess project that the GitHub repository 32 | should map to (this can be found on the "Projects" list within TargetProcess) 33 | 34 | --------------------- 35 | Commit Message Syntax 36 | --------------------- 37 | 38 | General comment format for adding comments and/or changing entity states: 39 | 40 | 41 | #[Entity ID]: 42 | Eg: Fixed out of memory exceptions #1221:Fixed 43 | 44 | 45 | The entire line will appear as a comment in your User Story, Bug, Feature, or Task; and the entity's 46 | state will be changed to the state name, if specified. A new state is not required, and an 47 | Assignable's state will not change unless it is specified. Entity ID is required. This 48 | text sequence can appear anywhere in your commit message. 49 | 50 | 51 | Developer Notes 52 | --------------- 53 | 54 | data 55 | -base_url 56 | -username 57 | -password 58 | -project_id 59 | 60 | 61 | -------------------------------------------------------------------------------- /vendor/internal-gems/yammer4r-0.1.5/spec/yammer/client_spec.rb: -------------------------------------------------------------------------------- 1 | require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') 2 | require 'ostruct' 3 | 4 | describe Yammer::Client do 5 | 6 | context "creating" do 7 | 8 | before(:each) do 9 | mock_consumer = mock(OAuth::Consumer) 10 | OAuth::Consumer.stub!("new").and_return(mock_consumer) 11 | @mock_http = mock("http") 12 | mock_consumer.stub!("http").and_return(@mock_http) 13 | end 14 | 15 | it "can be configured to be verbose" do 16 | @mock_http.should_receive("set_debug_output").with($stderr) 17 | Yammer::Client.new(:consumer => {}, :access => {}, :verbose => true) 18 | end 19 | 20 | it "should not be configured to be verbose unless asked to be" do 21 | @mock_http.should_not_receive("set_debug_output") 22 | Yammer::Client.new(:consumer => {}, :access => {}) 23 | end 24 | 25 | it "should not be configured to be verbose if asked not to be" do 26 | @mock_http.should_not_receive("set_debug_output") 27 | Yammer::Client.new(:consumer => {}, :access => {}, :verbose => false) 28 | end 29 | 30 | end 31 | 32 | context "users" do 33 | 34 | before(:each) do 35 | @mock_access_token = mock(OAuth::AccessToken) 36 | @response = OpenStruct.new(:code => 200, :body => '{}') 37 | OAuth::AccessToken.stub!("new").and_return(@mock_access_token) 38 | @client = Yammer::Client.new(:consumer => {}, :access => {}) 39 | end 40 | 41 | it "should request the first page by default" do 42 | @mock_access_token.should_receive("get").with("/api/v1/users.json").and_return(@response) 43 | @client.users 44 | end 45 | 46 | it "can request a specified page" do 47 | @mock_access_token.should_receive("get").with("/api/v1/users.json?page=2").and_return(@response) 48 | @client.users(:page => 2) 49 | end 50 | 51 | end 52 | 53 | end -------------------------------------------------------------------------------- /services/bamboo.rb: -------------------------------------------------------------------------------- 1 | class Service::Bamboo < Service 2 | string :base_url, :build_key, :username 3 | password :password 4 | 5 | def receive_push 6 | verify_config 7 | authenticated { |token| trigger_build(token) } 8 | rescue SocketError => e 9 | if e.to_s =~ /getaddrinfo: Name or service not known/ 10 | raise_config_error("Invalid Bamboo host name") 11 | else 12 | raise 13 | end 14 | end 15 | 16 | def trigger_build(token) 17 | res = http_post "api/rest/executeBuild.action", 18 | "auth=#{CGI.escape(token)}&buildKey=#{CGI.escape(build_key)}" 19 | msg = XmlSimple.xml_in(res.body) 20 | raise_config_error msg["error"] if msg["error"] 21 | end 22 | 23 | def authenticated 24 | token = login 25 | yield token 26 | ensure 27 | logout(token) 28 | end 29 | 30 | def login 31 | res = http_post "api/rest/login.action", 32 | "username=#{CGI.escape(username)}&password=#{CGI.escape(password)}" 33 | case res.status 34 | when 200..204 35 | XmlSimple.xml_in(res.body)['auth'].first 36 | when 403, 401, 422 then raise_config_error("Invalid credentials") 37 | when 404, 301 then raise_config_error("Invalid Bamboo project URL") 38 | end 39 | end 40 | 41 | def logout(token) 42 | return unless token 43 | http_post "api/rest/logout.action", "auth=#{CGI.escape(token)}" 44 | end 45 | 46 | def verify_config 47 | %w(base_url build_key username password).each do |var| 48 | raise_config_error "Missing configuration: #{var}" if send(var).to_s.empty? 49 | end 50 | http.ssl[:verify] = false 51 | http.url_prefix = base_url 52 | end 53 | 54 | def base_url 55 | @base_url ||= data['base_url'].gsub(/\/$/, '') 56 | end 57 | 58 | def build_key 59 | @build_key ||= data['build_key'] 60 | end 61 | 62 | def username 63 | @username ||= data['username'] 64 | end 65 | 66 | def password 67 | @password ||= data['password'] 68 | end 69 | end 70 | -------------------------------------------------------------------------------- /services/harvest.rb: -------------------------------------------------------------------------------- 1 | require 'base64' 2 | require 'bigdecimal' 3 | require 'date' 4 | require 'jcode' if RUBY_VERSION < '1.9' 5 | require 'time' 6 | require 'rexml/document' 7 | 8 | class Service::Harvest < Service 9 | string :subdomain, :username 10 | password :password 11 | boolean :ssl 12 | 13 | def receive_push 14 | if data['username'].to_s.empty? 15 | raise_config_error "Needs a username" 16 | end 17 | if data['password'].to_s.empty? 18 | raise_config_error "Needs a password" 19 | end 20 | 21 | http.basic_auth(data['username'], data['password']) 22 | http.headers['Content-Type'] = 'application/xml' 23 | http.headers['Accept'] = 'application/xml' 24 | http.url_prefix = "http#{:s if data['ssl']}://#{data['subdomain']}.harvestapp.com/" 25 | 26 | statuses = [] 27 | repository = payload['repository']['name'] 28 | 29 | payload['commits'].each do |commit| 30 | author = commit['author'] || {} 31 | tiny_url = shorten_url(commit['url']) 32 | statuses << "[#{repository}] #{tiny_url} #{author['name']} - #{commit['message']}" 33 | end 34 | 35 | messages = messages_from_daily statuses * "\n" 36 | 37 | timer, message = messages.last 38 | http_post "daily/update/#{timer}", message if timer 39 | end 40 | 41 | # Gets the daily day entries, and builds the xml payload for the timer update api. 42 | # 43 | # status - String message build from the commit messages of the push. 44 | # 45 | # Returns an Array of [timer, String xml message] tuples for each day entry. 46 | def messages_from_daily(status) 47 | daily = http_get 'daily' 48 | doc = REXML::Document.new(daily.body) 49 | messages = [] 50 | doc.elements.each('daily/day_entries/day_entry') do |ele| 51 | if ele.elements['timer_started_at'] 52 | messages << [ele.elements['id'].text, 53 | "#{ele.elements['notes'].text}\n#{status}#{ele.elements['hours'].text}"] 54 | end 55 | end 56 | messages 57 | end 58 | end 59 | -------------------------------------------------------------------------------- /services/lighthouse.rb: -------------------------------------------------------------------------------- 1 | class Service::Lighthouse < Service 2 | string :subdomain, :project_id, :token 3 | boolean :private, :send_only_ticket_commits 4 | 5 | def receive_push 6 | # matches string with square braces with content starting with # and a digit. 7 | check_for_lighthouse_flags = /\[#\d.+?\]/ 8 | 9 | payload['commits'].each do |commit| 10 | next if commit['message'] =~ /^x / 11 | next if data['send_only_ticket_commits'] == false && (commit['message'] =~ check_for_lighthouse_flags).nil? 12 | 13 | commit_id = commit['id'] 14 | added = commit['added'].map { |f| ['A', f] } 15 | removed = commit['removed'].map { |f| ['R', f] } 16 | modified = commit['modified'].map { |f| ['M', f] } 17 | diff = YAML.dump(added + removed + modified) 18 | 19 | diff = YAML.dump([]) if data['private'] 20 | 21 | title = "Changeset [%s] by %s" % [commit_id, commit['author']['name']] 22 | body = "#{commit['message']}\n#{commit['url']}" 23 | changeset_xml = <<-XML.strip 24 | 25 | #{CGI.escapeHTML(title)} 26 | #{CGI.escapeHTML(body)} 27 | #{CGI.escapeHTML(diff)} 28 | #{CGI.escapeHTML(commit['author']['name'])} 29 | #{CGI.escapeHTML(commit_id)} 30 | #{CGI.escapeHTML(commit['timestamp'])} 31 | 32 | XML 33 | 34 | account = "http://#{data['subdomain']}.lighthouseapp.com" 35 | 36 | begin 37 | http.basic_auth data['token'], 'x' 38 | http.headers['Content-Type'] = 'application/xml' 39 | http_post '%s/projects/%d/changesets.xml' % [ 40 | "http://#{data['subdomain']}.lighthouseapp.com", data['project_id'].to_i], 41 | changeset_xml 42 | rescue URI::InvalidURIError 43 | raise_config_error "Invalid subdomain: #{data['subdomain']}" 44 | end 45 | end 46 | end 47 | end 48 | -------------------------------------------------------------------------------- /services/campfire.rb: -------------------------------------------------------------------------------- 1 | class Service::Campfire < Service 2 | class << self 3 | attr_accessor :campfire_class 4 | end 5 | 6 | self.campfire_class = Tinder::Campfire 7 | 8 | string :subdomain, :room, :token 9 | boolean :master_only, :play_sound, :long_url 10 | 11 | default_events :push, :pull_request, :issues 12 | 13 | def receive_push 14 | url = data['long_url'].to_i == 1 ? summary_url : shorten_url(summary_url) 15 | messages = [] 16 | messages << "#{summary_message}: #{url}" 17 | messages += commit_messages.first(8) 18 | 19 | if messages.first =~ /pushed 1 new commit/ 20 | messages.shift # drop summary message 21 | messages.first << " ( #{distinct_commits.first['url']} )" 22 | end 23 | 24 | send_messages messages 25 | end 26 | 27 | def receive_pull_request 28 | send_messages summary_message if opened? 29 | end 30 | 31 | alias receive_issues receive_pull_request 32 | 33 | def send_messages(messages) 34 | raise_config_error 'Missing campfire token' if data['token'].to_s.empty? 35 | 36 | return if data['master_only'].to_i == 1 and branch_name != 'master' 37 | 38 | play_sound = data['play_sound'].to_i == 1 39 | 40 | unless room = find_room 41 | raise_config_error 'No such campfire room' 42 | end 43 | 44 | Array(messages).each { |line| room.speak line } 45 | room.play "rimshot" if play_sound && room.respond_to?(:play) 46 | rescue OpenSSL::SSL::SSLError => boom 47 | raise_config_error "SSL Error: #{boom}" 48 | rescue Tinder::AuthenticationFailed => boom 49 | raise_config_error "Authentication Error: #{boom}" 50 | rescue Faraday::Error::ConnectionFailed 51 | raise_config_error "Connection refused- invalid campfire subdomain." 52 | end 53 | 54 | attr_writer :campfire 55 | def campfire 56 | @campfire ||= self.class.campfire_class.new(campfire_domain, :ssl => true, :token => data['token']) 57 | end 58 | 59 | def campfire_domain 60 | data['subdomain'].to_s.sub /\.campfirenow\.com$/i, '' 61 | end 62 | 63 | def find_room 64 | room = campfire.find_room_by_name(data['room']) 65 | rescue StandardError 66 | end 67 | end 68 | -------------------------------------------------------------------------------- /services/convore.rb: -------------------------------------------------------------------------------- 1 | class Service::Convore < Service 2 | string :topic_id, :username 3 | password :password 4 | 5 | def receive_push 6 | raise_config_error "Missing username" if data['username'].to_s == '' 7 | 8 | repository = payload['repository']['name'] 9 | owner = payload['repository']['owner']['name'] 10 | branch = branch_name 11 | commits = payload['commits'] 12 | compare_url = payload['compare'] 13 | commits.reject! { |commit| commit['message'].to_s.strip == '' } 14 | return if commits.empty? 15 | 16 | prefix = "[#{repository}/#{branch}]" 17 | primary, others = commits[0..4], Array(commits[5..-1]) 18 | messages = 19 | primary.map do |commit| 20 | short = commit['message'].split("\n", 2).first 21 | short += ' ...' if short != commit['message'] 22 | "#{prefix} #{short} - #{commit['author']['name']}" 23 | end 24 | 25 | if messages.size > 1 26 | before, after = payload['before'][0..6], payload['after'][0..6] 27 | url = compare_url 28 | summary = 29 | if others.any? 30 | "#{prefix} (+#{others.length} more) commits #{before}...#{after}: #{url}" 31 | else 32 | "#{prefix} commits #{before}...#{after}: #{url}" 33 | end 34 | messages << summary 35 | else 36 | url = commits.first['url'] 37 | messages[0] = "#{messages.first} (#{url})" 38 | end 39 | 40 | http.url_prefix = "https://convore.com/api/topics" 41 | http.basic_auth data['username'], data['password'] 42 | 43 | begin 44 | messages.each do |line| 45 | res = speak(data['topic_id'], line) 46 | if res.status < 200 or res.status > 299 47 | raise_config_error "Convore Error" 48 | end 49 | 50 | body = JSON.parse(res.body) 51 | raise_config_error "Convore Error" if body.include?("error") 52 | end 53 | 54 | rescue Faraday::Error::ConnectionFailed 55 | raise_config_error "Connection refused. Invalid group." 56 | end 57 | end 58 | 59 | def speak(topic_id, line) 60 | http_post "#{data['topic_id']}/messages/create.json", 61 | :message => line 62 | end 63 | end 64 | -------------------------------------------------------------------------------- /test/freckle_test.rb: -------------------------------------------------------------------------------- 1 | require File.expand_path('../helper', __FILE__) 2 | 3 | class FreckleTest < Service::TestCase 4 | def setup 5 | @stubs = Faraday::Adapter::Test::Stubs.new 6 | end 7 | 8 | def test_posts_with_2_entries 9 | data = call_service :push 10 | assert_equal 2, data['entries'].size 11 | end 12 | 13 | def test_includes_auth_token 14 | data = call_service :push 15 | assert_equal '12345', data['token'] 16 | end 17 | 18 | def test_parses_minutes_from_commit_message 19 | data = call_service :push 20 | assert_equal '15', data['entries'][0]['minutes'] 21 | assert_equal '2hrs', data['entries'][1]['minutes'] 22 | end 23 | 24 | def test_strips_freckle_tags 25 | data = call_service :push 26 | assert_equal 'stub git call for Grit#heads test', 27 | data['entries'][0]['description'] 28 | assert_equal 'clean up heads test', 29 | data['entries'][1]['description'] 30 | end 31 | 32 | def test_includes_project_name 33 | data = call_service :push 34 | assert_equal 'Test Project', 35 | data['entries'][0]['project_name'] 36 | end 37 | 38 | def test_includes_author_email_as_user 39 | data = call_service :push 40 | assert_equal 'tom@mojombo.com', 41 | data['entries'][0]['user'] 42 | end 43 | 44 | def test_includes_commit_url 45 | data = call_service :push 46 | assert_equal 'http://github.com/mojombo/grit/commit/06f63b43050935962f84fe54473a7c5de7977325', 47 | data['entries'][0]['url'] 48 | end 49 | 50 | def test_includes_timestamp_as_date 51 | data = call_service :push 52 | assert_equal '2007-10-10T00:11:02-07:00', 53 | data['entries'][0]['date'] 54 | end 55 | 56 | def data 57 | { 58 | "subdomain" => "abloom", 59 | "token" => "12345", 60 | "project" => "Test Project" 61 | } 62 | end 63 | 64 | def service(*args) 65 | super Service::Freckle, *args 66 | end 67 | 68 | def call_service(event) 69 | res = nil 70 | svc = service data, payload 71 | @stubs.post '/api/entries/import' do |env| 72 | res = JSON.parse env[:body] 73 | end 74 | svc.send "receive_#{event}" 75 | res 76 | end 77 | end 78 | 79 | 80 | -------------------------------------------------------------------------------- /docs/ontime: -------------------------------------------------------------------------------- 1 | OnTime GitHub Integration 2 | ========================= 3 | 4 | Install Notes 5 | ------------- 6 | 7 | In order to properly configure OnTime and GitHub to work together a few settings have to be configured. 8 | 9 | 1. Log into your OnTime v11.1+ installation as the Administrator or with a user that has System Options privledges. 10 | 2. Open up the "Tools" menu and click on "System Options" and then go to the "GitHub Integration" option in the left pane. 11 | 3. Make sure that "Enable GitHub Integration" is checked and that an API Key exists. If it doesn't then click "Generate a New API Key" to make one 12 | 4. Copy the API key and paste that into the OnTime service hook in your GitHub repository. 13 | 14 | NOTE: If you have a non-hosted installation of OnTime your installation must have access to the internet. Hosted accounts already have internet access. 15 | 16 | Usage 17 | ----- 18 | 19 | When entering in commit messages in Git, any message that contains a specially formatted OnTime tag will attempted to be linked to the respective OnTime item. The tag is formatted as follows: 20 | 21 | [otx: id# (wl: # timeunit)] 22 | 23 | * Where the `x` in `otx` can be: 24 | * `d` for defects (i.e. `otd`) 25 | * `f` for features (i.e. `otf`) 26 | * `t` for tasks (i.e. `ott`) 27 | * `i` for incidents (i.e. `oti`) 28 | * NOTE: d, f, t and i are constant even if you've renamed the fields in your OnTime installation. 29 | * `id#` is the id number of the item that the commit links to 30 | * `wl: # timeunit` is optional. When provided it will add a worklog entry to that item after the commit is pushed to github. 31 | * `#` is some non-negative real number 32 | * `timeunit` is a valid timeunit that is used in your installation, either fully spelled or abbreviated with respect to your OnTime timeunit pick list configuration 33 | 34 | A few examples of valid tags (assuming you have hours as a timeunit in OnTime and it's abbreviated spelling is 'hrs'): 35 | 36 | [otd: 45] 37 | 38 | [otf: 2] 39 | 40 | [otf: 823 wl: 5 hours] 41 | 42 | [ott: 92 wl: 8.3 hrs] 43 | 44 | [oti: srx0091] 45 | 46 | Developer Notes 47 | --------------- 48 | 49 | data 50 | - ontime_url 51 | - api_key 52 | 53 | -------------------------------------------------------------------------------- /services/README.md: -------------------------------------------------------------------------------- 1 | # Services 2 | 3 | This is the directory that all Services go. Creating a Service is 4 | simple: 5 | 6 | ```ruby 7 | class Service::MyService < Service 8 | def receive_push 9 | end 10 | end 11 | ``` 12 | 13 | Inside the method, you can access the configuration data in a hash named 14 | `data`, and the payload data in a Hash named `payload`. 15 | 16 | Note: A service can respond to more than one event. Currently, only `push` 17 | is supported. 18 | 19 | ## Tip: Check configuration data early. 20 | 21 | ```ruby 22 | class Service::MyService < Service 23 | def receive_push 24 | if data['username'].to_s.empty? 25 | raise_config_error "Needs a username" 26 | end 27 | end 28 | end 29 | ``` 30 | 31 | ## Tip: Use `http` helpers to make HTTP calls easily. 32 | 33 | ```ruby 34 | class Service::MyService < Service 35 | def receive_push 36 | # Sets this basic auth info for every request. 37 | http.basic_auth(data['username'], data['password']) 38 | 39 | # Every request sends JSON. 40 | http.headers['Content-Type'] = 'application/json' 41 | 42 | # Uses this URL as a prefix for every request. 43 | http.url_prefix = "https://my-service.com/api" 44 | 45 | payload['commits'].each do |commit| 46 | 47 | # POST https://my-service.com/api/commits.json 48 | http_post "commits.json", commit.to_json 49 | 50 | end 51 | end 52 | end 53 | ``` 54 | 55 | ## Tip: Test your service like a bossk. 56 | 57 | ```ruby 58 | class MyServiceTest < Service::TestCase 59 | def setup 60 | @stubs = Faraday::Adapter::Test::Stubs.new 61 | end 62 | 63 | def test_push 64 | @stubs.post "/api/create.json" do |env| 65 | assert_equal 'my-service.com', env[:url].host 66 | assert_equal 'application/json', 67 | env[:request_headers]['content-type'] 68 | assert_equal basic_auth("user", "pass"), 69 | env[:request_headers]['authorization'] 70 | [200, {}, ''] 71 | end 72 | 73 | svc = service :push, 74 | {'username' => 'user', 'password' => 'pass'}, payload 75 | svc.receive_push 76 | end 77 | 78 | def service(*args) 79 | super Service::MyService, *args 80 | end 81 | end 82 | ``` 83 | 84 | ## Documentation 85 | 86 | Each Service needs to have documentation aimed at end users in /docs. 87 | See existing services for the format. 88 | -------------------------------------------------------------------------------- /test/irc_test.rb: -------------------------------------------------------------------------------- 1 | require File.expand_path('../helper', __FILE__) 2 | require 'stringio' 3 | 4 | class IRCTest < Service::TestCase 5 | class FakeIRC < Service::IRC 6 | def readable_io 7 | @readable_io ||= StringIO.new(" 004 n ") 8 | end 9 | 10 | def writable_io 11 | @writable_io ||= StringIO.new 12 | end 13 | 14 | def puts(*args) 15 | writable_io.puts *args 16 | end 17 | 18 | def gets 19 | readable_io.gets 20 | end 21 | 22 | def eof? 23 | true 24 | end 25 | 26 | def shorten_url(*args) 27 | 'short' 28 | end 29 | end 30 | 31 | def test_push 32 | svc = service({'room' => 'r', 'nick' => 'n'}, payload) 33 | 34 | svc.receive_push 35 | msgs = svc.writable_io.string.split("\n") 36 | assert_equal "NICK n", msgs.shift 37 | assert_match "USER n", msgs.shift 38 | assert_equal "JOIN #r", msgs.shift.strip 39 | assert_match /PRIVMSG #r.*grit/, msgs.shift 40 | assert_match /PRIVMSG #r.*grit/, msgs.shift 41 | assert_match /PRIVMSG #r.*grit/, msgs.shift 42 | assert_match /PRIVMSG #r.*grit/, msgs.shift 43 | assert_equal "PART #r", msgs.shift.strip 44 | assert_equal "QUIT", msgs.shift.strip 45 | assert_nil msgs.shift 46 | end 47 | 48 | def test_pull_request 49 | svc = service(:pull_request, {'room' => 'r', 'nick' => 'n'}, pull_payload) 50 | 51 | svc.receive_pull_request 52 | msgs = svc.writable_io.string.split("\n") 53 | assert_equal "NICK n", msgs.shift 54 | assert_match "USER n", msgs.shift 55 | assert_equal "JOIN #r", msgs.shift.strip 56 | assert_match /PRIVMSG #r.*grit/, msgs.shift 57 | assert_equal "PART #r", msgs.shift.strip 58 | assert_equal "QUIT", msgs.shift.strip 59 | assert_nil msgs.shift 60 | end 61 | 62 | def test_issues 63 | svc = service(:issues, {'room' => 'r', 'nick' => 'n'}, issues_payload) 64 | 65 | svc.receive_issues 66 | msgs = svc.writable_io.string.split("\n") 67 | assert_equal "NICK n", msgs.shift 68 | assert_match "USER n", msgs.shift 69 | assert_equal "JOIN #r", msgs.shift.strip 70 | assert_match /PRIVMSG #r.*grit/, msgs.shift 71 | assert_equal "PART #r", msgs.shift.strip 72 | assert_equal "QUIT", msgs.shift.strip 73 | assert_nil msgs.shift 74 | end 75 | 76 | def service(*args) 77 | super FakeIRC, *args 78 | end 79 | end 80 | 81 | -------------------------------------------------------------------------------- /vendor/internal-gems/rubyforge/lib/rubyforge.rb: -------------------------------------------------------------------------------- 1 | # This code was pretty much copied from Ara Howard's 2 | # RubyForge gem... thanks Ara! :) 3 | 4 | require 'net/https' 5 | require 'openssl' 6 | require 'webrick/cookie' 7 | 8 | class RubyForge 9 | def initialize(username, password) 10 | @cookies = Array.new 11 | login(username, password) 12 | end 13 | 14 | def post_news(group_id, subject, body) 15 | url = URI.parse('http://rubyforge.org/news/submit.php') 16 | form = { 17 | 'group_id' => group_id.to_s, 18 | 'post_changes' => 'y', 19 | 'summary' => subject, 20 | 'details' => body, 21 | 'submit' => 'Submit' 22 | } 23 | execute(url, form) 24 | end 25 | 26 | ####### 27 | private 28 | ####### 29 | 30 | def login(username, password) 31 | url = URI.parse('https://rubyforge.org/account/login.php') 32 | form = { 33 | 'return_to' => '', 34 | 'form_loginname' => username, 35 | 'form_pw' => password, 36 | 'login' => 'Login' 37 | } 38 | response = execute(url, form) 39 | bake_cookies(url, response) 40 | end 41 | 42 | def execute(url, parameters) 43 | request = Net::HTTP::Post.new(url.request_uri) 44 | request['Content-Type'] = 'application/x-www-form-urlencoded' 45 | @cookies.each do |cookie| 46 | request['Cookie'] = cookie 47 | end 48 | http = Net::HTTP.new(url.host, url.port) 49 | if url.scheme == 'https' 50 | http.use_ssl = true 51 | http.verify_mode = OpenSSL::SSL::VERIFY_NONE 52 | end 53 | request_data = query_string_for(parameters) 54 | request['Content-Length'] = request_data.length.to_s 55 | http.request(request, request_data) 56 | end 57 | 58 | def bake_cookies(url, response) 59 | (response.get_fields('Set-Cookie') || []).each do |raw_cookie| 60 | WEBrick::Cookie.parse_set_cookies(raw_cookie).each do |baked_cookie| 61 | baked_cookie.domain ||= url.host 62 | baked_cookie.path ||= url.path 63 | @cookies << baked_cookie 64 | end 65 | end 66 | end 67 | 68 | def query_string_for(parameters) 69 | parameters.sort_by { |k,v| k.to_s }.map { |k,v| 70 | k && [ WEBrick::HTTPUtils.escape_form(k.to_s), 71 | WEBrick::HTTPUtils.escape_form(v.to_s) ].join('=') 72 | }.compact.join('&') 73 | end 74 | end 75 | -------------------------------------------------------------------------------- /services/jabber.rb: -------------------------------------------------------------------------------- 1 | # Jabber::Simple does some insane kind of queueing if it thinks 2 | # we are not in their buddy list (which is always) so messages 3 | # never get sent before we disconnect. This forces the library 4 | # to assume the recipient is a buddy. 5 | class ::Jabber::Simple 6 | def subscribed_to?(x); true; end 7 | end 8 | 9 | # Default implementation of MUCClient uses blocked connection 10 | class ::Jabber::MUC::MUCClient 11 | def join(jid, password=nil) 12 | raise "MUCClient already active" if active? 13 | 14 | @jid = (jid.kind_of?(::Jabber::JID) ? jid : ::Jabber::JID.new(jid)) 15 | activate 16 | 17 | pres = ::Jabber::Presence.new 18 | pres.to = @jid 19 | pres.from = @my_jid 20 | xmuc = ::Jabber::MUC::XMUC.new 21 | xmuc.password = password 22 | pres.add xmuc 23 | 24 | @stream.send pres 25 | 26 | self 27 | end 28 | end 29 | 30 | class Service::Jabber < Service 31 | string :user 32 | 33 | def receive_push 34 | # Accept any friend request 35 | im.accept_subscriptions = true 36 | 37 | #Split multiple addresses into array, removing duplicates 38 | recipients = data.has_key?('user') ? data['user'].split(',').each(&:strip!).uniq : [] 39 | conferences = data.has_key?('muc') ? data['muc'].split(',').each(&:strip!).uniq : [] 40 | messages = [] 41 | messages << "#{summary_message}: #{summary_url}" 42 | messages += commit_messages 43 | message = messages.join("\n") 44 | 45 | deliver_messages(message, recipients) 46 | 47 | # temporarily disabled 48 | #deliver_muc(message, conferences) if !conferences.empty? 49 | end 50 | 51 | def deliver_messages(message, recipients) 52 | recipients.each do |recipient| 53 | im.deliver_deferred recipient, message, :chat 54 | end 55 | end 56 | 57 | def deliver_muc(message, conferences) 58 | conferences.each do |conference| 59 | muc = mucs[conference] 60 | muc ||= mucs[conference] = ::Jabber::MUC::MUCClient.new(im.client) 61 | muc.join(conference) unless muc.active?() 62 | im.deliver_deferred conference, message, :groupchat 63 | end 64 | end 65 | 66 | def mucs 67 | @@mucs ||= {} 68 | end 69 | 70 | attr_writer :im 71 | def im 72 | @im || @@im ||= begin 73 | ::Jabber::Simple.new(secrets['jabber']['user'], secrets['jabber']['password']) 74 | end 75 | end 76 | end 77 | -------------------------------------------------------------------------------- /docs/you_track: -------------------------------------------------------------------------------- 1 | YouTrack 2 | ======== 3 | 4 | --------------------------------------- 5 | YouTrack - GitHub Integration Overview 6 | --------------------------------------- 7 | 8 | Integration with YouTrack allows GitHub user to apply commands to YouTrack issues 9 | right from commit comments. 10 | 11 | -------------- 12 | Install Notes 13 | -------------- 14 | 15 | 1. YouTrack Requirements 16 | 17 | - Requires YouTrack version 2.0 or above. YouTrack Energy EAP builds are 18 | supported as well. 19 | 20 | - Your YouTrack server should be acessible from the internet. 21 | 22 | - REST API must be enabled in your YouTrack server. 23 | 24 | - Committer's email addresses in GitHub and YouTrack should be the same. 25 | YouTrack looks for user account of a committer by an email address, which the 26 | committer has registered in GitHub. If YouTrack doesn't find a user account with the 27 | same email as committer's email, a command specified in commit's comment won't be applied. 28 | 29 | 2. Settings in GitHub 30 | 31 | In the GitHub integration config, the following settings should be provided: 32 | 33 | - YouTrack Server URL 34 | 35 | - Administrator's account (e.g. 'root' user) credentials to access your YouTrack 36 | server. 37 | 38 | - Name of a user group in YouTrack, in which YouTrack will search for committer's 39 | account. 40 | 41 | --------------------------------- 42 | Essential YouTrack Configuration 43 | --------------------------------- 44 | 45 | - Enable REST API via 'Administration' > 'Settings' section on your YouTrack 46 | server. 47 | 48 | - Use an existing user group (or create a new one) with all users who commit changes 49 | in GitHub. 50 | 51 | --------------- 52 | Command Syntax 53 | --------------- 54 | 55 | General comment format for applying commands: 56 | 57 | 58 | [some comment text] #issueID [command_2] ... [command_n] 59 | [some comment text] #issueID [command_2] ... [command_n] 60 | ... 61 | 62 | 63 | *Important note:* 64 | YouTrack tries to parse as a command any string after a hash mark (#) with an issueID till the end of the line. 65 | If it contains any incorrect commands or attributes, the command will not be applied. If there is no command after 66 | issue, that issue is marked as Fixed. 67 | 68 | Developer Notes 69 | --------------- 70 | 71 | data 72 | -base_url 73 | -username 74 | -password 75 | -committers 76 | 77 | 78 | --------------------------------------------------------------------------------