├── .gitignore ├── Gemfile ├── LICENSE ├── README.md ├── run.rb └── setup.rb /.gitignore: -------------------------------------------------------------------------------- 1 | *.gem 2 | *.rbc 3 | /.config 4 | /coverage/ 5 | /InstalledFiles 6 | /pkg/ 7 | /spec/reports/ 8 | /test/tmp/ 9 | /test/version_tmp/ 10 | /tmp/ 11 | 12 | ## Specific to RubyMotion: 13 | .dat* 14 | .repl_history 15 | build/ 16 | 17 | ## Documentation cache and generated files: 18 | /.yardoc/ 19 | /_yardoc/ 20 | /doc/ 21 | /rdoc/ 22 | 23 | ## Environment normalisation: 24 | /.bundle/ 25 | /lib/bundler/man/ 26 | 27 | # for a library or gem, you might want to ignore these files since the code is 28 | # intended to run in multiple environments; otherwise, check them in: 29 | Gemfile.lock 30 | # .ruby-version 31 | # .ruby-gemset 32 | 33 | # unless supporting rvm < 1.11.0 or doing something fancy, ignore this: 34 | .rvmrc 35 | 36 | settings.json -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source "https://rubygems.org" 2 | 3 | gem "hue", git: "https://github.com/soffes/hue" 4 | 5 | gem "travis" 6 | 7 | gem "json" 8 | 9 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Josh Kalderimis 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Travis CI in all the Hues 2 | === 3 | 4 | A little app which syncs the status of projects you are testing on travis-ci.org to your [Philips Hue][1] lights. 5 | 6 | Runs happily on a Mac or Raspberry Pi. 7 | 8 | Installation 9 | --- 10 | 11 | ```Shell 12 | bundle install 13 | ``` 14 | 15 | Then setup which lights map to which projects on [Travis CI][2]: 16 | 17 | ```Shell 18 | bundle exec ruby setup.rb 19 | ``` 20 | 21 | And finally sync the projects state and lights: 22 | 23 | ```Shell 24 | bundle exec ruby ruby.rb 25 | ``` 26 | 27 | ### To Do: 28 | 29 | 30 | - [ ] support for travis-ci.com 31 | - [ ] support for Travsi CI Enterprise 32 | - [ ] flash the light when it changes from Passing to Failing 33 | - [ ] clean up the scripts 34 | - [ ] add some basic tests 35 | 36 | 37 | ------- 38 | [1]: http://meethue.com 39 | [2]: https://travis-ci.org 40 | -------------------------------------------------------------------------------- /run.rb: -------------------------------------------------------------------------------- 1 | require 'hue' 2 | require 'json' 3 | require 'travis/client' 4 | 5 | hue = nil 6 | 7 | unless File.exists?('settings.json') 8 | puts "Please setup which Hue lights you want to link on Travis CI first" 9 | exit 10 | end 11 | 12 | begin 13 | puts "Locating the Hue bridge" 14 | 15 | hue = Hue::Client.new("travis-ci-on-the-piiii") 16 | 17 | puts "Hue bridge found at #{client.bridge.ip}\n\n" 18 | rescue Hue::NoBridgeFound => e 19 | puts "Sorry but no Hue bridge could be found" 20 | exit 21 | rescue => e 22 | # nothing for now 23 | end 24 | 25 | begin 26 | hue = Hue::Client.new("travis-ci-on-the-pi") 27 | 28 | puts "Looks like the bridge knows who you are!\n\n" 29 | rescue Hue::LinkButtonNotPressed => e 30 | puts "Please setup which Hue lights you want to link on Travis CI first" 31 | exit 32 | end 33 | 34 | TRANSITION_TIME = 2 35 | PASSED = { hue: 25500, brightness: 255, saturation: 255 } 36 | FAILED = { hue: 65535, brightness: 255, saturation: 255 } 37 | 38 | file = File.read('settings.json') 39 | monitored_lights = JSON.parse(file)['lights'] 40 | 41 | message = "setup to sync with Travis CI repos" 42 | 43 | case monitored_lights.size 44 | when 0 45 | puts "No lights #{message}" 46 | puts "Please setup which Hue lights you want to link on Travis CI first" 47 | exit 48 | when 1 49 | puts "1 light #{message}" 50 | else 51 | puts "#{monitored_lights.size} lights #{message}" 52 | end 53 | 54 | def repo_status(travis, slug) 55 | repo = travis.repo(slug) 56 | master = repo.branch('master') 57 | master.state 58 | rescue => e 59 | puts "had an error fetching the status of repo:#{slug}, moving on" 60 | raise 61 | end 62 | 63 | def update_light(hue, light_id, state) 64 | case state 65 | when 'passed' 66 | hue.light(light_id).set_state PASSED, TRANSITION_TIME 67 | when 'failed' 68 | hue.light(light_id).set_state FAILED, TRANSITION_TIME 69 | end 70 | rescue => e 71 | puts "had an error updating light:#{light_id}, moving on" 72 | raise 73 | end 74 | 75 | puts "Starting monitoring: #{monitored_lights.collect { |ml| ml["repo"] }}\n\n" 76 | travis = Travis::Client.new 77 | loop do 78 | travis.clear_cache 79 | monitored_lights.each do |ml| 80 | begin 81 | puts "checking status of #{ml["repo"]}" 82 | state = repo_status(travis, ml["repo"]) 83 | puts "the most recent master build on #{ml["repo"]} #{state}" 84 | update_light(hue, ml["light_id"], state) 85 | rescue => e 86 | # nothing for now 87 | end 88 | end 89 | sleep 3 90 | end 91 | -------------------------------------------------------------------------------- /setup.rb: -------------------------------------------------------------------------------- 1 | require 'hue' 2 | require 'json' 3 | 4 | hue = nil 5 | 6 | begin 7 | puts "Locating the Hue bridge" 8 | 9 | hue = Hue::Client.new("travis-ci-on-the-piiii") 10 | 11 | puts "Hue bridge found at #{client.bridge.ip}\n\n" 12 | rescue Hue::NoBridgeFound => e 13 | puts "Sorry but no Hue bridge could be found" 14 | exit 15 | rescue => e 16 | # nothing for now 17 | end 18 | 19 | begin 20 | hue = Hue::Client.new("travis-ci-on-the-pi") 21 | 22 | puts "Looks like the bridge knows who you are!\n\n" 23 | rescue Hue::LinkButtonNotPressed => e 24 | puts "This is the first time setting this up, so you need to please the link button" 25 | sleep 2 26 | retry 27 | end 28 | 29 | lights = hue.lights 30 | case lights.size 31 | when 0 32 | puts "Sorry but it doesn't look like any lights are connected to your Hue" 33 | exit 34 | when 1 35 | puts "Found a light!\n\n" 36 | else 37 | puts "Ohhhh, found #{lights.size} lights!\n\n" 38 | end 39 | 40 | monitored_lights = [] 41 | 42 | lights.each do |light| 43 | light.set_state alert: 'lselect' 44 | sleep 2 45 | light.set_state alert: 'none' 46 | print "Would you like to setup '#{light.name}' to link to a repo on travis-ci.org? (y/n) : " 47 | STDOUT.flush 48 | answer = gets.chomp.downcase 49 | case answer 50 | when 'y' 51 | print "What is the repo you would like to link this light to? eg. travis-ci/travis-api : " 52 | STDOUT.flush 53 | repo = gets.chomp.downcase 54 | puts "\n" 55 | light.name = "travis-ci: #{repo.split('/').last}"[0..30] 56 | monitored_lights << { light_id: light.id, repo: repo } 57 | else 58 | next 59 | end 60 | end 61 | 62 | settings = { 63 | lights: monitored_lights 64 | } 65 | 66 | File.open("settings.json","w") do |f| 67 | f.write(settings.to_json) 68 | end 69 | 70 | message = "setup to sync with Travis CI repos" 71 | 72 | case monitored_lights.size 73 | when 0 74 | puts "No lights #{message}" 75 | when 1 76 | puts "1 light #{message}" 77 | else 78 | puts "#{monitored_lights.size} lights #{message}" 79 | end 80 | 81 | --------------------------------------------------------------------------------