summaryrefslogtreecommitdiff
path: root/Meta/notify_irc.py
blob: c8e0eaeed6d9b2e841e85c7902c406a5bce59906 (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
110
111
112
113
114
115
116
117
#!/usr/bin/env python3

import json
import sys
import requests

# Must be exactly three lines each!
# No trailing newline! (I.e. keep it as backslash-newline-tripleapostrophe.)
TEMPLATE_PUSH = '''\
{commit}{post_commit} (pushed master: {status}) {compare} https://github.com/SerenityOS/serenity/actions/runs/{run_id}\
'''
TEMPLATE_PR = '''\
{title} ({actor} {action}: {status}) {link} https://github.com/SerenityOS/serenity/actions/runs/{run_id}\
'''
SERENITY_BOT = 'http://94.130.182.143:8080'


def compute_lines(wrapper):
    actor, run_id, raw_status, event = wrapper

    if raw_status == 'success':
        status = 'The build passed.'
    elif raw_status == 'failure':
        status = 'The build failed.'
    else:
        status = 'The build {}(?)'.format(raw_status)

    if 'action' not in event:
        # This is a push.
        if 'commits' not in event or not event['commits']:
            show_msg = '??? (No commits in event?!)'
            post_commit = ''
        else:
            commits = event['commits']
            show_commit = commits[-1]['message']
            if 'skip ci' in show_commit or 'ci skip' in show_commit:
                print('User requested to skip IRC notification. Okay!')
                return False
            # First line of the last commit:
            show_msg = show_commit.split('\n')[0]
            if len(commits) == 1:
                post_commit = ''
            elif len(commits) == 2:
                post_commit = ' (+1 commit)'
            else:
                post_commit = ' (+{} commits)'.format(len(commits))
        return TEMPLATE_PUSH.format(
            actor=actor,
            status=status,
            run_id=run_id,
            commit=show_msg,
            post_commit=post_commit,
            compare=event.get('compare', '???'),
        )
    elif 'pull_request' in event:
        # This is a PR.
        raw_action = event['action']
        pull_request = event['pull_request']
        # actor, until here, is whoever caused the action to run -
        # if it's a PR we want the author's name in the notification.
        actor = pull_request['user']['login']
        if raw_action == 'opened':
            action = 'opened'
        elif raw_action == 'reopened':
            # Reduce spam, don't notify about reopened PRs
            return False
        elif raw_action == 'synchronize':
            # Reduce spam, don't notify about PR updates
            return False
        else:
            action = '{}(?)'.format(raw_action)
        if pull_request.get('draft', True):
            print("This is a draft PR, so IRC won't be notified.")
            print('Note: No rebuild occurs when the PR is "un-drafted"!')
            return False
        return TEMPLATE_PR.format(
            actor=actor,
            action=action,
            status=status,
            run_id=run_id,
            title=pull_request.get('title', '???'),
            link=pull_request.get('_links', {}).get('html', {}).get('href', '???'),
        )
    else:
        print('Unrecognized event type?!')
        return False


def send_notification(line):
    """Send a message to IRC channel via HTTP bridge.

    Ars:
        line (str): message to send
    """

    print('> ' + line)
    try:
        response = requests.post(SERENITY_BOT, data={'msg': line})
    except BaseException as e:
        print('Notification failed: {}: {}'.format(type(e), e))
    else:
        print('Notification result: HTTP {}'.format(response.status_code))


def run_on(json_string):
    wrapper = json.loads(json_string)
    line = compute_lines(wrapper)
    if line:
        send_notification(line)


def run():
    run_on(sys.stdin.read())


if __name__ == '__main__':
    run()