gitlab-flowdock-git-hook 0.4.2.2
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/.rspec +1 -0
- data/.travis.yml +3 -0
- data/Gemfile +13 -0
- data/LICENSE.txt +20 -0
- data/README.md +99 -0
- data/Rakefile +43 -0
- data/VERSION +1 -0
- data/gitlab-flowdock-git-hook.gemspec +75 -0
- data/lib/flowdock-git-hook.rb +1 -0
- data/lib/flowdock/git.rb +94 -0
- data/lib/flowdock/git/builder.rb +84 -0
- data/post-receive +6 -0
- data/spec/builder_spec.rb +135 -0
- data/spec/flowdock_git_spec.rb +86 -0
- data/spec/spec_helper.rb +12 -0
- metadata +185 -0
data/.document
ADDED
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--color
|
data/.travis.yml
ADDED
data/Gemfile
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
source "http://rubygems.org"
|
2
|
+
|
3
|
+
gem "gitlab-grit", ">= 2.4.1"
|
4
|
+
gem "multi_json"
|
5
|
+
|
6
|
+
group :development do
|
7
|
+
gem "rdoc", ">= 2.4.2"
|
8
|
+
gem "rspec", "~> 2.8"
|
9
|
+
gem "bundler", "~> 1.0"
|
10
|
+
gem "jeweler", "~> 1.8.7"
|
11
|
+
gem "webmock", ">= 1.6.4"
|
12
|
+
gem "jruby-openssl", :platforms => :jruby, :require => false
|
13
|
+
end
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2011 Flowdock Ltd.
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,99 @@
|
|
1
|
+
# Flowdock Git Hook
|
2
|
+
|
3
|
+
Git Post-Receive hook for [Flowdock](http://flowdock.com).
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
First, you need to install this gem. You need to have Ruby 1.8.6 and Rubygems installed in your system.
|
8
|
+
|
9
|
+
$ gem install flowdock-git-hook
|
10
|
+
|
11
|
+
Then, download the post-receive hook file to the hooks directory and make it executable
|
12
|
+
|
13
|
+
$ wget -O hooks/post-receive https://raw.github.com/flowdock/flowdock-git-hook/master/post-receive
|
14
|
+
$ chmod +x hooks/post-receive
|
15
|
+
|
16
|
+
Configure your Flow API tokens to git configuration
|
17
|
+
|
18
|
+
$ git config flowdock.token <Flow API token>
|
19
|
+
|
20
|
+
After this, you should get updates from your git repo every time you push to it.
|
21
|
+
|
22
|
+
## Configuration
|
23
|
+
|
24
|
+
Service specific instructions for [Gitlab](https://github.com/flowdock/flowdock-git-hook/wiki/Gitlab) and [Redmine](https://github.com/flowdock/flowdock-git-hook/wiki/Redmine) can be found in [Wiki](https://github.com/flowdock/flowdock-git-hook/wiki).
|
25
|
+
|
26
|
+
### Repository URL
|
27
|
+
|
28
|
+
Each Team Inbox item sent from the post-receive hook can link back to the repository. To configure the URL for the repository, configure a `repository-url`:
|
29
|
+
|
30
|
+
$ git config flowdock.repository-url "http://example.com/mygitviewer/repo"
|
31
|
+
|
32
|
+
### Commit URLs
|
33
|
+
|
34
|
+
Commit SHAs links in the Team Inbox of Flowdock can be made clickable to view the change on the web. To configure the URL for viewing commits, configure a `commit-url-pattern`:
|
35
|
+
|
36
|
+
$ git config flowdock.commit-url-pattern "http://example.com/mygitviewer/commits/%s"
|
37
|
+
|
38
|
+
The `%s` will be replaced with the commit SHA.
|
39
|
+
|
40
|
+
### Diff URL
|
41
|
+
|
42
|
+
Commit messages in Team Inbox can have a action for viewing the commit diff. To enable the Diff action for comparing commits, configure a `diff-url-pattern`:
|
43
|
+
|
44
|
+
$ gitconfig flowdock.diff-url-pattern "http://example.com/mygitviewer/compare/%s...%s"
|
45
|
+
|
46
|
+
## Advanced usage
|
47
|
+
|
48
|
+
The git hook allows Flowdock tags to be attached to push messages. If you only need static tags, e.g. git repo name as tag, this can be configured in git config:
|
49
|
+
|
50
|
+
$ git config flowdock.tags git,push
|
51
|
+
|
52
|
+
For programmatic control over tagging, you can change how the hook is called in post-receive hook file.
|
53
|
+
|
54
|
+
Flowdock::Git.background_post(ref, before, after, :tags => ["git", "push"])
|
55
|
+
|
56
|
+
Note that you can also define token as parameter allowing multiple Flows to be notified.
|
57
|
+
|
58
|
+
Flowdock::Git.background_post(ref, before, after, :token => "flow-token")
|
59
|
+
Flowdock::Git.background_post(ref, before, after, :token => "another-flow")
|
60
|
+
|
61
|
+
### Usage as a library
|
62
|
+
|
63
|
+
You can use the gem as a library from an application, without the need to set configuration parameters on the Git repository. You can pass the required parameters directly like so:
|
64
|
+
|
65
|
+
Flowdock::Git.post(ref, before, after, :token => "flow-token",
|
66
|
+
:repo => "/path/to/repo",
|
67
|
+
:repo_url => "http://example.com/mygitviewer/repo",
|
68
|
+
:commit_url => "http://example.com/mygitviewer/repo/commit/%s",
|
69
|
+
:diff_url => "http://example.com/mygitviewer/repo/compare/%s...%s")
|
70
|
+
|
71
|
+
## Example data
|
72
|
+
|
73
|
+
The hook uses [GitHub webhook](http://help.github.com/post-receive-hooks/) format.
|
74
|
+
|
75
|
+
payload {
|
76
|
+
"after": "122b95a8808ea0cf708fb43b400a377c25c35d7f",
|
77
|
+
"before": "2a445d1d348d9d45217cb9c89c12b67d3767ce42",
|
78
|
+
"commits": [
|
79
|
+
{
|
80
|
+
"added": [],
|
81
|
+
"author": {
|
82
|
+
"email": "raine.virta@nodeta.fi",
|
83
|
+
"name": "Raine Virta"
|
84
|
+
},
|
85
|
+
"id": "122b95a8808ea0cf708fb43b400a377c25c35d7f",
|
86
|
+
"message": "yeah!",
|
87
|
+
"modified": [
|
88
|
+
"TEST_FILE"
|
89
|
+
],
|
90
|
+
"removed": [],
|
91
|
+
"timestamp": "2010-08-11T13:46:39+03:00"
|
92
|
+
}
|
93
|
+
],
|
94
|
+
"ref": "refs\/heads\/master",
|
95
|
+
"ref_name": "master",
|
96
|
+
"repository": {
|
97
|
+
"name": "testrepo"
|
98
|
+
}
|
99
|
+
}
|
data/Rakefile
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'bundler'
|
5
|
+
begin
|
6
|
+
Bundler.setup(:default, :development)
|
7
|
+
rescue Bundler::BundlerError => e
|
8
|
+
$stderr.puts e.message
|
9
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
10
|
+
exit e.status_code
|
11
|
+
end
|
12
|
+
require 'rake'
|
13
|
+
|
14
|
+
require 'jeweler'
|
15
|
+
Jeweler::Tasks.new do |gem|
|
16
|
+
# gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
|
17
|
+
gem.name = "flowdock-git-hook"
|
18
|
+
gem.homepage = "http://github.com/flowdock/flowdock-git-hook"
|
19
|
+
gem.license = "MIT"
|
20
|
+
gem.summary = %Q{Git Post-Receive hook for Flowdock}
|
21
|
+
gem.email = "lautis@gmail.com"
|
22
|
+
gem.authors = ["Ville Lautanala"]
|
23
|
+
# dependencies defined in Gemfile
|
24
|
+
end
|
25
|
+
Jeweler::RubygemsDotOrgTasks.new
|
26
|
+
|
27
|
+
require 'rspec/core'
|
28
|
+
require 'rspec/core/rake_task'
|
29
|
+
RSpec::Core::RakeTask.new(:spec) do |spec|
|
30
|
+
spec.pattern = FileList['spec/**/*_spec.rb']
|
31
|
+
end
|
32
|
+
|
33
|
+
task :default => :spec
|
34
|
+
|
35
|
+
require 'rdoc/task'
|
36
|
+
RDoc::Task.new do |rdoc|
|
37
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
38
|
+
|
39
|
+
rdoc.rdoc_dir = 'rdoc'
|
40
|
+
rdoc.title = "flowdock #{version}"
|
41
|
+
rdoc.rdoc_files.include('README*')
|
42
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
43
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.4.2
|
@@ -0,0 +1,75 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = "gitlab-flowdock-git-hook"
|
8
|
+
s.version = "0.4.2.2"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Ville Lautanala", "Boyan Tabakov"]
|
12
|
+
s.date = "2013-10-03"
|
13
|
+
s.email = "blade@alslayer.net"
|
14
|
+
s.extra_rdoc_files = [
|
15
|
+
"LICENSE.txt",
|
16
|
+
"README.md"
|
17
|
+
]
|
18
|
+
s.files = [
|
19
|
+
".document",
|
20
|
+
".rspec",
|
21
|
+
".travis.yml",
|
22
|
+
"Gemfile",
|
23
|
+
"LICENSE.txt",
|
24
|
+
"README.md",
|
25
|
+
"Rakefile",
|
26
|
+
"VERSION",
|
27
|
+
"gitlab-flowdock-git-hook.gemspec",
|
28
|
+
"lib/flowdock-git-hook.rb",
|
29
|
+
"lib/flowdock/git.rb",
|
30
|
+
"lib/flowdock/git/builder.rb",
|
31
|
+
"post-receive",
|
32
|
+
"spec/builder_spec.rb",
|
33
|
+
"spec/flowdock_git_spec.rb",
|
34
|
+
"spec/spec_helper.rb"
|
35
|
+
]
|
36
|
+
s.homepage = "http://github.com/bladealslayer/flowdock-git-hook"
|
37
|
+
s.licenses = ["MIT"]
|
38
|
+
s.require_paths = ["lib"]
|
39
|
+
s.rubygems_version = "2.0.5"
|
40
|
+
s.summary = "Git Post-Receive hook for Flowdock. Gem requirements patched for use with Gitlab."
|
41
|
+
|
42
|
+
if s.respond_to? :specification_version then
|
43
|
+
s.specification_version = 4
|
44
|
+
|
45
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
46
|
+
s.add_runtime_dependency(%q<gitlab-grit>, [">= 2.4.1"])
|
47
|
+
s.add_runtime_dependency(%q<multi_json>, [">= 0"])
|
48
|
+
s.add_development_dependency(%q<rdoc>, [">= 2.4.2"])
|
49
|
+
s.add_development_dependency(%q<rspec>, ["~> 2.8"])
|
50
|
+
s.add_development_dependency(%q<bundler>, ["~> 1.0"])
|
51
|
+
s.add_development_dependency(%q<jeweler>, ["~> 1.8.7"])
|
52
|
+
s.add_development_dependency(%q<webmock>, [">= 1.6.4"])
|
53
|
+
s.add_development_dependency(%q<jruby-openssl>, [">= 0"])
|
54
|
+
else
|
55
|
+
s.add_dependency(%q<gitlab-grit>, [">= 2.4.1"])
|
56
|
+
s.add_dependency(%q<multi_json>, [">= 0"])
|
57
|
+
s.add_dependency(%q<rdoc>, [">= 2.4.2"])
|
58
|
+
s.add_dependency(%q<rspec>, ["~> 2.8"])
|
59
|
+
s.add_dependency(%q<bundler>, ["~> 1.0"])
|
60
|
+
s.add_dependency(%q<jeweler>, ["~> 1.8.7"])
|
61
|
+
s.add_dependency(%q<webmock>, [">= 1.6.4"])
|
62
|
+
s.add_dependency(%q<jruby-openssl>, [">= 0"])
|
63
|
+
end
|
64
|
+
else
|
65
|
+
s.add_dependency(%q<gitlab-grit>, [">= 2.4.1"])
|
66
|
+
s.add_dependency(%q<multi_json>, [">= 0"])
|
67
|
+
s.add_dependency(%q<rdoc>, [">= 2.4.2"])
|
68
|
+
s.add_dependency(%q<rspec>, ["~> 2.8"])
|
69
|
+
s.add_dependency(%q<bundler>, ["~> 1.0"])
|
70
|
+
s.add_dependency(%q<jeweler>, ["~> 1.8.7"])
|
71
|
+
s.add_dependency(%q<webmock>, [">= 1.6.4"])
|
72
|
+
s.add_dependency(%q<jruby-openssl>, [">= 0"])
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'flowdock/git'
|
data/lib/flowdock/git.rb
ADDED
@@ -0,0 +1,94 @@
|
|
1
|
+
require "multi_json"
|
2
|
+
require "net/https"
|
3
|
+
require "cgi"
|
4
|
+
|
5
|
+
require "flowdock/git/builder"
|
6
|
+
|
7
|
+
module Flowdock
|
8
|
+
class Git
|
9
|
+
class TokenError < StandardError; end
|
10
|
+
API_ENDPOINT = "https://api.flowdock.com/v1/git"
|
11
|
+
|
12
|
+
class << self
|
13
|
+
def post(ref, from, to, options = {})
|
14
|
+
git = Git.new(options)
|
15
|
+
git.post(Git::Builder.new(git.repo, ref, from, to))
|
16
|
+
end
|
17
|
+
|
18
|
+
def background_post(ref, from, to, options = {})
|
19
|
+
git = Git.new(options)
|
20
|
+
git.background_post(Git::Builder.new(git.repo, ref, from, to))
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def initialize(options = {})
|
25
|
+
@options = options
|
26
|
+
@token = options[:token] || config["flowdock.token"] || raise(TokenError.new("Flowdock API token not found"))
|
27
|
+
@commit_url = options[:commit_url] || config["flowdock.commit-url-pattern"] || nil
|
28
|
+
@diff_url = options[:diff_url] || config["flowdock.diff-url-pattern"] || nil
|
29
|
+
@repo_url = options[:repo_url] || config["flowdock.repository-url"] || nil
|
30
|
+
end
|
31
|
+
|
32
|
+
# Send git push notification to Flowdock
|
33
|
+
def post(data)
|
34
|
+
uri = URI.parse("#{API_ENDPOINT}/#{([@token] + tags).join('+')}")
|
35
|
+
req = Net::HTTP::Post.new(uri.path)
|
36
|
+
|
37
|
+
payload_hash = data.to_hash
|
38
|
+
if @repo_url
|
39
|
+
payload_hash[:repository][:url] = @repo_url
|
40
|
+
end
|
41
|
+
if @commit_url
|
42
|
+
payload_hash[:commits].each do |commit|
|
43
|
+
commit[:url] = @commit_url % commit[:id]
|
44
|
+
end
|
45
|
+
end
|
46
|
+
if @diff_url
|
47
|
+
payload_hash[:compare] = @diff_url % [payload_hash[:before], payload_hash[:after]]
|
48
|
+
end
|
49
|
+
|
50
|
+
req.set_form_data(:payload => MultiJson.encode(payload_hash))
|
51
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
52
|
+
|
53
|
+
if uri.scheme == 'https'
|
54
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
55
|
+
http.use_ssl = true
|
56
|
+
end
|
57
|
+
|
58
|
+
http.start { |http| http.request(req) }
|
59
|
+
end
|
60
|
+
|
61
|
+
# Create and post notification in background process. Avoid blocking the push notification.
|
62
|
+
def background_post(data)
|
63
|
+
pid = Process.fork
|
64
|
+
if pid.nil?
|
65
|
+
Grit::Git.with_timeout(600) do
|
66
|
+
post(data) # Child
|
67
|
+
end
|
68
|
+
else
|
69
|
+
Process.detach(pid) # Parent
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def repo
|
74
|
+
@repo ||= Grit::Repo.new(@options[:repo] || Dir.pwd)
|
75
|
+
end
|
76
|
+
|
77
|
+
private
|
78
|
+
|
79
|
+
# Flowdock tags attached to the push notification
|
80
|
+
def tags
|
81
|
+
if @options[:tags]
|
82
|
+
@options[:tags]
|
83
|
+
else
|
84
|
+
config["flowdock.tags"].to_s.split(",")
|
85
|
+
end.map do |t|
|
86
|
+
CGI.escape(t)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def config
|
91
|
+
@config ||= Grit::Config.new(repo)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
require "grit"
|
2
|
+
|
3
|
+
module Flowdock
|
4
|
+
class Git
|
5
|
+
# Class used to build Git payload
|
6
|
+
class Builder
|
7
|
+
def initialize(repo, ref, before, after)
|
8
|
+
@repo = repo
|
9
|
+
@ref = ref
|
10
|
+
@before = before
|
11
|
+
@after = after
|
12
|
+
end
|
13
|
+
|
14
|
+
def commits
|
15
|
+
@repo.commits_between(@before, @after).map do |commit|
|
16
|
+
{
|
17
|
+
:id => commit.sha,
|
18
|
+
:message => commit.message,
|
19
|
+
:timestamp => commit.authored_date.iso8601,
|
20
|
+
:author => {
|
21
|
+
:name => commit.author.name,
|
22
|
+
:email => commit.author.email
|
23
|
+
},
|
24
|
+
:removed => filter(commit.diffs) { |d| d.deleted_file },
|
25
|
+
:added => filter(commit.diffs) { |d| d.new_file },
|
26
|
+
:modified => filter(commit.diffs) { |d| !d.deleted_file && !d.new_file }
|
27
|
+
}
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def ref_name
|
32
|
+
@ref.to_s.sub(/\Arefs\/(heads|tags)\//, '')
|
33
|
+
end
|
34
|
+
|
35
|
+
def to_hash
|
36
|
+
encode({
|
37
|
+
:before => @before,
|
38
|
+
:after => @after,
|
39
|
+
:ref => @ref,
|
40
|
+
:commits => commits,
|
41
|
+
:ref_name => @ref.to_s.sub(/\Arefs\/(heads|tags)\//, ''),
|
42
|
+
:repository => {
|
43
|
+
:name => File.basename(@repo.path).sub(/\.git$/,'')
|
44
|
+
}
|
45
|
+
}).merge(if @before == "0000000000000000000000000000000000000000"
|
46
|
+
{:created => true}
|
47
|
+
elsif @after == "0000000000000000000000000000000000000000"
|
48
|
+
{:deleted => true}
|
49
|
+
else
|
50
|
+
{}
|
51
|
+
end)
|
52
|
+
end
|
53
|
+
|
54
|
+
private
|
55
|
+
|
56
|
+
def filter(diffs)
|
57
|
+
diffs.select { |e| yield e }.map { |diff| diff.b_path }
|
58
|
+
end
|
59
|
+
|
60
|
+
# This only works on Ruby 1.9
|
61
|
+
def encode_as_utf8(obj)
|
62
|
+
if obj.is_a? Hash
|
63
|
+
obj.each_pair do |key, val|
|
64
|
+
encode_as_utf8(val)
|
65
|
+
end
|
66
|
+
elsif obj.is_a?(Array)
|
67
|
+
obj.each do |val|
|
68
|
+
encode_as_utf8(val)
|
69
|
+
end
|
70
|
+
elsif obj.is_a?(String) && obj.encoding != Encoding::UTF_8
|
71
|
+
if !obj.force_encoding("UTF-8").valid_encoding?
|
72
|
+
obj.force_encoding("ISO-8859-1").encode!(Encoding::UTF_8, :invalid => :replace, :undef => :replace)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
obj
|
76
|
+
end
|
77
|
+
|
78
|
+
def encode(hash)
|
79
|
+
return hash unless "".respond_to? :encode
|
80
|
+
encode_as_utf8(hash)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
data/post-receive
ADDED
@@ -0,0 +1,135 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
3
|
+
|
4
|
+
describe "Git Payload Builder" do
|
5
|
+
before :each do
|
6
|
+
@repo = Grit::Repo.new(".")
|
7
|
+
@before = "7e32af569ba794b0b1c5e4c38fef1d4e2e56be51"
|
8
|
+
@after = "a66d3ce668ae6f2a42d54d811962724200d5b32b"
|
9
|
+
end
|
10
|
+
|
11
|
+
it "parses ref name from head" do
|
12
|
+
Flowdock::Git::Builder.new(@repo, "refs/heads/master", @before, @after).ref_name.should == "master"
|
13
|
+
end
|
14
|
+
|
15
|
+
it "parses ref name from tag" do
|
16
|
+
Flowdock::Git::Builder.new(@repo, "refs/tags/release-1.0", @before, @after).ref_name.should == "release-1.0"
|
17
|
+
end
|
18
|
+
|
19
|
+
it "detects new branch and sets created=true in data" do
|
20
|
+
hash = Flowdock::Git::Builder.new(@repo, "refs/heads/master", "0000000000000000000000000000000000000000", @after).to_hash
|
21
|
+
hash[:created].should eq(true)
|
22
|
+
hash[:deleted].should_not eq(true)
|
23
|
+
end
|
24
|
+
|
25
|
+
it "detects deleted branch and sets deleted=true in data" do
|
26
|
+
hash = Flowdock::Git::Builder.new(@repo, "refs/heads/master", @before, "0000000000000000000000000000000000000000").to_hash
|
27
|
+
hash[:deleted].should eq(true)
|
28
|
+
hash[:created].should_not eq(true)
|
29
|
+
end
|
30
|
+
|
31
|
+
it "doesn't include commits in branch delete" do
|
32
|
+
hash = Flowdock::Git::Builder.new(@repo, "refs/heads/master", @before, "0000000000000000000000000000000000000000").to_hash
|
33
|
+
hash[:commits].should be_empty
|
34
|
+
end
|
35
|
+
|
36
|
+
describe "data hash" do
|
37
|
+
before :each do
|
38
|
+
@repo.stub!(:path).and_return("/foo/bar/flowdock-git-hook/.git")
|
39
|
+
@hash = Flowdock::Git::Builder.new(@repo, "refs/heads/master", @before, @after).to_hash
|
40
|
+
end
|
41
|
+
|
42
|
+
if RUBY_VERSION > '1.9'
|
43
|
+
it "properly sets encoding for UTF-8 content" do
|
44
|
+
builder = Flowdock::Git::Builder.new(@repo, "refs/heads/master", @before, "0000000000000000000000000000000000000000")
|
45
|
+
builder.stub(:commits).and_return([
|
46
|
+
{
|
47
|
+
:id => "0000000000000000000000000000000000000001",
|
48
|
+
:message => "This message contains UTF-8: ö".force_encoding("ASCII-8BIT"),
|
49
|
+
:timestamp => Time.now.iso8601,
|
50
|
+
:author => {
|
51
|
+
:name => "Föö Bär".force_encoding("ASCII-8BIT"),
|
52
|
+
:email => "foo@example.com"
|
53
|
+
},
|
54
|
+
:removed => [],
|
55
|
+
:added => [],
|
56
|
+
:modified => []
|
57
|
+
}
|
58
|
+
])
|
59
|
+
builder.to_hash[:commits][0][:message].encoding.should eq(Encoding::UTF_8)
|
60
|
+
builder.to_hash[:commits][0][:message].should == "This message contains UTF-8: ö"
|
61
|
+
end
|
62
|
+
|
63
|
+
it "encodes ISO-8859-1 to UTF-8" do
|
64
|
+
builder = Flowdock::Git::Builder.new(@repo, "refs/heads/master", @before, "0000000000000000000000000000000000000000")
|
65
|
+
builder.stub(:commits).and_return([
|
66
|
+
{
|
67
|
+
:id => "0000000000000000000000000000000000000001",
|
68
|
+
:message => "This message contains UTF-8: ö".encode("ISO-8859-1").force_encoding("ASCII-8BIT"),
|
69
|
+
:timestamp => Time.now.iso8601,
|
70
|
+
:author => {
|
71
|
+
:name => "Föö Bär".encode("ISO-8859-1").force_encoding("ASCII-8BIT"),
|
72
|
+
:email => "foo@example.com"
|
73
|
+
},
|
74
|
+
:removed => [],
|
75
|
+
:added => [],
|
76
|
+
:modified => []
|
77
|
+
}
|
78
|
+
])
|
79
|
+
builder.to_hash[:commits][0][:author][:name].encoding.should eq(Encoding::UTF_8)
|
80
|
+
builder.to_hash[:commits][0][:author][:name].should == "Föö Bär"
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
it "contains before" do
|
85
|
+
@hash[:before].should == @before
|
86
|
+
end
|
87
|
+
|
88
|
+
it "contains after" do
|
89
|
+
@hash[:after].should == @after
|
90
|
+
end
|
91
|
+
|
92
|
+
it "contains ref" do
|
93
|
+
@hash[:ref].should == "refs/heads/master"
|
94
|
+
end
|
95
|
+
|
96
|
+
it "contains ref name" do
|
97
|
+
@hash[:ref_name].should == "master"
|
98
|
+
end
|
99
|
+
|
100
|
+
describe "commits" do
|
101
|
+
it "contains all changed commits" do
|
102
|
+
@hash[:commits].should have(2).items
|
103
|
+
end
|
104
|
+
|
105
|
+
it "has commit author information" do
|
106
|
+
@hash[:commits].first[:author][:name].should eq("Ville Lautanala")
|
107
|
+
@hash[:commits].first[:author][:email].should eq("lautis@gmail.com")
|
108
|
+
end
|
109
|
+
|
110
|
+
it "has commit id" do
|
111
|
+
@hash[:commits].first[:id].should == "cf4a78c59cf9e06ebd7336900b2a66b85a88b76c"
|
112
|
+
end
|
113
|
+
|
114
|
+
it "puts deleted files in an array" do
|
115
|
+
@hash[:commits].first[:removed].should include("spec/flowdock-git-hook_spec.rb")
|
116
|
+
end
|
117
|
+
|
118
|
+
it "puts added files to an array" do
|
119
|
+
@hash[:commits].first[:added].should include("lib/flowdock/git.rb")
|
120
|
+
end
|
121
|
+
|
122
|
+
it "detects modified files" do
|
123
|
+
@hash[:commits].first[:modified].should_not include("spec/flowdock-git-hook_spec.rb")
|
124
|
+
@hash[:commits].first[:modified].should_not include("lib/flowdock/git.rb")
|
125
|
+
@hash[:commits].first[:modified].should include("lib/flowdock-git-hook.rb")
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
describe "repository information" do
|
130
|
+
it "contains repository name based on file path" do
|
131
|
+
@hash[:repository][:name] = "flowdock-git-hook"
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
describe "Flowdock Git Hook" do
|
4
|
+
it "raises error if git token is not defined" do
|
5
|
+
lambda {
|
6
|
+
Flowdock::Git.new
|
7
|
+
}.should raise_error(Flowdock::Git::TokenError)
|
8
|
+
end
|
9
|
+
|
10
|
+
it "can read token from git config" do
|
11
|
+
Grit::Config.stub!(:new).and_return({
|
12
|
+
"flowdock.token" => "flowdock-token"
|
13
|
+
})
|
14
|
+
|
15
|
+
lambda {
|
16
|
+
Flowdock::Git.new
|
17
|
+
}.should_not raise_error
|
18
|
+
end
|
19
|
+
|
20
|
+
it "encodes content as UTF-8" do
|
21
|
+
@repo = Grit::Repo.new(".")
|
22
|
+
@before = "7e32af569ba794b0b1c5e4c38fef1d4e2e56be51"
|
23
|
+
@after = "a66d3ce668ae6f2a42d54d811962724200d5b32b"
|
24
|
+
@repo.stub!(:path).and_return("/foo/bar/flowdock-git-hook/.git")
|
25
|
+
@hash = Flowdock::Git::Builder.new(@repo, "refs/heads/master", @before, @after).to_hash
|
26
|
+
end
|
27
|
+
|
28
|
+
it "builds payload" do
|
29
|
+
stub_request(:post, "https://api.flowdock.com/v1/git/flowdock-token")
|
30
|
+
Flowdock::Git.post("refs/heads/master", "7e32af569ba794b0b1c5e4c38fef1d4e2e56be51", "a1a94ba4bfa5f855676066861604b8edae1a20f5", :token => "flowdock-token")
|
31
|
+
a_request(:post, "https://api.flowdock.com/v1/git/flowdock-token").with { |req|
|
32
|
+
req.body.match(/7e32af569ba794b0b1c5e4c38fef1d4e2e56be51/)
|
33
|
+
}.should have_been_made
|
34
|
+
end
|
35
|
+
|
36
|
+
it "builds payload with repo url, diff url and commit urls" do
|
37
|
+
Grit::Config.stub!(:new).and_return({
|
38
|
+
"flowdock.token" => "flowdock-token",
|
39
|
+
"flowdock.repository-url" => "http://www.example.com",
|
40
|
+
"flowdock.diff-url-pattern" => "http://www.example.com/compare/%s...%s",
|
41
|
+
"flowdock.commit-url-pattern" => "http://www.example.com/commit/%s"
|
42
|
+
})
|
43
|
+
stub_request(:post, "https://api.flowdock.com/v1/git/flowdock-token")
|
44
|
+
Flowdock::Git.post("refs/heads/master", "7e32af569ba794b0b1c5e4c38fef1d4e2e56be51", "a1a94ba4bfa5f855676066861604b8edae1a20f5", :token => "flowdock-token")
|
45
|
+
a_request(:post, "https://api.flowdock.com/v1/git/flowdock-token").with { |req|
|
46
|
+
body = CGI.unescape(req.body)
|
47
|
+
body.match("http://www.example.com/") &&
|
48
|
+
body.match("http://www.example.com/compare/7e32af569ba794b0b1c5e4c38fef1d4e2e56be51...a1a94ba4bfa5f855676066861604b8edae1a20f5")
|
49
|
+
}.should have_been_made
|
50
|
+
end
|
51
|
+
|
52
|
+
describe "Tagging" do
|
53
|
+
it "reads tags from initializer parameter" do
|
54
|
+
tags = Flowdock::Git.new(:token => "flowdock-token", :tags => ["foo", "bar"]).send(:tags)
|
55
|
+
tags.should include("foo", "bar")
|
56
|
+
end
|
57
|
+
|
58
|
+
it "reads tags from gitconfig as fallback" do
|
59
|
+
Grit::Config.stub!(:new).and_return({
|
60
|
+
"flowdock.tags" => "foo,bar"
|
61
|
+
})
|
62
|
+
tags = Flowdock::Git.new(:token => "flowdock-token").send(:tags)
|
63
|
+
tags.should include("foo", "bar")
|
64
|
+
end
|
65
|
+
|
66
|
+
it "encodes tags suitable for URI" do
|
67
|
+
Flowdock::Git.new(:token => "flowdock-token", :tags => ["foo%bar"]).send(:tags).should include("foo%25bar")
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
describe "Flowdock Git Hook", "HTTP Post" do
|
73
|
+
before :each do
|
74
|
+
stub_request(:post, "https://api.flowdock.com/v1/git/flowdock-token+foo+bar")
|
75
|
+
Flowdock::Git.post("origin/refs/master", "7e32af569ba794b0b1c5e4c38fef1d4e2e56be51", "a1a94ba4bfa5f855676066861604b8edae1a20f5", :token => "flowdock-token", :tags => ["foo", "bar"])
|
76
|
+
end
|
77
|
+
|
78
|
+
it "posts to api.flowdock.com" do
|
79
|
+
a_request(:post, "https://api.flowdock.com/v1/git/flowdock-token+foo+bar").should have_been_made
|
80
|
+
end
|
81
|
+
|
82
|
+
it "sends payload encoded as JSON" do
|
83
|
+
payload = MultiJson.encode(Flowdock::Git::Builder.new(Grit::Repo.new("."), "origin/refs/master", "7e32af569ba794b0b1c5e4c38fef1d4e2e56be51", "a1a94ba4bfa5f855676066861604b8edae1a20f5").to_hash)
|
84
|
+
a_request(:post, "https://api.flowdock.com/v1/git/flowdock-token+foo+bar").with(:body => {:payload => payload}).should have_been_made
|
85
|
+
end
|
86
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
2
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
3
|
+
require 'rspec'
|
4
|
+
require 'webmock/rspec'
|
5
|
+
require 'flowdock-git-hook'
|
6
|
+
|
7
|
+
# Requires supporting files with custom matchers and macros, etc,
|
8
|
+
# in ./support/ and its subdirectories.
|
9
|
+
Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
|
10
|
+
|
11
|
+
RSpec.configure do |config|
|
12
|
+
end
|
metadata
ADDED
@@ -0,0 +1,185 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: gitlab-flowdock-git-hook
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 4
|
8
|
+
- 2
|
9
|
+
- 2
|
10
|
+
version: 0.4.2.2
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Ville Lautanala
|
14
|
+
- Boyan Tabakov
|
15
|
+
autorequire:
|
16
|
+
bindir: bin
|
17
|
+
cert_chain: []
|
18
|
+
|
19
|
+
date: 2013-10-03 00:00:00 +03:00
|
20
|
+
default_executable:
|
21
|
+
dependencies:
|
22
|
+
- !ruby/object:Gem::Dependency
|
23
|
+
name: gitlab-grit
|
24
|
+
prerelease: false
|
25
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
segments:
|
30
|
+
- 2
|
31
|
+
- 4
|
32
|
+
- 1
|
33
|
+
version: 2.4.1
|
34
|
+
type: :runtime
|
35
|
+
version_requirements: *id001
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: multi_json
|
38
|
+
prerelease: false
|
39
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
segments:
|
44
|
+
- 0
|
45
|
+
version: "0"
|
46
|
+
type: :runtime
|
47
|
+
version_requirements: *id002
|
48
|
+
- !ruby/object:Gem::Dependency
|
49
|
+
name: rdoc
|
50
|
+
prerelease: false
|
51
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - ">="
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
segments:
|
56
|
+
- 2
|
57
|
+
- 4
|
58
|
+
- 2
|
59
|
+
version: 2.4.2
|
60
|
+
type: :development
|
61
|
+
version_requirements: *id003
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: rspec
|
64
|
+
prerelease: false
|
65
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - ~>
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
segments:
|
70
|
+
- 2
|
71
|
+
- 8
|
72
|
+
version: "2.8"
|
73
|
+
type: :development
|
74
|
+
version_requirements: *id004
|
75
|
+
- !ruby/object:Gem::Dependency
|
76
|
+
name: bundler
|
77
|
+
prerelease: false
|
78
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ~>
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
segments:
|
83
|
+
- 1
|
84
|
+
- 0
|
85
|
+
version: "1.0"
|
86
|
+
type: :development
|
87
|
+
version_requirements: *id005
|
88
|
+
- !ruby/object:Gem::Dependency
|
89
|
+
name: jeweler
|
90
|
+
prerelease: false
|
91
|
+
requirement: &id006 !ruby/object:Gem::Requirement
|
92
|
+
requirements:
|
93
|
+
- - ~>
|
94
|
+
- !ruby/object:Gem::Version
|
95
|
+
segments:
|
96
|
+
- 1
|
97
|
+
- 8
|
98
|
+
- 7
|
99
|
+
version: 1.8.7
|
100
|
+
type: :development
|
101
|
+
version_requirements: *id006
|
102
|
+
- !ruby/object:Gem::Dependency
|
103
|
+
name: webmock
|
104
|
+
prerelease: false
|
105
|
+
requirement: &id007 !ruby/object:Gem::Requirement
|
106
|
+
requirements:
|
107
|
+
- - ">="
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
segments:
|
110
|
+
- 1
|
111
|
+
- 6
|
112
|
+
- 4
|
113
|
+
version: 1.6.4
|
114
|
+
type: :development
|
115
|
+
version_requirements: *id007
|
116
|
+
- !ruby/object:Gem::Dependency
|
117
|
+
name: jruby-openssl
|
118
|
+
prerelease: false
|
119
|
+
requirement: &id008 !ruby/object:Gem::Requirement
|
120
|
+
requirements:
|
121
|
+
- - ">="
|
122
|
+
- !ruby/object:Gem::Version
|
123
|
+
segments:
|
124
|
+
- 0
|
125
|
+
version: "0"
|
126
|
+
type: :development
|
127
|
+
version_requirements: *id008
|
128
|
+
description:
|
129
|
+
email: blade@alslayer.net
|
130
|
+
executables: []
|
131
|
+
|
132
|
+
extensions: []
|
133
|
+
|
134
|
+
extra_rdoc_files:
|
135
|
+
- LICENSE.txt
|
136
|
+
- README.md
|
137
|
+
files:
|
138
|
+
- .document
|
139
|
+
- .rspec
|
140
|
+
- .travis.yml
|
141
|
+
- Gemfile
|
142
|
+
- LICENSE.txt
|
143
|
+
- README.md
|
144
|
+
- Rakefile
|
145
|
+
- VERSION
|
146
|
+
- gitlab-flowdock-git-hook.gemspec
|
147
|
+
- lib/flowdock-git-hook.rb
|
148
|
+
- lib/flowdock/git.rb
|
149
|
+
- lib/flowdock/git/builder.rb
|
150
|
+
- post-receive
|
151
|
+
- spec/builder_spec.rb
|
152
|
+
- spec/flowdock_git_spec.rb
|
153
|
+
- spec/spec_helper.rb
|
154
|
+
has_rdoc: true
|
155
|
+
homepage: http://github.com/bladealslayer/flowdock-git-hook
|
156
|
+
licenses:
|
157
|
+
- MIT
|
158
|
+
post_install_message:
|
159
|
+
rdoc_options: []
|
160
|
+
|
161
|
+
require_paths:
|
162
|
+
- lib
|
163
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
164
|
+
requirements:
|
165
|
+
- - ">="
|
166
|
+
- !ruby/object:Gem::Version
|
167
|
+
segments:
|
168
|
+
- 0
|
169
|
+
version: "0"
|
170
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
171
|
+
requirements:
|
172
|
+
- - ">="
|
173
|
+
- !ruby/object:Gem::Version
|
174
|
+
segments:
|
175
|
+
- 0
|
176
|
+
version: "0"
|
177
|
+
requirements: []
|
178
|
+
|
179
|
+
rubyforge_project:
|
180
|
+
rubygems_version: 1.3.6
|
181
|
+
signing_key:
|
182
|
+
specification_version: 4
|
183
|
+
summary: Git Post-Receive hook for Flowdock. Gem requirements patched for use with Gitlab.
|
184
|
+
test_files: []
|
185
|
+
|