Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 42 additions & 0 deletions spec/github/models_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,12 @@ describe Github::Subject do
it "still uses latest_comment_url even for non-body types" do
subject_from("Commit", url: "u", latest_comment_url: "c").comment_url.should eq "c"
end

# Release は subject.url を取得するとリリースノートが返る(issue #121)。
it "falls back to url for a release when latest_comment_url is blank" do
subject = subject_from("Release", url: "https://api.github.com/repos/o/r/releases/1")
subject.comment_url.should eq "https://api.github.com/repos/o/r/releases/1"
end
end

describe "#commented?" do
Expand Down Expand Up @@ -335,6 +341,42 @@ describe Github::Comment do
Github::Comment.new(nil).commented?.should be_false
end
end

# Release の応答は投稿者を author に入れる。user を必須にしていたころは解析ごと
# 失敗し、本文が「取得できませんでした」に倒れていた(issue #121)。
describe "#poster" do
it "parses a release payload and keeps its body" do
comment = Github::Comment.from_json(release_payload)

comment.body.should eq "リリースノート本文"
comment.poster.login.should eq "octocat"
end

it "prefers the comment user over the author" do
json = {user: {login: "commenter"}, author: {login: "releaser"}, body: "b"}.to_json
Github::Comment.from_json(json).poster.login.should eq "commenter"
end

it "falls back to an empty user when the payload has neither" do
Github::Comment.from_json({body: "b"}.to_json).poster.login.should be_nil
end

it "returns an empty user for a locally built comment" do
Github::Comment.new("b").poster.login.should be_nil
end
end
end

# GitHub の Release オブジェクト。投稿者は user ではなく author に入る。
private def release_payload
{
url: "https://api.github.com/repos/o/r/releases/1",
html_url: "https://github.com/o/r/releases/tag/v1.2.3",
author: {login: "octocat", avatar_url: "https://example.com/a.png"},
tag_name: "v1.2.3",
name: "v1.2.3",
body: "リリースノート本文",
}.to_json
end

private def notification_with(url = "", repo_html_url : String? = nil)
Expand Down
27 changes: 27 additions & 0 deletions spec/github/usecase_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,18 @@ private def subject_detail(comments : Int32? = nil, review_comments : Int32? = n
}.to_json)
end

# GitHub の Release オブジェクト。投稿者は user ではなく author に入る。
private def release_payload
{
url: "https://api.github.com/repos/octocat/Hello-World/releases/1",
html_url: "https://github.com/octocat/Hello-World/releases/tag/v1.2.3",
author: {login: "octocat", avatar_url: "https://example.com/a.png"},
tag_name: "v1.2.3",
name: "v1.2.3",
body: "リリースノート本文",
}.to_json
end

private def build(notify, comment)
Github::Usecase.new(StubRepo.new(comment)).build_message(notify)
end
Expand Down Expand Up @@ -107,6 +119,21 @@ describe Github::Usecase do
it "leaves text nil when there is no comment body" do
build(notification, comment(body: nil)).text.should be_nil
end

# Release は投稿者が author に入るため、user を必須にしていたころは応答の解析に
# 失敗し、本文が「取得できませんでした」になっていた(issue #121)。
it "keeps the release notes and author of a release notification" do
notify = notification(
url: "https://api.github.com/repos/octocat/Hello-World/releases/1",
reason: "subscribed",
type: Github::Subject::Type::RELEASE,
)
message = build(notify, Github::Comment.from_json(release_payload))

message.text.should eq "リリースノート本文"
message.author_name.should eq "octocat"
message.title_link.should eq "https://github.com/octocat/Hello-World/releases/tag/v1.2.3"
end
end

describe "#build_message mention" do
Expand Down
18 changes: 16 additions & 2 deletions src/github/models.cr
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,7 @@ module Github
ISSUE = "Issue"
COMMIT = "Commit"
DISCUSSION = "Discussion"
RELEASE = "Release"
end

UPDATE_TYPES = {
Expand All @@ -207,6 +208,10 @@ module Github
BODY_TYPES = {
Type::PULL_REQUEST,
Type::ISSUE,
# Release も subject.url を取得すると body(リリースノート)が返る。
# 通知に latest_comment_url が入らない場合でも本文を出せるようにする
# (issue #121)。
Type::RELEASE,
}

def update? : Bool
Expand Down Expand Up @@ -278,7 +283,11 @@ module Github
class Comment
include JSON::Serializable

getter user : User
# 投稿者。コメントや Issue / PR では user だが、Release では author に入る。
# 必須にすると Release の応答が丸ごと解析エラーになり、本文まで
# 「取得できませんでした」に倒れるため、どちらも nilable で受ける(issue #121)。
getter user : User?
getter author : User?
getter html_url : String?
getter body : String?
# スレッドのコメント数。subject 本体を取得したときだけ入り、コメント
Expand All @@ -288,7 +297,12 @@ module Github
getter review_comments : Int32?

def initialize(@body)
@user = User.new
end

# 表示に使う投稿者。どちらのキーも無い応答では空の User を返し、名前も
# アイコンも付けずに本文だけを出す。
def poster : User
user || author || User.new
end

# スレッドにコメントが 1 件以上付いているか(issue #116)。
Expand Down
6 changes: 3 additions & 3 deletions src/github/usecase.cr
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ module Github
# 投稿の区切りは reason だけで決め、CI によるメンション抑止は反映しない
# (issue #120。理由は Notify::Message#important? のコメント)。
important: notify.mention?,
author_name: comment.user.login,
author_icon: comment.user.avatar_url,
author_link: comment.user.html_url,
author_name: comment.poster.login,
author_icon: comment.poster.avatar_url,
author_link: comment.poster.html_url,
# コメントが無いスレッドでは comment は subject 本体(PR / Issue)になる。
# その中のコメント数を文言の切り替え判定に使う(issue #116)。
pretext: notify.pretext(comment),
Expand Down
Loading