foca-integrity 0.1.8 → 0.1.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (75) hide show
  1. data/README.markdown +7 -0
  2. data/Rakefile +89 -81
  3. data/config/config.sample.ru +11 -21
  4. data/config/config.sample.yml +15 -12
  5. data/lib/integrity.rb +21 -23
  6. data/lib/integrity/app.rb +138 -0
  7. data/lib/integrity/author.rb +39 -0
  8. data/lib/integrity/build.rb +54 -31
  9. data/lib/integrity/commit.rb +71 -0
  10. data/lib/integrity/helpers.rb +3 -3
  11. data/lib/integrity/helpers/authorization.rb +2 -2
  12. data/lib/integrity/helpers/forms.rb +3 -3
  13. data/lib/integrity/helpers/pretty_output.rb +1 -1
  14. data/lib/integrity/helpers/rendering.rb +6 -1
  15. data/lib/integrity/helpers/resources.rb +9 -3
  16. data/lib/integrity/helpers/urls.rb +15 -13
  17. data/lib/integrity/installer.rb +43 -60
  18. data/lib/integrity/migrations.rb +31 -48
  19. data/lib/integrity/notifier.rb +14 -16
  20. data/lib/integrity/notifier/base.rb +29 -19
  21. data/lib/integrity/notifier/test_helpers.rb +100 -0
  22. data/lib/integrity/project.rb +69 -33
  23. data/lib/integrity/project_builder.rb +23 -14
  24. data/lib/integrity/scm/git.rb +15 -14
  25. data/lib/integrity/scm/git/uri.rb +9 -9
  26. data/test/acceptance/api_test.rb +97 -0
  27. data/test/acceptance/browse_project_builds_test.rb +65 -0
  28. data/test/acceptance/browse_project_test.rb +95 -0
  29. data/test/acceptance/build_notifications_test.rb +42 -0
  30. data/test/acceptance/create_project_test.rb +97 -0
  31. data/test/acceptance/delete_project_test.rb +53 -0
  32. data/test/acceptance/edit_project_test.rb +117 -0
  33. data/test/acceptance/error_page_test.rb +18 -0
  34. data/test/acceptance/helpers.rb +2 -0
  35. data/test/acceptance/installer_test.rb +62 -0
  36. data/test/acceptance/manual_build_project_test.rb +82 -0
  37. data/test/acceptance/notifier_test.rb +109 -0
  38. data/test/acceptance/project_syndication_test.rb +30 -0
  39. data/test/acceptance/stylesheet_test.rb +18 -0
  40. data/test/helpers.rb +59 -27
  41. data/test/helpers/acceptance.rb +19 -64
  42. data/test/helpers/acceptance/email_notifier.rb +55 -0
  43. data/test/helpers/acceptance/git_helper.rb +15 -15
  44. data/test/helpers/acceptance/textfile_notifier.rb +3 -3
  45. data/test/helpers/expectations.rb +0 -1
  46. data/test/helpers/expectations/be_a.rb +4 -4
  47. data/test/helpers/expectations/change.rb +5 -5
  48. data/test/helpers/expectations/have.rb +4 -4
  49. data/test/helpers/expectations/predicates.rb +4 -4
  50. data/test/helpers/fixtures.rb +44 -18
  51. data/test/helpers/initial_migration_fixture.sql +44 -0
  52. data/test/unit/build_test.rb +51 -0
  53. data/test/unit/commit_test.rb +83 -0
  54. data/test/unit/helpers_test.rb +56 -0
  55. data/test/unit/integrity_test.rb +18 -0
  56. data/test/unit/migrations_test.rb +56 -0
  57. data/test/unit/notifier_test.rb +123 -0
  58. data/test/unit/project_builder_test.rb +108 -0
  59. data/test/unit/project_test.rb +282 -0
  60. data/test/unit/scm_test.rb +54 -0
  61. data/views/_commit_info.haml +24 -0
  62. data/views/build.haml +2 -2
  63. data/views/error.haml +4 -3
  64. data/views/home.haml +3 -5
  65. data/views/integrity.sass +19 -6
  66. data/views/new.haml +6 -6
  67. data/views/project.builder +9 -9
  68. data/views/project.haml +14 -12
  69. metadata +98 -116
  70. data/VERSION.yml +0 -4
  71. data/app.rb +0 -137
  72. data/integrity.gemspec +0 -76
  73. data/lib/integrity/core_ext/string.rb +0 -5
  74. data/test/helpers/expectations/have_tag.rb +0 -128
  75. data/views/_build_info.haml +0 -18
data/README.markdown CHANGED
@@ -8,6 +8,13 @@ Integrity
8
8
  * Join us on [#integrity][irc-channel] for ideas, help, patches or something
9
9
  * Get the code on [GitHub][repo]
10
10
 
11
+ Try it!
12
+ -------
13
+
14
+ $ git clone git://github.com/foca/integrity.git
15
+ $ rake launch
16
+ # Navigate to <http://0.0.0.0:4567>
17
+
11
18
  Thanks
12
19
  ------
13
20
 
data/Rakefile CHANGED
@@ -1,13 +1,38 @@
1
- require File.dirname(__FILE__) + "/lib/integrity"
2
1
  require "rake/testtask"
2
+ require "rake/clean"
3
3
  require "rcov/rcovtask"
4
4
 
5
- desc "Run all tests and check test coverage"
6
- task :default => "test:coverage:verify"
5
+ begin
6
+ require "metric_fu"
7
+ rescue LoadError
8
+ end
9
+
10
+ desc "Default: run all tests"
11
+ task :default => :test
12
+
13
+ desc "Special task for running tests on <http://builder.integrityapp.com>"
14
+ task :ci do
15
+ sh "git submodule update --init"
16
+
17
+ Rake::Task["test"].invoke
18
+
19
+ metrics = %w(flay flog:all reek roodi saikuro)
20
+ metrics.each { |m| Rake::Task["metrics:#{m}"].invoke }
21
+
22
+ rm_rf "/var/www/integrity-metrics"
23
+ mv "tmp/metric_fu", "/var/www/integrity-metrics"
24
+
25
+ File.open("/var/www/integrity-metrics/index.html", "w") { |f|
26
+ f << "<ul>"
27
+ metrics.map { |m| m.split(":").first }.each { |m|
28
+ f << %Q(<li><a href="/#{m}">#{m}</a></li>)
29
+ }
30
+ f << "</ul>"
31
+ }
32
+ end
7
33
 
8
34
  desc "Run tests"
9
35
  task :test => %w(test:units test:acceptance)
10
-
11
36
  namespace :test do
12
37
  Rake::TestTask.new(:units) do |t|
13
38
  t.test_files = FileList["test/unit/*_test.rb"]
@@ -17,94 +42,77 @@ namespace :test do
17
42
  t.test_files = FileList["test/acceptance/*_test.rb"]
18
43
  end
19
44
 
20
- desc "Measure test coverage"
21
- task :coverage => %w(test:coverage:units test:coverage:acceptance)
45
+ desc "Install all gems on which the tests depend on"
46
+ task :install_dependencies do
47
+ system "gem install rr mocha dm-sweatshop ZenTest"
48
+ system "gem install -s http://gems.github.com jeremymcanally-context \
49
+ jeremymcanally-matchy jeremymcanally-pending foca-storyteller"
50
+ system "git submodule update --init"
51
+ end
52
+ end
22
53
 
23
- namespace :coverage do
24
- desc "Measure test coverage of unit tests"
25
- Rcov::RcovTask.new(:units) do |rcov|
26
- rcov.pattern = "test/unit/*_test.rb"
27
- rcov.rcov_opts = %w(--html --aggregate .aggregated_coverage_report)
28
- rcov.rcov_opts << ENV["RCOV_OPTS"] if ENV["RCOV_OPTS"]
29
- end
54
+ desc "Launch Integrity real quick"
55
+ task :launch do
56
+ ruby "bin/integrity launch"
57
+ end
30
58
 
31
- desc "Measure test coverage of acceptance tests"
32
- Rcov::RcovTask.new(:acceptance) do |rcov|
33
- rcov.pattern = "test/acceptance/*_test.rb"
34
- rcov.rcov_opts = %w(--html --aggregate .aggregated_coverage_report)
35
- rcov.rcov_opts << ENV["RCOV_OPTS"] if ENV["RCOV_OPTS"]
59
+ directory "dist/"
60
+ CLOBBER.include("dist")
61
+
62
+ # Load the gemspec using the same limitations as github
63
+ def spec
64
+ @spec ||=
65
+ begin
66
+ require "rubygems/specification"
67
+ data = File.read("integrity.gemspec")
68
+ spec = nil
69
+ Thread.new { spec = eval("$SAFE = 3\n#{data}") }.join
70
+ spec
36
71
  end
72
+ end
37
73
 
38
- desc "Verify test coverage"
39
- task :verify => "test:coverage" do
40
- File.read("coverage/index.html") =~ /<tt class='coverage_total'>\s*(\d+\.\d+)%\s*<\/tt>/
41
- coverage = $1.to_f
42
-
43
- puts
44
- if coverage == 100
45
- puts "\e[32m100% coverage! Awesome!\e[0m"
46
- else
47
- puts "\e[31mOnly #{coverage}% code coverage. You can do better ;)\e[0m"
48
- end
49
- end
50
- end
74
+ def package(ext="")
75
+ "dist/integrity-#{spec.version}" + ext
76
+ end
51
77
 
52
- desc "Install all gems on which the tests depend on"
53
- task :install_dependencies do
54
- system 'gem install redgreen rr mocha ruby-debug dm-sweatshop webrat'
55
- system 'gem install -s http://gems.github.com jeremymcanally-context jeremymcanally-matchy jeremymcanally-pending foca-storyteller'
56
- end
78
+ desc "Build and install as local gem"
79
+ task :install => package('.gem') do
80
+ sh "gem install #{package('.gem')}"
57
81
  end
58
82
 
59
- namespace :db do
60
- desc "Setup connection."
61
- task :connect do
62
- config = File.expand_path(ENV['CONFIG']) if ENV['CONFIG']
63
- config = Integrity.root / 'config.yml' if File.exists?(Integrity.root / 'config.yml')
64
- Integrity.new(config)
83
+ desc "Publish the current release on Rubyforge"
84
+ task :rubyforge => ["rubyforge:gem", "rubyforge:tarball", "rubyforge:git"]
85
+
86
+ namespace :rubyforge do
87
+ desc "Publish gem and tarball to rubyforge"
88
+ task :gem => package(".gem") do
89
+ sh "rubyforge add_release integrity integrity #{spec.version} #{package('.gem')}"
65
90
  end
66
91
 
67
- desc "Automigrate the database"
68
- task :migrate => :connect do
69
- require "project"
70
- require "build"
71
- require "notifier"
72
- DataMapper.auto_migrate!
92
+ task :tarball => package(".tar.gz") do
93
+ sh "rubyforge add_file integrity integrity #{spec.version} #{package('.tar.gz')}"
73
94
  end
74
- end
75
95
 
76
- begin
77
- require 'jeweler'
78
- Jeweler::Tasks.new do |s|
79
- files = `git ls-files`.split("\n").reject {|f| f =~ %r(^test/acceptance) || f =~ %r(^test/unit) || f =~ /^\.git/ }
80
-
81
- s.name = 'integrity'
82
- s.summary = 'The easy and fun Continuous Integration server'
83
- s.description = 'Your Friendly Continuous Integration server. Easy, fun and painless!'
84
- s.homepage = 'http://integrityapp.com'
85
- s.rubyforge_project = 'integrity'
86
- s.email = 'contacto@nicolassanguinetti.info'
87
- s.authors = ['Nicolás Sanguinetti', 'Simon Rozet']
88
- s.files = files
89
- s.executables = ['integrity']
90
- s.post_install_message = 'Run `integrity help` for information on how to setup Integrity.'
91
-
92
- s.add_dependency 'sinatra', ['>= 0.9.0.3']
93
- s.add_dependency 'haml' # ah, you evil monkey you
94
- s.add_dependency 'dm-core', ['>= 0.9.5']
95
- s.add_dependency 'dm-validations', ['>= 0.9.5']
96
- s.add_dependency 'dm-types', ['>= 0.9.5']
97
- s.add_dependency 'dm-timestamps', ['>= 0.9.5']
98
- s.add_dependency 'dm-aggregates', ['>= 0.9.5']
99
- s.add_dependency 'dm-migrations', ['>= 0.9.5']
100
- s.add_dependency 'data_objects', ['>= 0.9.5']
101
- s.add_dependency 'do_sqlite3', ['>= 0.9.5']
102
- s.add_dependency 'json'
103
- s.add_dependency 'foca-sinatra-diddies', ['>= 0.0.2']
104
- s.add_dependency 'thor'
105
- s.add_dependency 'uuidtools' # required by dm-types
106
- s.add_dependency 'bcrypt-ruby' # required by dm-types
96
+ desc "Push to gitosis@rubyforge.org:integrity.git"
97
+ task :git do
98
+ sh "git push gitosis@rubyforge.org:integrity.git master"
107
99
  end
108
- rescue LoadError
109
100
  end
110
101
 
102
+ desc "Build gem tarball into dist/"
103
+ task :package => %w(.gem .tar.gz).map { |ext| package(ext) }
104
+ namespace :package do
105
+ file package(".tar.gz") => "dist/" do |f|
106
+ sh <<-SH
107
+ git archive \
108
+ --prefix=integrity-#{spec.version}/ \
109
+ --format=tar \
110
+ HEAD | gzip > #{f.name}
111
+ SH
112
+ end
113
+
114
+ file package(".gem") => "dist/" do |f|
115
+ sh "gem build integrity.gemspec"
116
+ mv File.basename(f.name), f.name
117
+ end
118
+ end
@@ -1,31 +1,21 @@
1
1
  #!/usr/bin/env ruby
2
- require 'rubygems'
3
- require 'integrity'
2
+ require "rubygems"
3
+ require "integrity"
4
4
 
5
5
  # If you want to add any notifiers, install the gems and then require them here
6
- # For example, to enable the Email notifier: install the gem (from github:
6
+ # For example, to enable the Email notifier: install the gem (from github:
7
7
  #
8
8
  # sudo gem install -s http://gems.github.com foca-integrity-email
9
- #
9
+ #
10
10
  # And then uncomment the following line:
11
- #
11
+ #
12
12
  # require "notifier/email"
13
13
 
14
- # Load integrity's configuration.
15
- Integrity.config = File.expand_path('./config.yml')
16
-
17
- #######################################################################
18
- ## ##
19
- ## == DON'T EDIT ANYTHING BELOW UNLESS YOU KNOW WHAT YOU'RE DOING == ##
20
- ## ##
21
- #######################################################################
22
- require Integrity.root / 'app'
14
+ # Load configuration and initialize Integrity
15
+ Integrity.new(File.dirname(__FILE__) + "/config.yml")
23
16
 
24
- set :public, Integrity.root / 'public'
25
- set :views, Integrity.root / 'views'
26
- set :port, 8910
27
- set :env, :production
28
- disable :run, :reload
17
+ # You probably don't want to edit anything below
18
+ Integrity::App.set :environment, ENV["RACK_ENV"] || :production
19
+ Integrity::App.set :port, 8910
29
20
 
30
- use Rack::CommonLogger, Integrity.logger if Integrity.config[:log_debug_info]
31
- run Sinatra::Application
21
+ run Integrity::App
@@ -4,24 +4,27 @@
4
4
  # http://builder.integrityapp.com
5
5
  :base_uri: http://integrity.domain.tld
6
6
 
7
- # This should be a complete connection string to your database. For example
8
- # `mysql://user@localhost/integrity` (you need an `integrity` db created in
9
- # localhost, of course).
7
+ # This should be a complete connection string to your database.
8
+ #
9
+ # Examples:
10
+ # * `mysql://user:password@localhost/integrity`
11
+ # * `postgres://user:password@localhost/integrity`
12
+ # * `sqlite3:///home/integrity/db/integrity.sqlite`
13
+ #
14
+ # Note:
15
+ # * The appropriate data_objects adapter must be installed (`do_mysql`, etc)
16
+ # * You must create the `integrity` database on localhost, of course.
10
17
  :database_uri: sqlite3:///var/integrity.db
11
18
 
12
- # This is where your project's code will be checked out to. Make sure it's
19
+ # This is where your project's code will be checked out to. Make sure it's
13
20
  # writable by the user that runs Integrity.
14
21
  :export_directory: /path/to/scm/exports
15
22
 
16
23
  # Path to the integrity log file
17
24
  :log: /var/log/integrity.log
18
25
 
19
- # Enable/Disable debug logging. Turning this on will log queries made to the
20
- # database and web requests (if using the provided rackup file)
21
- :log_debug_info: false
22
-
23
- # Enable or disable HTTP authentication for the app. BE AWARE that if you
24
- # disable this anyone can delete and alter projects, so do it only if your
26
+ # Enable or disable HTTP authentication for the app. BE AWARE that if you
27
+ # disable this anyone can delete and alter projects, so do it only if your
25
28
  # app is running in a controlled environment (ie, behind your company's
26
29
  # firewall.)
27
30
  :use_basic_auth: false
@@ -29,10 +32,10 @@
29
32
  # When `use_basic_auth` is true, the admin's username for HTTP authentication.
30
33
  :admin_username: username
31
34
 
32
- # When `use_basic_auth` is true, the admin's password. Usually saved as a
35
+ # When `use_basic_auth` is true, the admin's password. Usually saved as a
33
36
  # SHA1 hash. See the next option.
34
37
  :admin_password: a94a8fe5ccb19ba61c4c0873d391e987982fbbd3
35
38
 
36
- # If this is true, then whenever we authenticate the admin user, will hash
39
+ # If this is true, then whenever we authenticate the admin user, will hash
37
40
  # it using SHA1. If not, we'll assume the provided password is in plain text.
38
41
  :hash_admin_password: true
data/lib/integrity.rb CHANGED
@@ -1,40 +1,41 @@
1
- __DIR__ = File.dirname(__FILE__)
2
- $:.unshift "#{__DIR__}/integrity", *Dir["#{__DIR__}/../vendor/**/lib"].to_a
1
+ $:.unshift File.expand_path(File.dirname(__FILE__))
3
2
 
4
- require "rubygems"
5
3
  require "json"
6
4
  require "dm-core"
7
5
  require "dm-validations"
8
6
  require "dm-types"
9
7
  require "dm-timestamps"
10
8
  require "dm-aggregates"
9
+ require "sinatra/base"
11
10
 
12
11
  require "yaml"
13
12
  require "logger"
14
13
  require "digest/sha1"
15
14
  require "timeout"
16
15
  require "ostruct"
17
- require "fileutils"
16
+ require "pathname"
18
17
 
19
- require "core_ext/object"
20
- require "core_ext/string"
18
+ require "integrity/core_ext/object"
21
19
 
22
- require "project"
23
- require "build"
24
- require "project_builder"
25
- require "scm"
26
- require "scm/git"
27
- require "notifier"
20
+ require "integrity/project"
21
+ require "integrity/author"
22
+ require "integrity/commit"
23
+ require "integrity/build"
24
+ require "integrity/project_builder"
25
+ require "integrity/scm"
26
+ require "integrity/scm/git"
27
+ require "integrity/notifier"
28
+ require "integrity/helpers"
29
+ require "integrity/app"
28
30
 
29
31
  module Integrity
30
32
  def self.new(config_file = nil)
31
- self.config = config_file unless config_file.nil?
32
- DataMapper.logger = self.logger if config[:log_debug_info]
33
+ self.config = YAML.load_file(config_file) unless config_file.nil?
33
34
  DataMapper.setup(:default, config[:database_uri])
34
35
  end
35
36
 
36
37
  def self.root
37
- File.expand_path(File.join(File.dirname(__FILE__), ".."))
38
+ Pathname.new(File.dirname(__FILE__)).join("..").expand_path
38
39
  end
39
40
 
40
41
  def self.default_configuration
@@ -44,15 +45,15 @@ module Integrity
44
45
  :base_uri => "http://localhost:8910",
45
46
  :use_basic_auth => false,
46
47
  :build_all_commits => true,
47
- :log_debug_info => false }
48
+ :log_debug_info => false }.dup
48
49
  end
49
50
 
50
51
  def self.config
51
52
  @config ||= default_configuration
52
53
  end
53
54
 
54
- def self.config=(file)
55
- @config = default_configuration.merge(YAML.load_file(file))
55
+ def self.config=(options)
56
+ @config = default_configuration.merge(options)
56
57
  end
57
58
 
58
59
  def self.log(message, &block)
@@ -66,14 +67,11 @@ module Integrity
66
67
  end
67
68
 
68
69
  def self.version
69
- @version ||= begin
70
- file = YAML.load_file(Integrity.root / "VERSION.yml")
71
- "#{file['major']}.#{file['minor']}.#{file['patch']}"
72
- end
70
+ YAML.load_file(File.dirname(__FILE__) + "/../VERSION.yml").
71
+ values.join(".")
73
72
  end
74
73
 
75
74
  private
76
-
77
75
  class LogFormatter < Logger::Formatter
78
76
  def call(severity, time, progname, msg)
79
77
  time.strftime("[%H:%M:%S] ") + msg2str(msg) + "\n"
@@ -0,0 +1,138 @@
1
+ module Integrity
2
+ class App < Sinatra::Default
3
+ set :root, File.dirname(__FILE__) + "/../.."
4
+ set :app_file, __FILE__
5
+ enable :sessions
6
+
7
+ include Integrity
8
+ include Integrity::Helpers
9
+
10
+ not_found do
11
+ status 404
12
+ show :not_found, :title => "lost, are we?"
13
+ end
14
+
15
+ error do
16
+ @error = request.env["sinatra.error"]
17
+ status 500
18
+ show :error, :title => "something has gone terribly wrong"
19
+ end
20
+
21
+ before do
22
+ # The browser only sends http auth data for requests that are explicitly
23
+ # required to do so. This way we get the real values of +#logged_in?+ and
24
+ # +#current_user+
25
+ login_required if session[:user]
26
+ end
27
+
28
+ get "/integrity.css" do
29
+ response["Content-Type"] = "text/css; charset=utf-8"
30
+ etag stylesheet_hash
31
+ sass :integrity
32
+ end
33
+
34
+ get "/" do
35
+ @projects = Project.only_public_unless(authorized?)
36
+ show :home, :title => "projects"
37
+ end
38
+
39
+ get "/login" do
40
+ login_required
41
+
42
+ session[:user] = current_user
43
+ redirect root_url
44
+ end
45
+
46
+ get "/new" do
47
+ login_required
48
+
49
+ @project = Project.new
50
+ show :new, :title => ["projects", "new project"]
51
+ end
52
+
53
+ post "/" do
54
+ login_required
55
+
56
+ @project = Project.new(params[:project_data])
57
+
58
+ if @project.save
59
+ update_notifiers_of(@project)
60
+ redirect project_url(@project)
61
+ else
62
+ show :new, :title => ["projects", "new project"]
63
+ end
64
+ end
65
+
66
+ get "/:project.atom" do
67
+ login_required unless current_project.public?
68
+ response["Content-Type"] = "application/rss+xml; charset=utf-8"
69
+ builder :project
70
+ end
71
+
72
+ get "/:project" do
73
+ login_required unless current_project.public?
74
+ show :project, :title => ["projects", current_project.name]
75
+ end
76
+
77
+ put "/:project" do
78
+ login_required
79
+
80
+ if current_project.update_attributes(params[:project_data])
81
+ update_notifiers_of(current_project)
82
+ redirect project_url(current_project)
83
+ else
84
+ show :new, :title => ["projects", current_project.permalink, "edit"]
85
+ end
86
+ end
87
+
88
+ delete "/:project" do
89
+ login_required
90
+
91
+ current_project.destroy
92
+ redirect root_url
93
+ end
94
+
95
+ get "/:project/edit" do
96
+ login_required
97
+
98
+ show :new, :title => ["projects", current_project.permalink, "edit"]
99
+ end
100
+
101
+ post "/:project/push" do
102
+ login_required
103
+
104
+ content_type "text/plain"
105
+
106
+ begin
107
+ current_project.push(params[:payload])
108
+ 201
109
+ rescue ArgumentError
110
+ [422, "Invalid Request"]
111
+ end
112
+ end
113
+
114
+ post "/:project/builds" do
115
+ login_required
116
+
117
+ current_project.build
118
+ redirect project_url(current_project)
119
+ end
120
+
121
+ get "/:project/commits/:commit" do
122
+ login_required unless current_project.public?
123
+
124
+ show :build, :title => ["projects", current_project.permalink, current_commit.short_commit_identifier]
125
+ end
126
+
127
+ get "/:project/builds/:commit" do
128
+ redirect "/#{params[:project]}/commits/#{params[:commit]}", 301
129
+ end
130
+
131
+ post "/:project/commits/:commit/builds" do
132
+ login_required
133
+
134
+ current_project.build(params[:commit])
135
+ redirect commit_url(current_commit)
136
+ end
137
+ end
138
+ end