Skip to content
Closed
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
31 changes: 31 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
name: ci

on:
push:
branches: [master]
pull_request:

jobs:
check:
name: format / lint / spec
runs-on: ubuntu-24.04-arm
steps:
- name: checkout
uses: actions/checkout@v4

- name: install crystal
uses: crystal-lang/install-crystal@v1
with:
crystal: latest

- name: install shards
run: shards install

- name: check format
run: crystal tool format --check

- name: lint with ameba
run: ./bin/ameba

- name: run specs
run: crystal spec
5 changes: 3 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ jspm_packages
.serverless

bootstrap
bin
lib
env.yml
.idea/

.idea/
6 changes: 0 additions & 6 deletions .travis.yml

This file was deleted.

8 changes: 4 additions & 4 deletions shard.lock
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
version: 1.0
version: 2.0
shards:
clim:
github: at-grandpa/clim
version: 0.4.1
ameba:
git: https://github.com/crystal-ameba/ameba.git
version: 1.6.4

7 changes: 6 additions & 1 deletion shard.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@ targets:
bootstrap:
main: src/main.cr

crystal: 1.11.2
crystal: ">= 1.20.0"

development_dependencies:
ameba:
github: crystal-ameba/ameba
version: ~> 1.6

license: MIT
113 changes: 113 additions & 0 deletions spec/github/models_spec.cr
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
require "../spec_helper"

private def subject_from(type : String, url = "", latest_comment_url = "")
Github::Subject.from_json({
type: type,
title: "title",
url: url,
latest_comment_url: latest_comment_url,
}.to_json)
end

describe Github::Subject do
describe "#update?" do
it "is true for tracked subject types" do
[
Github::Subject::Type::PULL_REQUEST,
Github::Subject::Type::ISSUE,
Github::Subject::Type::COMMIT,
Github::Subject::Type::DISCUSSION,
].each do |type|
subject_from(type).update?.should be_true
end
end

it "is false for unknown subject types" do
subject_from("Release").update?.should be_false
end
end

describe "#color" do
it "returns a distinct color per known type" do
subject_from(Github::Subject::Type::PULL_REQUEST).color.should eq "#F6CEE3"
subject_from(Github::Subject::Type::ISSUE).color.should eq "#A9D0F5"
subject_from(Github::Subject::Type::COMMIT).color.should eq "#f5d7a9"
subject_from(Github::Subject::Type::DISCUSSION).color.should eq "#7fffd4"
end

it "falls back to a default color for unknown types" do
subject_from("Release").color.should eq "#D8D8D8"
end
end

describe "#comment_url" do
it "prefers latest_comment_url when present" do
subject = subject_from("Issue", url: "u", latest_comment_url: "c")
subject.comment_url.should eq "c"
end

it "falls back to url when latest_comment_url is blank" do
subject = subject_from("Issue", url: "u", latest_comment_url: "")
subject.comment_url.should eq "u"
end
end
end

describe Github::Notification do
describe "#mention?" do
it "is true for reasons that mention the user" do
Github::Notification::MENTION_REASONS.each do |reason|
notification_from(reason).mention?.should be_true
end
end

it "is false for non-mention reasons" do
notification_from("subscribed").mention?.should be_false
notification_from("ci_activity").mention?.should be_false
end
end

it "parses a GitHub notifications API payload" do
notifications = Array(Github::Notification).from_json(NOTIFICATIONS_FIXTURE)
notifications.size.should eq 1

notification = notifications.first
notification.reason.should eq "mention"
notification.subject.type.should eq "Issue"
notification.subject.title.should eq "Spurious failure"
notification.repository.full_name.should eq "octocat/Hello-World"
notification.mention?.should be_true
end
end

private def notification_from(reason : String)
Github::Notification.from_json({
reason: reason,
subject: {type: "Issue", title: "title"},
repository: {owner: {login: "octocat"}},
}.to_json)
end

NOTIFICATIONS_FIXTURE = <<-JSON
[
{
"reason": "mention",
"subject": {
"title": "Spurious failure",
"url": "https://api.github.com/repos/octocat/Hello-World/issues/1",
"latest_comment_url": "https://api.github.com/repos/octocat/Hello-World/issues/comments/1",
"type": "Issue"
},
"repository": {
"full_name": "octocat/Hello-World",
"html_url": "https://github.com/octocat/Hello-World",
"owner": {
"login": "octocat",
"avatar_url": "https://github.com/images/error/octocat.gif",
"html_url": "https://github.com/octocat"
}
},
"subscription_url": "https://api.github.com/notifications/threads/1/subscription"
}
]
JSON
9 changes: 0 additions & 9 deletions spec/github_notifications_slack_spec.cr

This file was deleted.

22 changes: 22 additions & 0 deletions spec/slack/models_spec.cr
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
require "../spec_helper"

describe Slack::Attachment do
it "omits unset fields when serialized" do
json = Slack::Attachment.new(text: "hello", color: "#000000").to_json
parsed = JSON.parse(json)

parsed["text"].should eq "hello"
parsed["color"].should eq "#000000"
parsed.as_h.has_key?("title").should be_false
end
end

describe Slack::Post do
it "wraps attachments under an attachments key" do
post = Slack::Post.new([Slack::Attachment.new(text: "a")])
parsed = JSON.parse(post.to_json)

parsed["attachments"].as_a.size.should eq 1
parsed["attachments"][0]["text"].should eq "a"
end
end
3 changes: 2 additions & 1 deletion spec/spec_helper.cr
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
require "spec"
require "../src/github_notifications_slack"
require "../src/github/models"
require "../src/slack/models"
13 changes: 7 additions & 6 deletions src/error/usecase.cr
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,21 @@ require "../slack/repository"

module Error
class Usecase
def alert(err)
slack = Slack::PostRepository.new ENV["ALERT_WEBHOOK_URL"]
def initialize(@slack_repo : Slack::PostRepository, @slack_id : String, @env : String)
end

def alert(err)
message = "エラーみたい…確認してみよっか"
attachment = Slack::Attachment.new(
fallback: message,
pretext: "<@#{ENV["SLACK_ID"]}> #{message}",
pretext: "<@#{@slack_id}> #{message}",
color: "#EB4646",
title: err.message,
text: err.backtrace.join('\n'),
footer: "github_notifications_slack (#{ENV["ENV"]})",
text: err.backtrace?.try(&.join('\n')),
footer: "github_notifications_slack (#{@env})",
footer_icon: "",
)
slack.send_attachment attachment
@slack_repo.send_attachment attachment

{msg: "ng"}
end
Expand Down
86 changes: 41 additions & 45 deletions src/github/models.cr
Original file line number Diff line number Diff line change
@@ -1,39 +1,37 @@
require "json"

module Github
class Notifications
class Notification
include JSON::Serializable

property subject : Subject
property reason : String
property repository : Repository
property subscription_url : String?
MENTION_REASONS = [
"assign",
"author",
"comment",
"invitation",
"mention",
"team_mention",
"review_requested",
# "ci_activity",
]

getter subject : Subject
getter reason : String
getter repository : Repository
getter subscription_url : String?

def mention? : Bool
[
"assign",
"author",
"comment",
"invitation",
"mention",
"team_mention",
"review_requested",
# "ci_activity",
].includes?(reason)
reason.in?(MENTION_REASONS)
end
end

class Subject
include JSON::Serializable

property type : String
property title : String?

@[JSON::Field(emit_null: false)]
property url : String = ""

@[JSON::Field(emit_null: false)]
property latest_comment_url : String = ""
getter type : String
getter title : String?
getter url : String = ""
getter latest_comment_url : String = ""

module Type
PULL_REQUEST = "PullRequest"
Expand All @@ -42,13 +40,15 @@ module Github
DISCUSSION = "Discussion"
end

UPDATE_TYPES = [
Type::PULL_REQUEST,
Type::ISSUE,
Type::COMMIT,
Type::DISCUSSION,
]

def update? : Bool
[
Type::PULL_REQUEST,
Type::ISSUE,
Type::COMMIT,
Type::DISCUSSION,
].includes?(type)
type.in?(UPDATE_TYPES)
end

def color : String
Expand All @@ -67,28 +67,24 @@ module Github
end

def comment_url : String
if !latest_comment_url.blank?
latest_comment_url
else
url
end
latest_comment_url.presence || url
end
end

class Repository
include JSON::Serializable

property full_name : String?
property html_url : String?
property owner : User
getter full_name : String?
getter html_url : String?
getter owner : User
end

class Comment
include JSON::Serializable

property user : User
property html_url : String?
property body : String?
getter user : User
getter html_url : String?
getter body : String?

def initialize(@body)
@user = User.new
Expand All @@ -98,9 +94,9 @@ module Github
class User
include JSON::Serializable

property login : String?
property avatar_url : String?
property html_url : String?
getter login : String?
getter avatar_url : String?
getter html_url : String?

def initialize
end
Expand All @@ -109,7 +105,7 @@ module Github
class Error
include JSON::Serializable

property message : String
property documentation_url : String?
getter message : String
getter documentation_url : String?
end
end
Loading
Loading