aboutsummaryrefslogtreecommitdiffstats
path: root/notification.rb
blob: 169fbf5702230d44e664bbe3a0e89e216c73ef0d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
require "net/smtp"
require "uri"
require "time"
require "net/http"
require "json"

class Notification
  def initialize(email: nil, slack: nil)
    @list = []
    @list << Email.new(email) if email
    @list << Slack.new(slack) if slack
  end

  def publish(*args)
    # FIXME
    @list.each { |t| t.publish(*args) }
  end

  class Email
    def initialize(smtp_server:, from:, to:)
      @smtp_server = URI.parse(smtp_server)
      @from = from
      @to = to
    end

    def finish(subject, body, id)
      Net::SMTP.start(@smtp_server.host, @smtp_server.port) { |smtp|
        smtp.send_message(<<~EOF, @from, @to)
          From: nyaci <#{@from}>
          To: #{@to}
          Date: #{Time.now.rfc2822}
          Subject: #{subject.delete("\r\n")}
          Message-Id: <nyaci-#{id}@#{@smtp_server.host}>

          #{body.gsub(/(?<!\r)\n/, "\r\n")}
        EOF
      }
    end

    def publish(project, jobid, results)
      prefix = "[NyaCI] [#{project}/#{jobid}]"

      results.sort_by! { |id, result| id }
      failed = results.count { |id, result| !result }
      if failed == 0
        subject = prefix + " success"
        body = <<~EOM
          All test cases passed successfully:

          #{results.map { |id, res| "- #{id}" }.join("\n")}

          #{NyaConfig.webroot + "/" + project + "/" + jobid}
        EOM
      else
        subject = prefix + " #{failed}/#{results.size} failed"
        body = <<~EOM
          The following test cases failed:

          #{results.select { |id, res| !res }
              .map { |id, res| "- #{id}" }.join("\n")}

          The rest cases passed:

          #{results.select { |id, res| res }
              .map { |id, res| "- #{id}" }.join("\n")}

          #{NyaConfig.webroot + "/" + project + "/" + jobid}
        EOM
      end

      finish(subject, body, jobid)
    end
  end

  class Slack
    def initialize(webhook:)
      @webhook = webhook
    end

    def publish(project, jobid, results)
      failed = results.count { |id, result| !result }

      link = NyaConfig.webroot + "/" + project + "/" + jobid
      result = failed == 0 ? "passed" : "failed"
      ary = ["nyaci build <#{link}|#{project}/#{jobid}> #{result}."]
      if failed != 0
        ary << "failed builds:"
        results.select { |id, r| !r }.map { |id, r| id }.sort.each { |i|
          link = NyaConfig.webroot + "/" + project + "/" + jobid + "/" + i
          ary << "- <#{link}|#{i}>"
        }
      end

      payload = JSON.generate(attachments: [{
        color: failed == 0 ? "good" : "danger",
        text: ary.join("\n"),
      }])

      uri = URI.parse(@webhook)
      http = Net::HTTP.new(uri.host, uri.port)
      http.use_ssl = uri.scheme == "https"
      body = http.start {
        res = http.post(uri.path, payload, "Content-Type" => "application/json")
        res.body
      }
      raise "failed to post to Slack: #{body}" if body != "ok"
    end
  end
end