/images/avatar.png

Patrick Wezhi Xu

Notify Me on Slack when the GitHub Pull Request Merged

Tired of refreshing the GitHub web pages and waiting for the PR from colleagues to be merged. Try to dump these things out of my head to concentrate on real work.

Steps

There are only three steps and step 2 is optional.

  1. Creating a Slack App via https://api.slack.com/messaging/webhooks. What you want is the Webhook URLs under Incoming Webhooks which starts with https://hooks.slack.com/services/, so that you can send the notification message to it.
  2. Aware of the Rate Limit of GitHub API and create a personal access token or creating GitHub Apps depending on your needs.
  3. With help of ChatGPT and a few fixes, we derived at this script
 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
import requests
import argparse
import time
import re

# Could be none or personal access token https://docs.github.com/en/rest/using-the-rest-api/rate-limits-for-the-rest-api
GITHUB_TOKEN="<your_github_token>"
# On how to get webhooks token https://api.slack.com/messaging/webhooks
SLACK_WEBHOOK="https://hooks.slack.com/services/XXXXXXXXXXX/YYYYYYYYYY/ZZZZZZZZZZZZZZ"
WAIT_DURATION_SEC=600

def parse_args():
    parser = argparse.ArgumentParser(description='Check if a GitHub pull request was merged and send a Slack message.')
    parser.add_argument('pr_url', help='GitHub pull request URL.')
    return parser.parse_args()

def parse_pr_url(pr_url):
    """
    Parses the PR URL and returns the owner, repository, and PR number.

    Example URL: https://github.com/owner/repo/pull/123
    """
    pattern = r'https?://github\.com/(?P<owner>[^/]+)/(?P<repo>[^/]+)/pull/(?P<pr_number>\d+)'
    match = re.match(pattern, pr_url)
    if match:
        return match.group('owner'), match.group('repo'), int(match.group('pr_number'))
    else:
        raise ValueError('Invalid GitHub pull request URL.')

def check_if_pr_merged(owner, repo, pr_number, github_token=None):
    url = f'https://api.github.com/repos/{owner}/{repo}/pulls/{pr_number}'
    headers = {'Accept': 'application/vnd.github.v3+json'}
    if github_token:
        headers['Authorization'] = f'token {github_token}'
    response = requests.get(url, headers=headers)
    if response.status_code == 200:
        pr_data = response.json()
        return pr_data.get('merged', False)
    else:
        print(f'Error fetching PR data: {url} {response.status_code} {response.reason}')
        return False

def send_slack_message(slack_webhook_url, message):
    payload = {'text': message}
    response = requests.post(slack_webhook_url, json=payload)
    if response.status_code != 200:
        print(f'Error sending Slack message: {slack_webhook_url} {response.status_code} {response.reason}')

def main():
    args = parse_args()
    try:
        owner, repo, pr_number = parse_pr_url(args.pr_url)
    except ValueError as e:
        print(e)
        return

    print(f"Monitoring PR #{pr_number} in repository '{owner}/{repo}' for merge status.")

    while True:
        is_merged = check_if_pr_merged(owner, repo, pr_number, GITHUB_TOKEN)

        if is_merged:
            message = f'Pull request {args.pr_url} has been merged.'
            send_slack_message(SLACK_WEBHOOK, message)
            break
        else:
            time.sleep(WAIT_DURATION_SEC)

if __name__ == '__main__':
    main()

After aliasing, you could do ntfslk https://github.com/owner/repo/pull/123 & to put it in the background. When the script scans and finds out the PR is merged, a notification will pop up in the channel.

LeetCode Weekly Contest 156 and others

Second week of LeetCode Challenge. Participated the virtual contest.

Weekly Contest 156

1207. Unique Number of Occurrences

https://leetcode.com/contest/weekly-contest-156/problems/unique-number-of-occurrences/

Brute force. Record total occurrence of each number and iterate over it to see if there is any duplication.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
class Solution {
public:
    bool uniqueOccurrences(vector<int>& arr) {
        unordered_map<int, int> occ;
        unordered_map<int, bool> flag;
        
        for (int i = 0; i < arr.size(); ++i) {
            occ[arr[i]]++;
        }
        
        for (const auto x : occ) {
            if (flag.find(x.second) != flag.end()) {
                if (flag[x.second]) return false;
            } else {
                flag[x.second] = true;
            }
        }
        
        return true;
    }
};

1208. Get Equal Substrings Within Budget

https://leetcode.com/contest/weekly-contest-156/problems/get-equal-substrings-within-budget/

LeetCode Weekly Contest 155 and others

This is the first week of LeetCode Challenges. It includes weekly contest 155 and other problems.

Weekly Contest 155

https://leetcode.com/contest/weekly-contest-155

1200. Minimum Absolute Difference

https://leetcode.com/contest/weekly-contest-155/problems/minimum-absolute-difference/

Brute force. Find the minimum absolute difference and then iterate the list again to output the pairs with minimum absolute difference.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class Solution {
public:
    vector<vector<int>> minimumAbsDifference(vector<int>& arr) {
        vector<vector<int>> ans;
        if (arr.size() == 1) return ans;
        sort(arr.begin(), arr.end());
        
        int mini = 0x3f3f3f3f;
        for (int i = 1; i < arr.size(); ++i) {
            mini = min(mini, abs(arr[i] - arr[i-1]));
        }
        
        for (int i = 1; i < arr.size(); ++i) {
            if (abs(arr[i]- arr[i-1]) == mini) {
                if (arr[i] < arr[i-1]) {
                    ans.push_back({arr[i], arr[i-1]});
                } else {
                    ans.push_back({arr[i-1], arr[i]});
                }
            }
        }
        return ans;
    }
};

1201. Ugly Number III

https://leetcode.com/contest/weekly-contest-155/problems/ugly-number-iii/

CLDictP: A Command-Line Dictionary Tool

A command line dictionary written in Perl using Merriam-Webster APIs.

This is my first project using Perl. I feel it is tedious to type formatted definitions to Quizlet(A website which can make flashcards for you) and I’m too lazy to open browser and online dictionary pages. Why not combining these two?

It uses following APIs:

  • Merriam-Webster Learner

  • Merriam-Webster Collegiate

For each entry, it contains:

  • Pronunciation: IPA(International Phonetic Alphabet)

  • Part of Speech

Static Linked List - Another Way To Represent Graphs

Static Linked List is a data structure that stores linked list in static arrays. It is usually used to represent graphs. It is very interesting that its Chinese name literally translated as “Linked Forward Star”. You have two choices of paths to understand this.

However, I would recommend to explore both ideas to have a better understanding. If you know some of it or you just don’t care, you can jump to here straight away.