A reusable GitHub Action that analyzes pull request complexity using OpenAI's LLM. This action uses the complexity-analyzer tool to calculate a complexity score (1-10) and provide an explanation for the score.
- 🔍 Analyzes PR diffs to calculate complexity scores (1-10 scale)
- 🤖 Powered by OpenAI's GPT models
- 📊 Provides detailed explanations for complexity ratings
- 🔄 Reusable across all repositories
- ⚙️ Highly configurable with sensible defaults
- 📝 Supports both JSON and Markdown output formats
- 💬 Optional automatic PR comments
name: Analyze PR Complexity
on:
pull_request:
types: [opened, synchronize]
jobs:
complexity-analysis:
runs-on: ubuntu-latest
steps:
- name: Analyze PR Complexity
uses: your-org/complexity-analyzer@main
with:
pr-url: ${{ github.event.pull_request.html_url }}
openai-api-key: ${{ secrets.OPENAI_API_KEY }}
github-token: ${{ secrets.GITHUB_TOKEN }}name: Analyze PR Complexity
on:
pull_request:
types: [opened, synchronize]
jobs:
complexity-analysis:
runs-on: ubuntu-latest
steps:
- name: Analyze PR Complexity
id: complexity
uses: your-org/complexity-analyzer@main
with:
pr-url: ${{ github.event.pull_request.html_url }}
openai-api-key: ${{ secrets.OPENAI_API_KEY }}
github-token: ${{ secrets.GITHUB_TOKEN }}
model: 'gpt-4'
format: 'json'
output-file: 'complexity-report.json'
timeout: '120'
max-tokens: '50000'
hunks-per-file: '2'
sleep-seconds: '0.7'
python-version: '3.11'
- name: Display complexity score
run: |
echo "Complexity Score: ${{ steps.complexity.outputs.score }}"
echo "Explanation: ${{ steps.complexity.outputs.explanation }}"
echo "Model: ${{ steps.complexity.outputs.model }}"
- name: Upload complexity report
uses: actions/upload-artifact@v4
with:
name: complexity-report
path: complexity-report.jsonname: Analyze PR Complexity
on:
pull_request:
types: [opened, synchronize]
jobs:
complexity-analysis:
runs-on: ubuntu-latest
permissions:
pull-requests: write
contents: read
steps:
- name: Analyze PR Complexity
id: complexity
uses: your-org/complexity-analyzer@main
with:
pr-url: ${{ github.event.pull_request.html_url }}
openai-api-key: ${{ secrets.OPENAI_API_KEY }}
github-token: ${{ secrets.GITHUB_TOKEN }}
format: 'json'
- name: Comment PR
uses: actions/github-script@v7
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const score = ${{ steps.complexity.outputs.score }};
const explanation = JSON.parse(${{ steps.complexity.outputs.explanation }});
const comment = `## 📊 PR Complexity Analysis
**Complexity Score:** ${score}/10
**Explanation:**
${explanation}
---
*Analyzed by [Complexity Analyzer](https://github.com/your-org/complexity-analyzer)*`;
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: comment
});| Input | Description | Required | Default |
|---|---|---|---|
pr-url |
GitHub PR URL (e.g., https://github.com/owner/repo/pull/123) |
Yes | - |
openai-api-key |
OpenAI API key for LLM analysis | Yes | - |
github-token |
GitHub token for API access | No | ${{ github.token }} |
model |
OpenAI model name (e.g., gpt-4, gpt-5.1) |
No | gpt-5.1 |
format |
Output format: json or markdown |
No | json |
output-file |
Path to write output file | No | - |
timeout |
Request timeout in seconds | No | 120 |
max-tokens |
Maximum tokens for diff excerpt | No | 50000 |
hunks-per-file |
Maximum hunks per file to analyze | No | 2 |
sleep-seconds |
Sleep duration between GitHub API calls | No | 0.7 |
python-version |
Python version to use | No | 3.11 |
| Output | Description |
|---|---|
score |
Complexity score from 1-10 |
explanation |
Detailed explanation of the complexity rating |
model |
Model used for analysis (e.g., gpt-4, gpt-5.1) |
output |
Full JSON output from the analyzer |
{
"score": 5,
"explanation": "Multiple modules/services with non-trivial control flow changes",
"provider": "openai",
"model": "gpt-5.1",
"tokens": 1234,
"timestamp": "2024-01-01T12:00:00Z"
}When using format: 'markdown', the action outputs:
# PR Complexity Analysis
**Score:** 5/10
**Explanation:** Multiple modules/services with non-trivial control flow changes
**Details:**
- Repository: owner/repo
- PR: #123
- Model: gpt-5.1
- Tokens used: 1234You need to configure the following secrets in your repository:
-
OPENAI_API_KEY(Required)- Your OpenAI API key
- Get one from: https://platform.openai.com/api-keys
-
GITHUB_TOKEN(Optional but recommended)- Automatically provided by GitHub Actions
- Used for accessing GitHub API (higher rate limits for authenticated requests)
- Required for private repositories
- Go to your repository settings
- Navigate to Secrets and variables → Actions
- Click New repository secret
- Add
OPENAI_API_KEYwith your OpenAI API key
The analyzer returns a score from 1-10:
- 1-3: Simple changes (docs, small bug fixes, minor refactors)
- 4-6: Moderate complexity (new features, multiple files, some logic changes)
- 7-8: Significant complexity (architectural changes, complex logic)
- 9-10: Very high complexity (major refactors, system-wide changes)
- Fetch PR: Downloads the PR diff and metadata from GitHub API
- Process Diff:
- Redacts secrets and emails
- Filters out binary files, lockfiles, and vendor directories
- Truncates to token limit while preserving structure
- Builds statistics (additions, deletions, file counts, languages)
- Analyze: Sends formatted prompt to LLM with diff excerpt, stats, and title
- Score: Parses LLM response and returns complexity score (1-10) with explanation
- Secrets are never logged or persisted
- API keys are read from environment variables only
- Diffs are redacted to remove secrets and emails
- File paths are normalized to prevent directory traversal
- Requires OpenAI API access (costs may apply based on usage)
- Large PRs may be truncated to fit within token limits
- Analysis quality depends on the selected model
- Rate limited by GitHub API (0.7s delay between calls by default)
- name: Analyze PR
uses: your-org/complexity-analyzer@main
with:
pr-url: ${{ github.event.pull_request.html_url }}
openai-api-key: ${{ secrets.OPENAI_API_KEY }}
output-file: 'complexity.json'
- name: Upload Report
uses: actions/upload-artifact@v4
with:
name: complexity-analysis
path: complexity.json- name: Analyze with GPT-4
id: gpt4
uses: your-org/complexity-analyzer@main
with:
pr-url: ${{ github.event.pull_request.html_url }}
openai-api-key: ${{ secrets.OPENAI_API_KEY }}
model: 'gpt-4'
- name: Analyze with GPT-5.1
id: gpt5
uses: your-org/complexity-analyzer@main
with:
pr-url: ${{ github.event.pull_request.html_url }}
openai-api-key: ${{ secrets.OPENAI_API_KEY }}
model: 'gpt-5.1'
- name: Compare Results
run: |
echo "GPT-4 Score: ${{ steps.gpt4.outputs.score }}"
echo "GPT-5.1 Score: ${{ steps.gpt5.outputs.score }}"Make sure you've set up the OPENAI_API_KEY secret in your repository settings.
- Ensure the PR URL is correct
- For private repositories, make sure
GITHUB_TOKENis provided - Check that the token has sufficient permissions
Increase the sleep-seconds parameter to add more delay between GitHub API calls.
Reduce max-tokens or hunks-per-file to limit the amount of diff data sent to the LLM.
MIT License - See LICENSE file for details
Contributions are welcome! Please see the main repository for more information.
For issues, questions, or feature requests, please open an issue in the GitHub repository.