Skip to content

Commit

Permalink
Merge pull request #50 from unsplash/specs
Browse files Browse the repository at this point in the history
Refactor and add specs
  • Loading branch information
aaronklaassen authored Jan 5, 2022
2 parents 481c213 + 1dc131a commit 8f2c7d6
Show file tree
Hide file tree
Showing 11 changed files with 413 additions and 63 deletions.
4 changes: 4 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
source "https://rubygems.org"

gem "octokit"
gem "rspec", group: :test
57 changes: 57 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
GEM
remote: https://rubygems.org/
specs:
addressable (2.8.0)
public_suffix (>= 2.0.2, < 5.0)
diff-lcs (1.5.0)
faraday (1.8.0)
faraday-em_http (~> 1.0)
faraday-em_synchrony (~> 1.0)
faraday-excon (~> 1.1)
faraday-httpclient (~> 1.0.1)
faraday-net_http (~> 1.0)
faraday-net_http_persistent (~> 1.1)
faraday-patron (~> 1.0)
faraday-rack (~> 1.0)
multipart-post (>= 1.2, < 3)
ruby2_keywords (>= 0.0.4)
faraday-em_http (1.0.0)
faraday-em_synchrony (1.0.0)
faraday-excon (1.1.0)
faraday-httpclient (1.0.1)
faraday-net_http (1.0.1)
faraday-net_http_persistent (1.2.0)
faraday-patron (1.0.0)
faraday-rack (1.0.0)
multipart-post (2.1.1)
octokit (4.21.0)
faraday (>= 0.9)
sawyer (~> 0.8.0, >= 0.5.3)
public_suffix (4.0.6)
rspec (3.10.0)
rspec-core (~> 3.10.0)
rspec-expectations (~> 3.10.0)
rspec-mocks (~> 3.10.0)
rspec-core (3.10.1)
rspec-support (~> 3.10.0)
rspec-expectations (3.10.1)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.10.0)
rspec-mocks (3.10.2)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.10.0)
rspec-support (3.10.3)
ruby2_keywords (0.0.5)
sawyer (0.8.2)
addressable (>= 2.3.5)
faraday (> 0.8, < 2.0)

PLATFORMS
arm64-darwin-21

DEPENDENCIES
octokit
rspec

BUNDLED WITH
2.2.14
67 changes: 4 additions & 63 deletions entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,67 +2,8 @@

require "json"
require "octokit"
require_relative "lib/github"
require_relative "lib/commenter"
require_relative "lib/action"

json = File.read(ENV.fetch("GITHUB_EVENT_PATH"))
event = JSON.parse(json)

if !ENV["GITHUB_TOKEN"]
puts "Missing GITHUB_TOKEN"
exit(1)
end

github = Octokit::Client.new(access_token: ENV["GITHUB_TOKEN"])

if ARGV[0].empty?
puts "Missing message argument."
exit(1)
end

message = ARGV[0]
check_duplicate_msg = ARGV[1]
delete_prev_regex_msg = ARGV[2]
duplicate_msg_pattern = ARGV[3]

repo = event["repository"]["full_name"]

if ENV.fetch("GITHUB_EVENT_NAME") == "pull_request"
pr_number = event["number"]
else
pulls = github.pull_requests(repo, state: "open")

push_head = event["after"]
pr = pulls.find { |pr| pr["head"]["sha"] == push_head }

if !pr
puts "Couldn't find an open pull request for branch with head at #{push_head}."
exit(1)
end
pr_number = pr["number"]
end

if !duplicate_msg_pattern.empty? || !delete_prev_regex_msg.empty?
comments = github.issue_comments(repo, pr_number)

if check_duplicate_msg == "true"
duplicate = if !duplicate_msg_pattern.empty?
comments.find { |c| c["body"].match(/#{duplicate_msg_pattern}/) }
else
comments.find { |c| c["body"] == message }
end

if duplicate
puts "The PR already contains this message"
exit(0)
end
end

if !delete_prev_regex_msg.empty?
comments.each do |comment|
if comment["body"].match(/#{delete_prev_regex_msg}/)
github.delete_comment(repo, comment["id"])
end
end
end
end

github.add_comment(repo, pr_number, message)
exit(run)
26 changes: 26 additions & 0 deletions lib/action.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
def run
if !ENV["GITHUB_TOKEN"]
puts "Missing GITHUB_TOKEN"
return 1
end

if ARGV[0].nil? || ARGV[0].empty?
puts "Missing message argument."
return 1
end

commenter = Commenter.new(github: GitHub.new(env: ENV),
message: ARGV[0],
check_for_duplicates: ARGV[1],
duplicate_pattern: ARGV[2],
delete_previous_pattern: ARGV[3])

if commenter.block_duplicates? && commenter.existing_duplicates?
puts "The PR already contains this message"
return 0
end

commenter.delete_matching_comments!
commenter.comment!
return 0
end
35 changes: 35 additions & 0 deletions lib/commenter.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
class Commenter
def initialize(github:, message:, check_for_duplicates: true, duplicate_pattern: nil, delete_previous_pattern: nil)
@github = github
@message = message
@block_duplicates = check_for_duplicates.to_s.downcase.strip == "true"
@duplicate_pattern = !duplicate_pattern.to_s.empty? && Regexp.new(duplicate_pattern)
@delete_previous_pattern = !delete_previous_pattern.to_s.empty? && Regexp.new(delete_previous_pattern)
end

def block_duplicates?
@block_duplicates
end

def existing_duplicates?
if @duplicate_pattern
@github.comments.any? { |c| c["body"].match(/#{@duplicate_pattern}/) }
else
@github.comments.any? { |c| c["body"] == @message }
end
end

def delete_matching_comments!
return if !@delete_previous_pattern

@github.comments.each do |comment|
if comment["body"].match(/#{@delete_previous_pattern}/)
@github.delete_comment(@github.repo, comment["id"])
end
end
end

def comment!
@github.comment!(@message)
end
end
53 changes: 53 additions & 0 deletions lib/github.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
class GitHub
class MissingPR < StandardError; end

attr_reader :client

def initialize(env:)
@env = env
@client = Octokit::Client.new(access_token: env["GITHUB_TOKEN"])
end

def event
@_event ||= JSON.parse(File.read(@env.fetch("GITHUB_EVENT_PATH")))
end

def repo
@_repo ||= event["repository"]["full_name"]
end

def pr_number
@_pr ||= begin

if @env.fetch("GITHUB_EVENT_NAME") == "pull_request"
pr_number = event["number"]
else
pulls = client.pull_requests(repo, state: "open")

push_head = event["after"]
pr = pulls.find { |pr| pr["head"]["sha"] == push_head }

if !pr
raise MissingPR, "Couldn't find an open pull request for branch with head at #{push_head}"
end

pr["number"]
end

end
end

def comments
@_comments ||= client.issue_comments(repo, pr_number)
rescue MissingPR => e
puts e.message
exit(1)
end

def comment!(msg)
client.add_comment(repo, pr_number, message)
rescue MissingPR => e
puts e.message
exit(1)
end
end
76 changes: 76 additions & 0 deletions spec/action_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
require "spec_helper"

RSpec.describe "action.rb" do

let(:base_env) do
{
"GITHUB_TOKEN" => "secret",
"GITHUB_EVENT_PATH" => File.join(__dir__, "event.json")
}
end

before :each do
stub_const("ARGV", ["hello"])
end

describe "required arguments" do
it "fails without GITHUB_TOKEN" do
expect { run }.to output(/Missing GITHUB_TOKEN/).to_stdout
expect(run).to eq 1
end

it "fails without message" do
stub_const("ENV", base_env)
stub_const("ARGV", [])
expect { run }.to output(/Missing message argument/).to_stdout
expect(run).to eq 1
end
end

describe "blocking duplicate comments" do

before :each do
stub_const("ENV", base_env)
end

context "we are blocking duplicates" do
before :each do
allow_any_instance_of(Commenter).to receive(:block_duplicates?).and_return(true)
end

it "exits when there is already a matching comment" do
allow_any_instance_of(Commenter).to receive(:existing_duplicates?).and_return(true)
expect { run }.to output(/The PR already contains this message/).to_stdout
expect(run).to eq 0
end

it "comments when no match" do
allow_any_instance_of(Commenter).to receive(:existing_duplicates?).and_return(false)
allow_any_instance_of(Commenter).to receive(:comment!)
expect { run }.to_not output.to_stdout
expect(run).to eq 0
end
end

context "not blocking duplicates" do
before :each do
allow_any_instance_of(Commenter).to receive(:block_duplicates?).and_return(false)
end

it "comments even with match" do
allow_any_instance_of(Commenter).to receive(:existing_duplicates?).and_return(true)
allow_any_instance_of(Commenter).to receive(:comment!)
expect { run }.to_not output.to_stdout
expect(run).to eq 0
end

it "comments when no match" do
allow_any_instance_of(Commenter).to receive(:existing_duplicates?).and_return(false)
allow_any_instance_of(Commenter).to receive(:comment!)
expect { run }.to_not output.to_stdout
expect(run).to eq 0
end
end

end
end
Loading

0 comments on commit 8f2c7d6

Please sign in to comment.