Skip to content
This repository has been archived by the owner on Mar 29, 2022. It is now read-only.

Commit

Permalink
Move maturity timing to PR (#449)
Browse files Browse the repository at this point in the history
  • Loading branch information
MattIPv4 committed Aug 19, 2020
2 parents 94c67f1 + 041137d commit ba2641d
Show file tree
Hide file tree
Showing 82 changed files with 1,127 additions and 6,324 deletions.
4 changes: 4 additions & 0 deletions app/models/github_pull_request.rb
Expand Up @@ -31,6 +31,10 @@ def created_at
@graphql_hash.createdAt
end

def merged?
@graphql_hash.merged
end

def label_names
@graphql_hash.labels.edges.map do |e|
e.node.name.downcase
Expand Down
89 changes: 74 additions & 15 deletions app/models/pull_request.rb
@@ -1,30 +1,89 @@
# frozen_string_literal: true

class PullRequest
class PullRequest < ApplicationRecord
attr_reader :github_pull_request

def initialize(github_pull_request)
@github_pull_request = github_pull_request
end
delegate :title, :body, :url, :created_at, :name, :owner, :repo_id,
:name_with_owner, :label_names, :merged?, to: :github_pull_request

state_machine initial: :new do
event :spam_repo do
transition %i[new waiting] => :spam_repo,
if: ->(pr) { pr.spammy? }
end

event :invalid_label do
transition %i[new waiting] => :invalid_label,
if: ->(pr) { pr.labelled_invalid? }
end

event :eligible do
transition %i[new waiting] => :eligible,
if: ->(pr) { !pr.spammy_or_invalid? && pr.older_than_week? }
end

delegate :id, :title, :body, :url, :created_at, :name, :owner, :repo_id,
:name_with_owner, :label_names, to: :github_pull_request
event :waiting do
transition %i[new spam_repo invalid_label] => :waiting,
if: ->(pr) { !pr.spammy_or_invalid? && !pr.older_than_week? }
end

before_transition to: %i[waiting],
from: %i[new] do |pr, _transition|
pr.waiting_since = pr.created_at
pr.save!
end

def state
if spammy?
'spammy'
elsif label_names.include?('invalid')
'invalid'
else
'eligible'
before_transition to: %i[waiting],
from: %i[spam_repo invalid_label] do |pr, _transition|
pr.waiting_since = Time.zone.now
pr.save!
end
end

def eligible?
state == 'eligible'
def check_state
return if spam_repo
return if invalid_label
return if eligible

waiting
end

def most_recent_time
return waiting_since unless waiting_since.nil?

github_pull_request.created_at
end

def older_than_week?
most_recent_time <= (Time.zone.now - 7.days)
end

def labelled_invalid?
return false if merged?

label_names.select { |l| l[/\binvalid\b/i] }.any?
end

def spammy?
SpamRepositoryService.call(repo_id)
end

def spammy_or_invalid?
labelled_invalid? || spammy?
end

def github_id
github_pull_request.id
end

def define_github_pull_request(ghpr)
@github_pull_request = ghpr
end

def self.from_github_pull_request(ghpr)
pr = find_or_create_by(gh_id: ghpr.id)
pr.define_github_pull_request(ghpr)
pr.check_state
pr
end
end
79 changes: 45 additions & 34 deletions app/models/user.rb
Expand Up @@ -14,11 +14,18 @@ class User < ApplicationRecord
end

event :wait do
transition registered: :waiting
transition registered: :waiting,
if: ->(user) { user.sufficient_waiting_or_eligible_prs? }
end

event :complete do
transition waiting: :completed
transition waiting: :completed,
if: ->(user) { user.sufficient_eligible_prs? }
end

event :insufficient do
transition waiting: :registered,
unless: ->(user) { user.sufficient_waiting_or_eligible_prs? }
end

event :won do
Expand All @@ -27,7 +34,8 @@ class User < ApplicationRecord
end

event :incomplete do
transition registered: :incompleted
transition registered: :incompleted,
unless: ->(user) { user.any_waiting_or_is_eligible? }
end

event :gifted do
Expand All @@ -39,11 +47,6 @@ class User < ApplicationRecord
transition incompleted: :completed
end

event :ineligible do
transition waiting: :registered,
unless: ->(user) { user.sufficient_eligible_prs? }
end

state all - [:new] do
validates :terms_acceptance, acceptance: true
validates :email, presence: true
Expand All @@ -66,13 +69,15 @@ class User < ApplicationRecord
end

state :waiting do
validates :sufficient_eligible_prs?, inclusion: {
in: [true], message: 'user does not have sufficient eligible prs' }
validates :sufficient_waiting_or_eligible_prs?, inclusion: {
in: [true],
message: 'user does not have sufficient waiting or eligible prs' }
end

state :completed do
validates :won_hacktoberfest?, inclusion: {
in: [true], message: 'user has not met all winning conditions' }
validates :sufficient_eligible_prs?, inclusion: {
in: [true],
message: 'user does not have sufficient eligible prs' }

def win
assign_coupon
Expand All @@ -91,6 +96,8 @@ def win
state :incompleted do
validates :hacktoberfest_ended?, inclusion: {
in: [true], message: 'hacktoberfest has not yet ended' }
validates :any_waiting_prs?, inclusion: {
in: [false], message: 'user has waiting prs' }
validates :sufficient_eligible_prs?, inclusion: {
in: [false], message: 'user has too many sufficient eligible prs' }

Expand All @@ -113,10 +120,14 @@ def gift
end

before_transition to: %i[completed incompleted] do |user, _transition|
user.receipt = user.scoring_pull_requests
user.receipt = user.scoring_pull_requests_receipt
end

after_transition to: :waiting, do: :update_waiting_since
after_transition to: :waiting do |user, _transition|
# Some users might be able to go direct to winning
# if their PRs are already all a week old
user.complete
end

after_transition to: :completed do |user, _transition|
user.win
Expand All @@ -128,44 +139,44 @@ def pull_requests
pull_request_service.all
end

def score
score = eligible_pull_requests_count
score > 4 ? 4 : score
def waiting_pull_requests_count
pull_request_service.waiting_prs.count
end

def eligible_pull_requests_count
pull_request_service.eligible_prs.count
end

delegate :scoring_pull_requests, :non_scoring_pull_requests,
to: :pull_request_service
def waiting_or_eligible_pull_requests_count
waiting_pull_requests_count + eligible_pull_requests_count
end

def sufficient_waiting_or_eligible_prs?
waiting_or_eligible_pull_requests_count >= 4
end

def sufficient_eligible_prs?
eligible_pull_requests_count >= 4
end

def won_hacktoberfest?
sufficient_eligible_prs? && waiting_for_week?
def any_waiting_prs?
waiting_pull_requests_count.positive?
end

def hacktoberfest_ended?
Hacktoberfest.end_date.past?
def any_waiting_or_is_eligible?
any_waiting_prs? || sufficient_eligible_prs?
end

def update_waiting_since
latest_pr = scoring_pull_requests.max_by do |pr|
pr.github_pull_request.created_at
end

update(waiting_since: Time.zone.parse(
latest_pr.github_pull_request.created_at
))
def score
score = waiting_or_eligible_pull_requests_count
score > 4 ? 4 : score
end

def waiting_for_week?
return false if waiting_since.nil?
delegate :scoring_pull_requests, :non_scoring_pull_requests,
:scoring_pull_requests_receipt, to: :pull_request_service

waiting_since <= (Time.zone.now - 7.days)
def hacktoberfest_ended?
Hacktoberfest.end_date.past?
end

def completed_or_won?
Expand Down
9 changes: 3 additions & 6 deletions app/presenters/profile_page_presenter.rb
Expand Up @@ -37,8 +37,9 @@ def scoring_pull_requests

def persisted_winning_pull_requests
@user.receipt.map do |pr|
github_hash = Hashie::Mash.new(pr).github_pull_request.graphql_hash
PullRequest.new(GithubPullRequest.new(github_hash))
PullRequest.from_github_pull_request(
GithubPullRequest.new(Hashie::Mash.new(pr))
)
end
end

Expand All @@ -62,10 +63,6 @@ def name
@user.name
end

def waiting_since_for_js
@user.waiting_since&.httpdate
end

def show_timer?
@user.waiting?
end
Expand Down
2 changes: 1 addition & 1 deletion app/services/backfill_receipt_service.rb
Expand Up @@ -4,6 +4,6 @@ module BackfillReceiptService
module_function

def call(user)
user.update(receipt: user.scoring_pull_requests)
user.update(receipt: user.scoring_pull_requests_receipt)
end
end
4 changes: 2 additions & 2 deletions app/services/gift_service.rb
Expand Up @@ -10,10 +10,10 @@ def call
group.each do |u|
last_pr = u.receipt.max_by do |pr_obj|
Time.zone.parse(
pr_obj['github_pull_request']['graphql_hash']['createdAt']
pr_obj['createdAt']
)
end
date = last_pr['github_pull_request']['graphql_hash']['createdAt']
date = last_pr['createdAt']
score = u.receipt.count
user_dates << { id: u.id, score: score, date: date }
end
Expand Down
12 changes: 11 additions & 1 deletion app/services/pull_request_service.rb
Expand Up @@ -14,10 +14,14 @@ def all
# in order to lookup all Repo Spammy states in SQL query
# prs = PullRequestStateLookupService.new(filtered_github_pull_requests)
filtered_github_pull_requests(github_pull_requests).map do |ghpr|
PullRequest.new(ghpr)
PullRequest.from_github_pull_request(ghpr)
end
end

def waiting_prs
all.select(&:waiting?)
end

def eligible_prs
all.select(&:eligible?)
end
Expand All @@ -30,6 +34,12 @@ def scoring_pull_requests
end
end

def scoring_pull_requests_receipt
scoring_pull_requests.map do |pr|
pr.github_pull_request.graphql_hash
end
end

def non_scoring_pull_requests
all.drop(scoring_pull_requests.count)
end
Expand Down
2 changes: 1 addition & 1 deletion app/services/try_user_transition_from_waiting_service.rb
Expand Up @@ -6,6 +6,6 @@ def self.call(user)

return if user.complete

user.ineligible
user.insufficient
end
end
8 changes: 4 additions & 4 deletions app/services/user_state_transition_segment_service.rb
Expand Up @@ -13,7 +13,7 @@ def call(user, transition)
when :complete then complete(user)
when :retry_complete then complete(user)
when :incomplete then incomplete(user)
when :ineligible then ineligible(user)
when :insufficient then insufficient(user)
when :won then won(user, transition)
when :gifted then gifted(user)
end
Expand Down Expand Up @@ -43,9 +43,9 @@ def incomplete(user)
segment(user).identify(state: 'incomplete')
end

def ineligible(user)
segment(user).track('user_ineligible')
segment(user).identify(state: 'ineligible')
def insufficient(user)
segment(user).track('user_insufficient')
segment(user).identify(state: 'insufficient')
end

def won(user, transition)
Expand Down

0 comments on commit ba2641d

Please sign in to comment.