Skip to content
Merged
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
86 changes: 86 additions & 0 deletions .cursorrules
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
# GitHub Action Executor - Cursor AI Rules

## Project Overview
This is a FastAPI web application for triggering GitHub Actions workflows with OAuth authentication and permission checks.

## Environment Setup
- **Virtual Environment**: The project uses a Python virtual environment located at `./venv/`
- **Activation**: Always activate venv before running commands: `source venv/bin/activate` (Linux/Mac) or `venv\Scripts\activate` (Windows)
- **Python Version**: Python 3.12
- **Dependencies**: Install with `pip install -r requirements.txt` (after activating venv)

## Project Structure
- `app.py` - Main FastAPI application entry point
- `backend/routes/` - API route handlers (auth, workflow, api)
- `backend/services/` - Business logic services (GitHub API, OAuth, permissions)
- `frontend/templates/` - Jinja2 HTML templates
- `frontend/static/` - Static files (CSS, images)
- `tests/` - Pytest test suite
- `config.py` - Application configuration

## Running Commands
- **Start application (development)**: `python app.py` or `uvicorn app:app --host 0.0.0.0 --port 8000 --reload`
- **Start application (background with nohup)**: `./start.sh` (uses nohup, logs to nohup.out)
- **Stop application (nohup)**: `./stop.sh` (stops process started with start.sh)
- **Run as systemd service**: See "Deployment" section below
- **Run tests**: `pytest tests/ -v` (requires venv activation)
- **Run specific test**: `pytest tests/test_app.py::test_function_name -v`
- **Check syntax**: `python -m py_compile <file.py>`

## Testing
- **Test location**: `tests/` directory
- **Test framework**: pytest with pytest-asyncio
- **Fixtures**: Defined in `tests/conftest.py`
- **Always activate venv before running tests**: `source venv/bin/activate && pytest tests/ -v`
- **Test client**: Uses FastAPI TestClient from `fastapi.testclient`

## Code Style
- **Language**: Python 3.12 with type hints
- **Framework**: FastAPI (async/await)
- **Templates**: Jinja2 for HTML templates
- **Comments**: Use English for code comments and docstrings
- **Error handling**: Use try/except with proper logging

## Key Dependencies
- FastAPI - Web framework
- httpx - Async HTTP client for GitHub API
- PyJWT - JWT token generation for GitHub App
- python-dotenv - Environment variable management
- pytest - Testing framework

## Important Notes
- **Session Management**: Uses Starlette SessionMiddleware for OAuth state
- **GitHub App**: Requires GITHUB_APP_ID, GITHUB_APP_INSTALLATION_ID, and private key
- **OAuth**: Requires GITHUB_CLIENT_ID and GITHUB_CLIENT_SECRET
- **Environment Variables**: Loaded from `.env` file via python-dotenv
- **Templates**: Jinja2 templates in `frontend/templates/` with custom filters (urlencode)

## Common Tasks
- **Adding new route**: Add to appropriate file in `backend/routes/`
- **Adding new service**: Add to `backend/services/`
- **Adding test**: Add to `tests/` directory, follow existing patterns
- **Modifying templates**: Edit files in `frontend/templates/`


## Deployment
- **Development mode**: Direct execution with `python app.py` or `uvicorn` with `--reload`
- **Production with nohup**: Use `./start.sh` script (logs to `nohup.out`, PID in `app.pid`)
- **Production with systemd**: Use `github-action-executor.service` file
- Service file location: `github-action-executor.service`
- Installation: `sudo cp github-action-executor.service /etc/systemd/system/`
- Commands: `sudo systemctl start/stop/restart/status github-action-executor`
- Enable on boot: `sudo systemctl enable github-action-executor`
- Logs: `sudo journalctl -u github-action-executor -f`
- **Important**: Edit service file to set correct paths (WorkingDirectory, PATH, User, EnvironmentFile)
- **Service configuration**: Service uses venv Python and loads `.env` file automatically
- **Process management**: When running as service, use systemctl commands, not direct process management

## When Writing Code
- Always check if venv needs to be activated for Python commands
- Use async/await for all I/O operations (GitHub API calls)
- Add proper error handling and logging
- Write tests for new functionality
- Follow existing code patterns and structure
- Use type hints for function parameters and return values
- **When modifying startup logic**: Consider both development (direct) and production (service) modes

247 changes: 247 additions & 0 deletions .github/scripts/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,247 @@
# Badge Generator Scripts

Universal Python module for generating GitHub Actions workflow trigger badges.

## 📁 File Structure

```
.github/scripts/
├── generate_badges.py # Core module (low-level API)
├── generate_markdown.py # Markdown generator script
├── badge_config_builder.py # Python API for building configs
├── example_config.json # Example configuration
├── example_config.md # Visualization of example config
├── example_builder_usage.py # Example usage of BadgeConfigBuilder
└── README.md # This file
```

## 🎯 Quick Start

### Option 1: Programmatic Configuration (Recommended)

```python
from badge_config_builder import BadgeConfigBuilder

# 1. Create builder (creates temp config)
builder = BadgeConfigBuilder()

# 2. Add components
builder.add_workflow_table(
title="🧪 Run Tests",
workflow_id="test.yml",
rows=[
{"sanitizer": "Address", "badge_color": "4caf50", "inputs": {"sanitizer": "address"}},
{"sanitizer": "Memory", "badge_color": "2196f3", "inputs": {"sanitizer": "memory"}}
],
column_headers=["Sanitizer", "Actions"],
label_key="sanitizer"
)

builder.add_workflow_pair("🔨 Build", "build.yml")
builder.set_backport(["release/v1.0", "stable"])

# 3. Save config
config_path = builder.save()

# 4. Generate markdown preview
markdown = builder.generate_markdown(
app_domain="https://your-app.com",
repo_owner="owner",
repo_name="repo",
pr_number=123,
pr_branch="feature",
base_branch="main",
output_path="preview.md"
)
```

See `example_builder_usage.py` for a complete example.

### Option 2: Manual JSON Configuration

Create a JSON config file (see `example_config.json` for reference):

```json
{
"workflows": [
{
"title": "🧪 Run Tests",
"type": "table",
"workflow_id": "test.yml",
"rows": [...]
}
],
"backport_branches": ["release/v1.0"],
"legend": {...}
}
```

Then use `generate_markdown.py`:

```bash
python3 .github/scripts/badges/generate_markdown.py \
--config badge_config.json \
--app-domain "https://your-app.com" \
--repo-owner "owner" \
--repo-name "repo" \
--pr-number 123 \
--pr-branch "feature" \
--base-branch "main" \
--output comment.txt
```

## 📚 Architecture

### Core Module (`generate_badges.py`)

**Low-Level Functions (Core API):**
- `create_badge()` - Generate a single badge (direct or UI)
- `create_badge_pair()` - Generate a pair of badges (direct + UI)
- `create_table()` - Generate a markdown table with custom row formatter

**High-Level Helpers (Optional):**
- `create_backport_table()` - Convenience wrapper for backport tables
- `generate_comment()` - Generate complete PR comment

### Markdown Generator Script (`generate_markdown.py`)

Wrapper script used in GitHub Actions workflows. Reads JSON config and generates PR comment.

### Config Builder (`badge_config_builder.py`)

Python API for programmatically building configurations:
- `BadgeConfigBuilder()` - Create/load config
- `add_workflow_pair()` - Add simple workflow
- `add_workflow_table()` - Add workflow with table
- `set_backport()` - Configure backport
- `set_legend()` - Configure legend
- `save()` - Save config to file
- `generate_markdown()` - Generate markdown preview

## 📖 Examples

- **`example_config.json`** - Complete example configuration
- **`example_config.md`** - Visualization of what the example config generates
- **`example_builder_usage.py`** - Example of using BadgeConfigBuilder programmatically

## 🔧 Configuration Format

### Simple Badge Pair

```json
{
"workflows": [
{
"title": "🔨 Build",
"type": "pair",
"workflow_id": "build.yml",
"ref": "main",
"inputs": {"build_type": "release"},
"badge_color": "2196f3",
"icon": "🔨"
}
]
}
```

### Table with Multiple Rows

```json
{
"workflows": [
{
"title": "🧪 Run Tests",
"type": "table",
"workflow_id": "test.yml",
"column_headers": ["Sanitizer", "Actions"],
"label_key": "sanitizer",
"rows": [
{
"sanitizer": "Address",
"badge_color": "4caf50",
"inputs": {"sanitizer": "address"}
},
{
"sanitizer": "Memory",
"badge_color": "2196f3",
"inputs": {"sanitizer": "memory"}
}
]
}
]
}
```

### Legend Configuration

```json
{
"legend": {
"enabled": true,
"direct_text": "▶ - immediately runs the workflow with default parameters.",
"ui_text": "⚙️ - opens UI to review and modify parameters before running."
}
}
```

## 🚀 Integration

### Copy to Your Repository

```bash
mkdir -p .github/scripts
cp generate_badges.py generate_markdown.py .github/scripts/badges/
```

### Use in GitHub Actions

```yaml
- name: Generate badges
run: |
python3 .github/scripts/badges/generate_markdown.py \
--config badge_config.json \
--app-domain "${{ vars.APP_DOMAIN }}" \
--repo-owner "${{ github.repository_owner }}" \
--repo-name "${{ github.event.repository.name }}" \
--pr-number ${{ github.event.pull_request.number }} \
--pr-branch "${{ github.event.pull_request.head.ref }}" \
--base-branch "${{ github.event.pull_request.base.ref }}" \
--output comment.txt
```

## 📝 API Reference

### BadgeGenerator (Core Module)

```python
from generate_badges import BadgeGenerator

gen = BadgeGenerator(
app_domain="https://your-app.com",
repo_owner="owner",
repo_name="repo",
pr_number=123
)

# Low-level functions
badge = gen.create_badge("Run Tests", "test.yml", link_type="direct")
pair = gen.create_badge_pair("Run Tests", "test.yml")
table = gen.create_table(rows, headers, formatter)
```

### BadgeConfigBuilder

```python
from badge_config_builder import BadgeConfigBuilder

builder = BadgeConfigBuilder()
builder.add_workflow_pair("Build", "build.yml")
builder.add_workflow_table("Tests", "test.yml", rows=[...])
builder.set_backport(["release/v1.0"])
config_path = builder.save()
markdown = builder.generate_markdown(...)
```

## 📄 License

This script is part of the GitHub Action Executor project.
Loading