Skip to content

Commit

Permalink
Reposts PRs if they still haven't been reviewed in over 30 minutes
Browse files Browse the repository at this point in the history
But we only repost if it hasn't been reposted already.
  • Loading branch information
mxie committed Jan 9, 2015
1 parent 8729544 commit 3378e01
Show file tree
Hide file tree
Showing 11 changed files with 116 additions and 4 deletions.
1 change: 1 addition & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ gem "rack-timeout"
gem "rails", "4.2.0.rc2"
gem "recipient_interceptor"
gem "sass-rails"
gem "time_for_a_boolean"
gem "title"
gem "uglifier"
gem "unicorn"
Expand Down
6 changes: 3 additions & 3 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -233,9 +233,6 @@ GEM
sprockets (>= 2.8, < 4.0)
sprockets-rails (>= 2.0, < 4.0)
tilt (~> 1.1)
sawyer (0.5.5)
addressable (~> 2.3.5)
faraday (~> 0.8, < 0.10)
shoulda-matchers (2.7.0)
activesupport (>= 3.0.0)
slop (3.6.0)
Expand All @@ -258,6 +255,8 @@ GEM
thread (0.1.4)
thread_safe (0.3.4)
tilt (1.4.1)
time_for_a_boolean (0.0.5)
rails
timecop (0.7.1)
tins (1.3.3)
title (0.0.5)
Expand Down Expand Up @@ -316,6 +315,7 @@ DEPENDENCIES
shoulda-matchers
spring
spring-commands-rspec
time_for_a_boolean
timecop
title
uglifier
Expand Down
15 changes: 15 additions & 0 deletions app/models/pull_request.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
class PullRequest < ActiveRecord::Base
REPOST_THRESHOLD = 30

validates :github_url, presence: true, uniqueness: true
validates :repo_name, presence: true
validates :repo_github_url, presence: true
Expand All @@ -10,6 +12,8 @@ class PullRequest < ActiveRecord::Base

has_and_belongs_to_many :tags

time_for_a_boolean :reposted

def self.active
where(status: ["needs review", "in progress"])
end
Expand All @@ -24,6 +28,17 @@ def self.for_tags(tags)
end
end

def self.needs_reposting
timestamp = REPOST_THRESHOLD.minutes.ago

updated_before(timestamp).
where(status: "needs review", reposted_at: nil)
end

def self.updated_before(timestamp)
where("updated_at <= ?", timestamp)
end

def number
github_url.split("/").last
end
Expand Down
28 changes: 28 additions & 0 deletions app/services/pull_request_reposter.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
class PullRequestReposter
def initialize(pull_requests)
@pull_requests = pull_requests
end

def self.run(pull_requests)
self.new(pull_requests).run
end

def run
pull_requests.each do |pull_request|
post_to_slack(pull_request)
mark_as_reposted(pull_request)
end
end

private

attr_reader :pull_requests

def post_to_slack(pull_request)
WebhookNotifier.new(pull_request).send_notification
end

def mark_as_reposted(pull_request)
pull_request.update(reposted: true)
end
end
5 changes: 5 additions & 0 deletions db/migrate/20150108191114_add_reposted_at_to_pull_requests.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
class AddRepostedAtToPullRequests < ActiveRecord::Migration
def change
add_column :pull_requests, :reposted_at, :timestamp
end
end
3 changes: 2 additions & 1 deletion db/schema.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
#
# It's strongly recommended that you check this file into your version control system.

ActiveRecord::Schema.define(version: 20150107200715) do
ActiveRecord::Schema.define(version: 20150108191114) do

# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
Expand Down Expand Up @@ -45,6 +45,7 @@
t.string "avatar_url", default: "https://avatars1.githubusercontent.com/u/6183?v=3&s=200", null: false
t.integer "additions", default: 0, null: false
t.integer "deletions", default: 0, null: false
t.datetime "reposted_at"
end

add_index "pull_requests", ["status"], name: "index_pull_requests_on_status", using: :btree
Expand Down
4 changes: 4 additions & 0 deletions lib/tasks/scheduler.rake
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
desc "Reposts PRs that have not been reviewed for over 30 min. nor reposted"
task repost_prs: :environment do
PullRequestReposter.run(PullRequest.needs_reposting)
end
8 changes: 8 additions & 0 deletions spec/factories.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,14 @@
trait :in_progress do
status "in progress"
end

trait :needs_review do
status "needs review"
end

trait :stale do
updated_at { 31.minutes.ago }
end
end

factory :tag do
Expand Down
23 changes: 23 additions & 0 deletions spec/models/pull_request_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,27 @@
it { should validate_presence_of(:github_url) }
it { should validate_presence_of(:repo_name) }
it { should validate_presence_of(:status) }

describe ".needs_reposting" do
it "returns PRs that haven't been reviewed in over 30 minutes nor reposted" do
pr_to_report = create(:pull_request, :needs_review, reposted: false)
_reposted_pr = create(:pull_request, :needs_review, reposted: true)
_pr_in_progress = create(:pull_request, :in_progress)

travel(31.minutes) do
expect(PullRequest.needs_reposting).to eq [pr_to_report]
end
end
end

describe ".updated_before" do
it "returns pull requests that have not been updated since a given time" do
older_pr = create(:pull_request)

travel(31.minutes) do
_recently_updated_pr = create(:pull_request)
expect(PullRequest.updated_before(30.minutes.ago)).to eq [older_pr]
end
end
end
end
24 changes: 24 additions & 0 deletions spec/services/pull_request_reposter_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
require "rails_helper"

describe PullRequestReposter do
describe ".run" do
it "reposts the given PRs to Slack" do
prs_to_review = build_pair(:pull_request)
notifier = double(:webhook_notifier)
allow(WebhookNotifier).to receive(:new).and_return(notifier)
allow(notifier).to receive(:send_notification)

PullRequestReposter.run(prs_to_review)

expect(notifier).to have_received(:send_notification).twice
end

it "sets the timestamp for when the review was reposted" do
pr_to_review = create(:pull_request, reposted_at: nil)

PullRequestReposter.run([pr_to_review])

expect(pr_to_review.reload).to be_reposted
end
end
end
3 changes: 3 additions & 0 deletions spec/spec_helper.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
$LOAD_PATH.unshift(File.expand_path("../../app", __FILE__))

require "webmock/rspec"
require "active_support/testing/time_helpers"

# http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
RSpec.configure do |config|
Expand All @@ -13,6 +14,8 @@
end

config.order = :random

config.include ActiveSupport::Testing::TimeHelpers
end

WebMock.disable_net_connect!(allow_localhost: true)

0 comments on commit 3378e01

Please sign in to comment.