Initial commit of gem for trello/github integration

This commit is contained in:
Zachary Anker 2012-04-09 16:23:22 -07:00
Коммит 4ced5b2ae0
12 изменённых файлов: 265 добавлений и 0 удалений

4
Gemfile Normal file
Просмотреть файл

@ -0,0 +1,4 @@
source "http://rubygems.org"
gemspec
gem "rake"

29
Gemfile.lock Normal file
Просмотреть файл

@ -0,0 +1,29 @@
PATH
remote: .
specs:
github-trello (0.0.1)
sinatra (~> 1.3.2)
vegas (~> 0.1.8)
GEM
remote: http://rubygems.org/
specs:
rack (1.4.1)
rack-protection (1.2.0)
rack
rake (0.9.2.2)
sinatra (1.3.2)
rack (~> 1.3, >= 1.3.6)
rack-protection (~> 1.2)
tilt (~> 1.3, >= 1.3.3)
tilt (1.3.3)
vegas (0.1.11)
rack (>= 1.0.0)
PLATFORMS
java
ruby
DEPENDENCIES
github-trello!
rake

19
MIT-LICENSE Normal file
Просмотреть файл

@ -0,0 +1,19 @@
Copyright (c) 2011 Zachary Anker
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

4
README.md Normal file
Просмотреть файл

@ -0,0 +1,4 @@
Overview
===
Allows you to manage or reference your Trello board through commits to Github. Tag a commit with "Closes 1234" to have a card automatically archived, or "Card 1234" to have the commit sent to the card.

12
Rakefile Normal file
Просмотреть файл

@ -0,0 +1,12 @@
require "bundler"
Bundler.setup
require "rake"
require "rspec"
require "rspec/core/rake_task"
RSpec::Core::RakeTask.new("spec") do |spec|
spec.pattern = "spec/**/*_spec.rb"
end
task :default => :spec

25
bin/trello-web Executable file
Просмотреть файл

@ -0,0 +1,25 @@
#!/usr/bin/env ruby
$LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__) + "/../lib")
require "vegas"
require "github-trello/server"
Vegas::Runner.new(GithubTrello::Server, "trello-web", {
:launch_path => lambda {|vegas|
path = File.join(vegas.app_dir, "trello.yml")
if File.exists?(path)
GithubTrello::Server.config = YAML::load(File.read(path))
else
puts "[WARNING] No configuration found at #{path}."
puts "We've generated an example one for you, but you need to configure it still."
File.open(path, "w+") do |f|
f.write("#board_ids:\n# [repo name]: [board id]\n#oauth_token: [token]\n#api_key: [key]#on_start:\n# move_to: [list id]\n#on_close:\n# move_to: [list id]\n# archive: false\n# on_deploy:\n# move_to: [list id]\n# archive: true")
end
exit
end
nil
}
})

6
config.ru Normal file
Просмотреть файл

@ -0,0 +1,6 @@
#!/usr/bin/env ruby
$LOAD_PATH.unshift ::File.expand_path(::File.dirname(__FILE__) + "/lib")
require "trello/server"
use Rack::ShowExceptions
run TrelloService::Server.new

21
github-trello.gemspec Normal file
Просмотреть файл

@ -0,0 +1,21 @@
$LOAD_PATH.unshift(File.expand_path("../lib", __FILE__))
require "github-trello/version"
Gem::Specification.new do |s|
s.name = "github-trello"
s.version = GithubTrello::VERSION
s.platform = Gem::Platform::RUBY
s.authors = ["Zachary Anker"]
s.email = ["zach.anker@gmail.com"]
s.homepage = "http://github.com/zanker/github-trello"
s.summary = "Github -> Trello integration"
s.required_rubygems_version = ">= 1.3.6"
s.rubyforge_project = "github-trello"
s.add_runtime_dependency "vegas", "~>0.1.8"
s.add_runtime_dependency "sinatra", "~>1.3.2"
s.files = Dir.glob("lib/**/*") + %w[MIT-LICENSE README.md Rakefile]
s.executables = ["trello-web"]
end

1
lib/github-trello.rb Normal file
Просмотреть файл

@ -0,0 +1 @@
require "github-trello/version"

54
lib/github-trello/http.rb Normal file
Просмотреть файл

@ -0,0 +1,54 @@
require "cgi"
require "net/https"
module GithubTrello
class HTTP
def initialize(token, api_key)
@token, @api_key = token, api_key
@uri = URI("https://api.trello.com")
end
def get_card(board_id, card_id)
http_request(:get, "/1/boards/#{board_id}/cards/#{card_id}", :params => {:fields => "idList,closed"})
end
def update_card(card_id, params)
http_request(:put, "/1/cards/#{card_id}", :params => params)
end
def add_comment(card_id, comment)
http_request(:post, "/1/cards/#{card_id}/actions/comments", :body => "text=#{CGI::escape(comment)}")
end
private
def http_request(method, request_path, args={})
request_path << "?"
args[:params] ||= {}
args[:params][:key] = @api_key
args[:params][:token] = @token
args[:params].each {|k, v| request_path << "#{k}=#{CGI::escape(v)}&"}
http = Net::HTTP.new(@uri.host, @uri.port)
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
http.set_debug_output($stdout)
http.start
if method == :get
response = http.request_get(request_path)
elsif method == :post
response = http.request_post(request_path, args.delete(:body))
elsif method == :put
response = http.request_put(request_path, args.delete(:body))
end
unless response.code == "200" or response.code == "201"
raise Net::HTTPError.new("#{response.body == "" ? response.message : response.body.strip} (#{response.code})", response)
end
response.body
end
end
end

Просмотреть файл

@ -0,0 +1,87 @@
require "json"
require "sinatra/base"
require "github-trello/version"
require "github-trello/http"
module GithubTrello
class Server < Sinatra::Base
get "/posthook" do
config, http = self.class.config, self.class.http
payload = JSON.parse(params[:payload])
board_id = config["board_ids"][payload["repository"]["name"]]
unless board_id
puts "[ERROR] Commit from #{payload["repository"]["name"]} but no board_id entry found in config"
return
end
branch = payload["ref"].gsub("refs/heads/", "")
if config["blacklist_branches"] and config["blacklist_branches"].include?(branch)
return
elsif config["whitelist_branches"] and !config["whitelist_branches"].include?(branch)
return
end
payload["commits"].each do |commit|
# Figure out the card short id
match = commit["message"].match(/((case|card|close|archive|fix)e?s? \D?([0-9]+))/i)
next unless match and match[3].to_i > 0
# Determine the action to take
update_config = case match[2].downcase
when "case", "card" then config["on_start"]
when "close", "fix" then config["on_close"]
when "archive" then {:archive => true}
end
unless update_config.is_a?(Hash)
raise "Updating card with #{match[2].downcase} type, but no config found to indicate what to do"
end
results = http.get_card(board_id, match[3].to_i)
unless results
puts "[ERROR] Cannot find card matching ID #{match[3]}"
next
end
results = JSON.parse(results)
# Add the commit comment
message = "#{commit["author"]["name"]}: #{commit["message"]}\n\n[#{branch}] #{commit["url"]}"
message.gsub!(match[1], "")
message.gsub!(/\(\)$/, "")
http.add_comment(results["id"], message)
# Modify it if needed
to_update = {}
unless results["idList"] == update_config["move_to"]
to_update[:idList] = update_config["move_to"]
end
if !results["closed"] and update_config["archive"]
to_update[:closed] = true
end
unless to_update.empty?
http.update_card(results["id"], to_update)
end
end
""
end
get "/" do
"Nothing to see here"
end
def self.config=(config)
@config = config
@http = GithubTrello::HTTP.new(config["oauth_token"], config["api_key"])
end
def self.config; @config end
def self.http; @http end
end
end

Просмотреть файл

@ -0,0 +1,3 @@
module GithubTrello
VERSION = "0.0.1"
end