Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Database Configuration
DATABASE_URL=postgresql://user:password@localhost:5432/dbname
# Or for SQLite (development):
# DATABASE_URL=sqlite:///database.db

# API Keys for Code Analysis
OPENAI_API_KEY=your_openai_api_key_here
ANTHROPIC_API_KEY=your_anthropic_api_key_here

# Hugging Face Configuration
HF_TOKEN=your_huggingface_token_here

# GitHub Token (for scripts/update_checklist.py)
GITHUB_TOKEN=your_github_personal_access_token_here

# Optional: Distributed Training Configuration
# MASTER_ADDR=localhost
# MASTER_PORT=29500

# Optional: Debugging
# SQL_DEBUG=False
# SPACE_ID=your_space_id
2 changes: 1 addition & 1 deletion .github/workflows/auto-update-checklist.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ jobs:
python-version: '3.10'

- name: Install dependencies
run: pip install requests
run: pip install requests python-dotenv

- name: Run checklist updater
env:
Expand Down
4 changes: 3 additions & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,6 @@ flask
flask-migrate
flask-sqlalchemy
datasets
argilla
argilla
python-dotenv==1.0.0
requests>=2.31.0
72 changes: 72 additions & 0 deletions scripts/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
# Scripts Directory

This directory contains automation scripts for the CodeTuneStudio repository.

## update_checklist.py

Automatically updates the PR review checklist by fetching merged PRs from GitHub and marking them as completed.

### Requirements

- Python 3.10+
- python-dotenv
- requests

### Setup

1. Copy `.env.example` to `.env` in the project root:
```bash
cp .env.example .env
```

2. Add your GitHub personal access token to `.env`:
```
GITHUB_TOKEN=your_github_token_here
```

3. Install dependencies:
```bash
pip install -r requirements.txt
```

### Usage

Run the script manually:
```bash
python scripts/update_checklist.py
```

Or let the GitHub Actions workflow run it automatically (configured in `.github/workflows/auto-update-checklist.yml`).

### Security

- **Never commit your `.env` file** - it's already in `.gitignore`
- The script uses `python-dotenv` to securely load credentials from environment variables
- Proper error handling ensures the script fails gracefully if credentials are missing
- All functions follow PEP 8 standards with comprehensive docstrings

### Testing

Run the test suite:
```bash
python -m unittest tests.test_update_checklist -v
```

### How It Works

1. Loads environment variables from `.env` file using `python-dotenv`
2. Validates that `GITHUB_TOKEN` is set and not empty
3. Fetches closed PRs from the GitHub API
4. Reads the `PR_REVIEW_CHECKLIST.md` file
5. Updates lines containing PR numbers that have been merged
6. Writes the updated checklist back to the file

### Error Handling

The script includes comprehensive error handling for:
- Missing or empty `GITHUB_TOKEN`
- GitHub API failures
- File read/write errors
- Network timeouts

All errors result in clear error messages and proper exit codes.
1 change: 1 addition & 0 deletions scripts/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
"""Scripts package for CodeTuneStudio automation."""
240 changes: 240 additions & 0 deletions scripts/update_checklist.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,240 @@
"""
Script to automatically update the PR review checklist.

This script fetches closed PRs from the GitHub API and updates the
PR_REVIEW_CHECKLIST.md file to mark merged PRs as completed.

Environment Variables:
GITHUB_TOKEN: GitHub personal access token (required)

Usage:
python scripts/update_checklist.py
"""

import os
import sys
from typing import Dict, List, Any

import requests
from dotenv import load_dotenv


def load_environment() -> None:
"""
Load environment variables from .env file.

Uses python-dotenv to securely load environment variables from a .env file
if it exists. This allows for secure credential management without
hardcoding sensitive information.
"""
load_dotenv()


def validate_github_token() -> str:
"""
Validate and retrieve the GitHub token from environment variables.

Returns:
str: The GitHub token

Raises:
SystemExit: If GITHUB_TOKEN is not set or is empty, exits with code 1

Example:
>>> os.environ['GITHUB_TOKEN'] = 'ghp_test123'
>>> token = validate_github_token()
>>> assert token == 'ghp_test123'
"""
token = os.getenv("GITHUB_TOKEN")

if not token:
print(
"Error: GITHUB_TOKEN environment variable is not set.",
file=sys.stderr
)
print(
"Please set GITHUB_TOKEN in your environment or .env file.",
file=sys.stderr
)
print(
"For more information, see .env.example",
file=sys.stderr
)
sys.exit(1)

if not token.strip():
print(
"Error: GITHUB_TOKEN is empty.",
file=sys.stderr
)
sys.exit(1)

return token


def fetch_closed_prs(
repo: str,
token: str
) -> List[Dict[str, Any]]:
"""
Fetch closed pull requests from the GitHub API.

Args:
repo: Repository identifier in format 'owner/repo'
token: GitHub personal access token for authentication

Returns:
List of PR dictionaries from GitHub API

Raises:
requests.exceptions.RequestException: If API request fails
SystemExit: If API returns non-200 status code

Example:
>>> prs = fetch_closed_prs('owner/repo', 'token123')
>>> isinstance(prs, list)
True
"""
headers = {"Authorization": f"token {token}"}
url = f"https://api.github.com/repos/{repo}/pulls?state=closed"

try:
response = requests.get(url, headers=headers, timeout=30)
response.raise_for_status()
except requests.exceptions.RequestException as e:
print(f"Error: Failed to fetch PRs from GitHub API: {e}", file=sys.stderr)
sys.exit(1)

return response.json()


def read_checklist_file(filepath: str) -> List[str]:
"""
Read the checklist file and return its lines.

Args:
filepath: Path to the checklist file

Returns:
List of lines from the checklist file

Raises:
SystemExit: If file cannot be read
"""
try:
with open(filepath, "r", encoding="utf-8") as f:
lines = f.readlines()
return lines
except FileNotFoundError:
print(
f"Error: Checklist file '{filepath}' not found.",
file=sys.stderr
)
sys.exit(1)
except OSError as e:
print(
f"Error reading checklist file '{filepath}': {e}",
file=sys.stderr
)
sys.exit(1)


def update_checklist_lines(
lines: List[str],
prs: List[Dict[str, Any]]
) -> List[str]:
"""
Update checklist lines to mark merged PRs as completed.

Args:
lines: List of lines from the checklist file
prs: List of PR dictionaries from GitHub API

Returns:
Updated list of lines with merged PRs marked as completed

Example:
>>> lines = ['- [ ] PR #123 Something', '- [ ] PR #456 Other']
>>> prs = [{'number': 123, 'merged_at': '2024-01-01'}]
>>> updated = update_checklist_lines(lines, prs)
>>> '- [x] PR #123 Something' in updated[0]
True
"""
updated_lines = lines.copy()

for i, line in enumerate(updated_lines):
for pr in prs:
pr_marker = f"PR #{pr['number']}"
if pr_marker in line and pr.get("merged_at"):
# Replace unchecked box with checked box
updated_lines[i] = line.replace("[ ]", "[x]")
break # Move to next line after updating

return updated_lines


def write_checklist_file(filepath: str, lines: List[str]) -> None:
"""
Write updated lines back to the checklist file.

Args:
filepath: Path to the checklist file
lines: Updated list of lines to write

Raises:
SystemExit: If file cannot be written
"""
try:
with open(filepath, "w", encoding="utf-8") as f:
f.writelines(lines)
print(f"Successfully updated checklist: {filepath}")
except (IOError, OSError) as e:
print(
f"Error writing to {filepath}: {e}",
file=sys.stderr
)
sys.exit(1)


def main() -> None:
"""
Main function to update the PR review checklist.

This function orchestrates the entire process:
1. Loads environment variables
2. Validates GitHub token
3. Fetches closed PRs
4. Reads checklist file
5. Updates checklist with merged PRs
6. Writes updated checklist back to file
"""
# Configuration
REPO = "canstralian/CodeTuneStudio"
CHECKLIST_PATH = "PR_REVIEW_CHECKLIST.md"

# Load environment variables from .env file
load_environment()

# Validate GitHub token
github_token = validate_github_token()

# Fetch closed PRs from GitHub
print(f"Fetching closed PRs from {REPO}...")
prs = fetch_closed_prs(REPO, github_token)
print(f"Found {len(prs)} closed PRs")

# Read checklist file
print(f"Reading checklist from {CHECKLIST_PATH}...")
lines = read_checklist_file(CHECKLIST_PATH)

# Update checklist for merged PRs
print("Updating checklist...")
updated_lines = update_checklist_lines(lines, prs)

# Write updated checklist
write_checklist_file(CHECKLIST_PATH, updated_lines)
print("Checklist update complete!")


if __name__ == "__main__":
main()
Loading
Loading