Skip to content

Commit

Permalink
feat: migrate Purrr to Python (part 1)
Browse files Browse the repository at this point in the history
  • Loading branch information
daabr committed Dec 23, 2024
1 parent 643ba58 commit d17f8cc
Show file tree
Hide file tree
Showing 11 changed files with 1,088 additions and 0 deletions.
58 changes: 58 additions & 0 deletions purrr/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
---
title: Pull Request Review Reminder (Purrr)
description: Streamline code reviews and cut down turnaround time to merge pull requests
integrations: ["GitHub", "Google Sheets", "Slack"]
categories: ["DevOps"]
---

# Pull Request Review Reminder (Purrr)

Purrr integrates GitHub and Slack seamlessly, to streamline code reviews and
cut down the turnaround time to merge pull requests.

- Real-time, relevant, informative, 2-way updates
- Easier collaboration and faster execution
- Free and open-source

No more:

- Delays due to missed requests, comments, and state changes
- Notification fatigue due to updates that don't concern you
- Qestions like "Who's turn is it" or "What should I do now"

Check warning on line 21 in purrr/README.md

View workflow job for this annotation

GitHub Actions / Spell check with Typos

"Qestions" should be "Questions".

All that and more is implemented with a few hundred lines of Python.
AutoKitteh takes care of all the system infrastructure and reliability needs.

## Slack Usage

Event-based, 2-way synchronization:

- Slack channels are created and archived automatically for each PR
- Stakeholders are added and removed automatically in Slack and GitHub
- Reviews, comments, conversation threads, and emoji reactions are updated in
both directions

User matching between GitHub and Slack is based on email addresses and
case-insensitive full names.

Available Slack slash commands:

- `/purrr help`
- `/purrr opt-in`
- `/purrr opt-out`
- `/purrr list`
- `/purrr status [PR]`
- `/purrr approve [PR]`

## Data Storage

Purrr uses a simple Google Sheet for:

1. Mapping between GitHub PRs and Slack channels
2. Mapping between GitHub comments/reviews and Slack message threads
3. Caching user IDs (optimization to reduce API calls)
4. User opt-out database

Use-cases 1 and 2 use a TTL of 30 days (configurable in the `autokitteh.yaml`
manifest file). Use-case 3 uses a TTL of one day since the last cache hit.
Use-case 4 is permanent (until the user opts back in).
69 changes: 69 additions & 0 deletions purrr/autokitteh.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# This YAML file is a declarative manifest that describes the setup
# of the AutoKitteh project "Pull Request Review Reminder" (Purrr).
# Purrr integrates GitHub and Slack seamlessly, to streamline code
# reviews and cut down the turnaround time to merge pull requests.

version: v1

project:
name: purrr

vars:
# Temporary (easy to debug, but not scalable) replacement for Redis/Valkey.
- name: DATA_SHEET_URL
value: TODO
# PR channel names in Slack: "<prefix>_<number>_<title>".
- name: SLACK_CHANNEL_PREFIX
value: _pr
# Visibility of PR channels in Slack: "public" (default) or "private".
- name: SLACK_CHANNEL_VISIBILITY
value: public
# Create this channel / replace with your own / set to "" to disable it.
- name: SLACK_DEBUG_CHANNEL
value: purrr-debug
# TTL for GitHub/Slack mappings = 30 days (to forget stale PRs).
- name: STATE_TTL
value: 720h

connections:
- name: github_conn
integration: github
- name: sheets_conn
integration: googlesheets
- name: slack_conn
integration: slack

triggers:
# - name: github_issue_comment
# connection: github_conn
# event_type: issue_comment
# call: github_issue_comment.py:on_github_issue_comment
- name: github_pull_request
connection: github_conn
event_type: pull_request
call: github_pr.py:on_github_pull_request
# - name: github_pull_request_review
# connection: github_conn
# event_type: pull_request_review
# call: github_pr_review.py:on_github_pull_request_review
# - name: github_pull_request_review_comment
# connection: github_conn
# event_type: pull_request_review_comment
# call: github_review_comment.py:on_github_pull_request_review_comment
# - name: github_pull_request_review_thread
# connection: github_conn
# event_type: pull_request_review_thread
# call: github_thread.py:on_github_pull_request_review_thread

# - name: slack_message
# connection: slack_conn
# event_type: message
# call: slack_message.py:on_slack_message
# - name: slack_reaction_added
# connection: slack_conn
# event_type: reaction_added
# call: slack_reaction.py:on_slack_reaction_added
- name: slack_slash_command
connection: slack_conn
event_type: slash_command
call: slack_cmd.py:on_slack_slash_command
48 changes: 48 additions & 0 deletions purrr/data_helper.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
"""Thin wrapper over the Google Sheets API for data management and caching.
Redis/Valkey would be a better choice, but are not available at this time.
"""

from datetime import datetime


# Cache user lookup results for a day, to reduce the amount
# of API calls (especially to Slack), to avoid throttling.
_USER_CACHE_TTL = "24h"


def cache_slack_user_id(github_username: str, slack_user_id: str) -> None:
"""Map a GitHub username to a Slack user ID, for a day.
This helps reduce the amount of Slack lookup API calls, to avoid throttling.
"""
return # TODO: Implement this function.


def cached_slack_user_id(github_username: str) -> str:
"""Return the Slack user ID mapped to a GitHub user, if it's already cached.
This helps reduce the amount of Slack lookup API calls, to avoid throttling.
Args:
github_username: GitHub username to look-up.
Returns:
Slack user ID, or "" if not found.
"""
return "" # TODO: Implement this function.


def slack_opt_in(user_id: str) -> None:
"""Delete the opt-out timestamp for a Slack user."""
return # TODO: Implement this function.


def slack_opt_out(user_id: str) -> None:
"""Return the opt-out timestamp for a Slack user, or None if they're opted-in."""
return # TODO: Implement this function.


def slack_opted_out(user_id: str) -> datetime | None:
"""Return the opt-out timestamp for a Slack user, or None if they're opted-in."""
return None # TODO: Implement this function.
6 changes: 6 additions & 0 deletions purrr/github_helper.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
"""Thin layer of logic on top of the GitHub API."""

from autokitteh.github import github_client


shared_client = github_client("github_conn")
Loading

0 comments on commit d17f8cc

Please sign in to comment.