Skip to main content

Slack and GitHub integration for automating code review requests

Project description

review-request

A Python package for automating Slack code review requests and GitHub PR reminders. Call the services directly from any Python application — no web framework dependency.

Features

  • Send Slack review request messages from a slash command payload
  • Daily digest of open GitHub PRs awaiting team review
  • Slack notification when a Jira sprint closes
  • Slack alert for in-progress Jira issues past their due date

Installation

pip install review-request

Requires Python 3.11+.

Configuration

There is no global config object. Pass credentials and mappings directly to each service constructor. The CLI scripts read from environment variables (or a .env file):

Variable Purpose
GITHUB_TOKEN GitHub API auth
BOT_TOKEN Slack bot token
JIRA_SITE e.g. https://yourorg.atlassian.net
JIRA_EMAIL Jira account email
JIRA_API_TOKEN Jira API token
APP_URL Public URL for bot icon (optional)

Usage

All services are async. Call them from a route handler, background task, or any async context in your service.

Send a review request

SendMessage parses a Slack slash command text payload, fetches the PR from GitHub, and posts or schedules a message to Slack.

from review_request.services.send_message import SendMessage

async def handle_review_request(user_id: str, text: str) -> None:
    await SendMessage(
        user_id=user_id,
        message=text,
        github_token="ghp_...",
        bot_token="xoxb-...",
        default_channel_id="C123456",
        slack_team_mappings={"@squad-name": "S123456"},
    ).send()

The text format:

<PR_URL> [@user or #channel or @group] [--scheduled=YYYY/MM/DD HH:MM:SS]
Example Behaviour
https://github.com/org/repo/pull/123 @alice Posts immediately, mentions @alice
https://github.com/org/repo/pull/123 #code-review @squad Posts to #code-review, mentions @squad
https://github.com/org/repo/pull/123 --scheduled=2025/12/01 09:00:00 Schedules at 09:00 GMT+7

If no reviewer is specified, the service falls back to the teams already requested on the GitHub PR. Up to 2 PR URLs may be submitted at once.

Raises ValueError for invalid input (no URL, invalid URL, too many PRs). Handle it to return a user-facing error:

try:
    await SendMessage(user_id, text, channel_id).send()
except ValueError as e:
    return {"error": str(e)}

Send a daily PR reminder

PRReminderService scans GitHub for open PRs assigned to a team and posts a digest to Slack.

from review_request.services.pr_reminder_service import PRReminderService

async def send_pr_reminder() -> None:
    service = PRReminderService(
        github_token="ghp_...",
        slack_token="xoxb-...",
        repositories=[
            {"url": "https://github.com/org/repo", "base_branch": "main"},
        ],
    )
    team_config = {
        "channel_id": "C123456",         # Slack channel to post to
        "slack_group_id": "S123456",     # Slack usergroup to mention
        "github_team": "my-team",        # GitHub team slug
        "max_age_pr_days": 30,           # ignore PRs older than this
        "remind_date": ["Monday", "Wednesday", "Friday"],  # days to send
    }
    await service.send_reminder(team_config)

send_reminder skips posting if today is not in remind_date and returns True when nothing needs sending.


Notify on Jira sprint completion

JiraSprintNotificationService posts a formatted sprint summary to a Slack channel.

from review_request.services.jira_sprint_notification_service import (
    JiraSprintNotificationService,
    SprintNotificationError,
)

async def notify_sprint_complete(
    channel_id: str,
    sprint_name: str,
    start_date: str,
    end_date: str,
    completed_by: str,
) -> None:
    service = JiraSprintNotificationService(slack_token="xoxb-...")
    await service.send_notification(
        channel_id=channel_id,
        sprint_name=sprint_name,
        start_date=start_date,
        end_date=end_date,
        completed_by=completed_by,
    )

# Or process a raw Jira webhook payload (only acts on "sprint_closed" events)
async def handle_jira_webhook(channel_id: str, webhook_data: dict) -> None:
    service = JiraSprintNotificationService(slack_token="xoxb-...")
    await service.process_webhook(channel_id=channel_id, webhook_data=webhook_data)

Send a Jira overdue reminder

JiraOverdueReminderService queries Jira for in-progress issues past their due date and posts a Slack alert.

from review_request.services.jira_overdue_reminder_service import JiraOverdueReminderService

async def send_jira_overdue_reminder() -> None:
    service = JiraOverdueReminderService(
        jira_site="https://yourorg.atlassian.net",
        jira_email="you@example.com",
        jira_api_token="...",
        slack_token="xoxb-...",
    )
    team_config = {
        "channel_id": "C123456",
        "slack_group_id": "S123456",
        "jira_jql": 'project = ET AND statusCategory = "In Progress" AND duedate < now()',
        "remind_date": ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday"],
    }
    await service.send_reminder(team_config)

CLI scripts

The package also ships two CLI commands for running reminders directly (e.g. from a cron job):

pr-reminder             # send PR digest for all configured teams
pr-reminder --dry-run   # print messages without posting to Slack
jira-overdue-reminder   # send Jira overdue alerts for all configured teams

Development

python -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]"

pytest                           # run all tests
pytest tests/path/test.py::fn    # run a single test
ruff check src/ && black src/    # lint and format
mypy src/                         # type check
pre-commit run --all-files        # run all pre-commit hooks

Publishing

Merging to main automatically publishes to PyPI via GitHub Actions (OIDC trusted publishing, no stored token required).

Always bump the version before merging to avoid a duplicate version rejection:

./scripts/bump_version.sh           # patch  0.1.2 → 0.1.3
./scripts/bump_version.sh minor     # minor  0.1.2 → 0.2.0
./scripts/bump_version.sh major     # major  0.1.2 → 1.0.0

This updates both pyproject.toml and src/review_request/__init__.py.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

review_request-0.1.4.tar.gz (28.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

review_request-0.1.4-py3-none-any.whl (35.9 kB view details)

Uploaded Python 3

File details

Details for the file review_request-0.1.4.tar.gz.

File metadata

  • Download URL: review_request-0.1.4.tar.gz
  • Upload date:
  • Size: 28.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.12.9

File hashes

Hashes for review_request-0.1.4.tar.gz
Algorithm Hash digest
SHA256 339b196e6cddf7aad80d03a0033f40c23d7c9c94b7927cce3729de9614e14854
MD5 41ecc95063ce4b15674382af695a39aa
BLAKE2b-256 06d9d177f60962628ce635c6601817423cc23c0c4b206579b2551c15209fd5d1

See more details on using hashes here.

Provenance

The following attestation bundles were made for review_request-0.1.4.tar.gz:

Publisher: publish.yml on kingkong0905/review-request

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file review_request-0.1.4-py3-none-any.whl.

File metadata

  • Download URL: review_request-0.1.4-py3-none-any.whl
  • Upload date:
  • Size: 35.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.12.9

File hashes

Hashes for review_request-0.1.4-py3-none-any.whl
Algorithm Hash digest
SHA256 443d74736cf95cd907d64363b612e111461571e8d77dc712c7af43b7bc12207e
MD5 da2b005f39c024e25c733dc511f1dd16
BLAKE2b-256 711db8ee4c1e6b91d7474d561c22b6fd9db02f8023faf27b564415502e0978f2

See more details on using hashes here.

Provenance

The following attestation bundles were made for review_request-0.1.4-py3-none-any.whl:

Publisher: publish.yml on kingkong0905/review-request

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page