good-egg 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- good_egg-0.1.0/.claude/agents.md +1 -0
- good_egg-0.1.0/.github/ISSUE_TEMPLATE/bug_report.md +36 -0
- good_egg-0.1.0/.github/ISSUE_TEMPLATE/feature_request.md +21 -0
- good_egg-0.1.0/.github/workflows/ci.yml +33 -0
- good_egg-0.1.0/.github/workflows/release.yml +74 -0
- good_egg-0.1.0/.gitignore +18 -0
- good_egg-0.1.0/.python-version +1 -0
- good_egg-0.1.0/CHANGELOG.md +25 -0
- good_egg-0.1.0/CLAUDE.md +86 -0
- good_egg-0.1.0/CONTRIBUTING.md +83 -0
- good_egg-0.1.0/LICENSE +21 -0
- good_egg-0.1.0/PKG-INFO +266 -0
- good_egg-0.1.0/README.md +235 -0
- good_egg-0.1.0/action.yml +69 -0
- good_egg-0.1.0/assets/egg.jpg +0 -0
- good_egg-0.1.0/docs/configuration.md +171 -0
- good_egg-0.1.0/docs/github-action.md +157 -0
- good_egg-0.1.0/docs/library.md +243 -0
- good_egg-0.1.0/docs/mcp-server.md +221 -0
- good_egg-0.1.0/examples/.good-egg.yml +78 -0
- good_egg-0.1.0/examples/basic-workflow.yml +17 -0
- good_egg-0.1.0/examples/library_usage.py +26 -0
- good_egg-0.1.0/examples/strict-workflow.yml +29 -0
- good_egg-0.1.0/pyproject.toml +81 -0
- good_egg-0.1.0/scripts/generate_language_multipliers.py +127 -0
- good_egg-0.1.0/scripts/validate_scoring.py +405 -0
- good_egg-0.1.0/src/good_egg/__init__.py +25 -0
- good_egg-0.1.0/src/good_egg/__main__.py +6 -0
- good_egg-0.1.0/src/good_egg/action.py +148 -0
- good_egg-0.1.0/src/good_egg/cache.py +125 -0
- good_egg-0.1.0/src/good_egg/cli.py +96 -0
- good_egg-0.1.0/src/good_egg/config.py +174 -0
- good_egg-0.1.0/src/good_egg/exceptions.py +63 -0
- good_egg-0.1.0/src/good_egg/formatter.py +161 -0
- good_egg-0.1.0/src/good_egg/github_client.py +633 -0
- good_egg-0.1.0/src/good_egg/graph_builder.py +181 -0
- good_egg-0.1.0/src/good_egg/mcp_server.py +229 -0
- good_egg-0.1.0/src/good_egg/models.py +92 -0
- good_egg-0.1.0/src/good_egg/py.typed +0 -0
- good_egg-0.1.0/src/good_egg/scorer.py +258 -0
- good_egg-0.1.0/tests/__init__.py +0 -0
- good_egg-0.1.0/tests/conftest.py +178 -0
- good_egg-0.1.0/tests/fixtures/pr_event.json +16 -0
- good_egg-0.1.0/tests/fixtures/user_prs.json +47 -0
- good_egg-0.1.0/tests/test_action.py +231 -0
- good_egg-0.1.0/tests/test_cache.py +102 -0
- good_egg-0.1.0/tests/test_cli.py +154 -0
- good_egg-0.1.0/tests/test_config.py +125 -0
- good_egg-0.1.0/tests/test_formatter.py +191 -0
- good_egg-0.1.0/tests/test_github_client.py +1005 -0
- good_egg-0.1.0/tests/test_graph_builder.py +445 -0
- good_egg-0.1.0/tests/test_mcp_server.py +388 -0
- good_egg-0.1.0/tests/test_models.py +111 -0
- good_egg-0.1.0/tests/test_scorer.py +416 -0
- good_egg-0.1.0/uv.lock +1163 -0
- good_egg-0.1.0/validation/validation_raw_20260209_192001.json +144 -0
- good_egg-0.1.0/validation/validation_raw_20260209_194747.json +817 -0
- good_egg-0.1.0/validation/validation_report_20260209_192001.md +52 -0
- good_egg-0.1.0/validation/validation_report_20260209_194747.md +100 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
../CLAUDE.md
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Bug Report
|
|
3
|
+
about: Report a bug in Good Egg
|
|
4
|
+
labels: bug
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Describe the bug
|
|
8
|
+
|
|
9
|
+
A clear description of what the bug is.
|
|
10
|
+
|
|
11
|
+
## To Reproduce
|
|
12
|
+
|
|
13
|
+
Steps to reproduce the behavior:
|
|
14
|
+
|
|
15
|
+
1. ...
|
|
16
|
+
2. ...
|
|
17
|
+
|
|
18
|
+
## Expected behavior
|
|
19
|
+
|
|
20
|
+
What you expected to happen.
|
|
21
|
+
|
|
22
|
+
## Environment
|
|
23
|
+
|
|
24
|
+
- Good Egg version: (e.g. v0.1.0 or commit SHA)
|
|
25
|
+
- Python version:
|
|
26
|
+
- OS:
|
|
27
|
+
|
|
28
|
+
## Logs / Error Output
|
|
29
|
+
|
|
30
|
+
```
|
|
31
|
+
Paste relevant logs here
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Additional context
|
|
35
|
+
|
|
36
|
+
Any other context about the problem.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Feature Request
|
|
3
|
+
about: Suggest a feature for Good Egg
|
|
4
|
+
labels: enhancement
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Problem
|
|
8
|
+
|
|
9
|
+
What problem does this solve? What use case does it address?
|
|
10
|
+
|
|
11
|
+
## Proposed Solution
|
|
12
|
+
|
|
13
|
+
Describe what you'd like to happen.
|
|
14
|
+
|
|
15
|
+
## Alternatives Considered
|
|
16
|
+
|
|
17
|
+
Any alternative solutions or features you've considered.
|
|
18
|
+
|
|
19
|
+
## Additional Context
|
|
20
|
+
|
|
21
|
+
Any other context, screenshots, or examples.
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
test:
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
steps:
|
|
13
|
+
- uses: actions/checkout@v4
|
|
14
|
+
|
|
15
|
+
- name: Set up Python
|
|
16
|
+
uses: actions/setup-python@v5
|
|
17
|
+
with:
|
|
18
|
+
python-version: '3.12'
|
|
19
|
+
|
|
20
|
+
- name: Install uv
|
|
21
|
+
uses: astral-sh/setup-uv@v4
|
|
22
|
+
|
|
23
|
+
- name: Install dependencies
|
|
24
|
+
run: uv sync
|
|
25
|
+
|
|
26
|
+
- name: Lint
|
|
27
|
+
run: uv run ruff check src/ tests/ scripts/
|
|
28
|
+
|
|
29
|
+
- name: Type check
|
|
30
|
+
run: uv run mypy src/good_egg/
|
|
31
|
+
|
|
32
|
+
- name: Test
|
|
33
|
+
run: uv run pytest --cov=good_egg -v
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags:
|
|
6
|
+
- 'v*'
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
test:
|
|
10
|
+
runs-on: ubuntu-latest
|
|
11
|
+
permissions:
|
|
12
|
+
contents: read
|
|
13
|
+
steps:
|
|
14
|
+
- uses: actions/checkout@v4
|
|
15
|
+
|
|
16
|
+
- name: Set up Python
|
|
17
|
+
uses: actions/setup-python@v5
|
|
18
|
+
with:
|
|
19
|
+
python-version: '3.12'
|
|
20
|
+
|
|
21
|
+
- name: Install uv
|
|
22
|
+
uses: astral-sh/setup-uv@v4
|
|
23
|
+
|
|
24
|
+
- name: Install dependencies
|
|
25
|
+
run: uv sync
|
|
26
|
+
|
|
27
|
+
- name: Lint
|
|
28
|
+
run: uv run ruff check src/ tests/ scripts/
|
|
29
|
+
|
|
30
|
+
- name: Test
|
|
31
|
+
run: uv run pytest --cov=good_egg -v
|
|
32
|
+
|
|
33
|
+
publish:
|
|
34
|
+
needs: test
|
|
35
|
+
runs-on: ubuntu-latest
|
|
36
|
+
environment: pypi
|
|
37
|
+
permissions:
|
|
38
|
+
id-token: write
|
|
39
|
+
steps:
|
|
40
|
+
- uses: actions/checkout@v4
|
|
41
|
+
|
|
42
|
+
- name: Set up Python
|
|
43
|
+
uses: actions/setup-python@v5
|
|
44
|
+
with:
|
|
45
|
+
python-version: '3.12'
|
|
46
|
+
|
|
47
|
+
- name: Install uv
|
|
48
|
+
uses: astral-sh/setup-uv@v4
|
|
49
|
+
|
|
50
|
+
- name: Build package
|
|
51
|
+
run: uv build
|
|
52
|
+
|
|
53
|
+
- name: Publish to PyPI
|
|
54
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
55
|
+
|
|
56
|
+
release:
|
|
57
|
+
needs: publish
|
|
58
|
+
runs-on: ubuntu-latest
|
|
59
|
+
permissions:
|
|
60
|
+
contents: write
|
|
61
|
+
steps:
|
|
62
|
+
- uses: actions/checkout@v4
|
|
63
|
+
|
|
64
|
+
- name: Create GitHub Release
|
|
65
|
+
uses: softprops/action-gh-release@v2
|
|
66
|
+
with:
|
|
67
|
+
generate_release_notes: true
|
|
68
|
+
|
|
69
|
+
- name: Update major version tag
|
|
70
|
+
run: |
|
|
71
|
+
TAG=${GITHUB_REF#refs/tags/}
|
|
72
|
+
MAJOR=${TAG%%.*}
|
|
73
|
+
git tag -f "$MAJOR" "$TAG"
|
|
74
|
+
git push origin "$MAJOR" --force
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
3.12
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [0.1.0] - 2026-02-10
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- GitHub Action for automated PR author trust scoring.
|
|
13
|
+
- CLI tool (`good-egg score`) for scoring contributors from the command line.
|
|
14
|
+
- Python library API for programmatic trust scoring.
|
|
15
|
+
- MCP server for AI assistant integration (optional `mcp` extra).
|
|
16
|
+
- Graph-based trust scoring engine built on weighted contribution graphs.
|
|
17
|
+
- Bipartite graph construction from merged PRs, reviews, and repository metadata.
|
|
18
|
+
- Configurable trust level thresholds (HIGH, MEDIUM, LOW).
|
|
19
|
+
- Recency decay so recent contributions count more than old ones.
|
|
20
|
+
- Language ecosystem normalization for fair cross-language comparison.
|
|
21
|
+
- SQLite-backed response cache with configurable TTLs.
|
|
22
|
+
- YAML configuration with environment variable overrides.
|
|
23
|
+
- Multiple output formatters: Markdown, CLI table, JSON, and GitHub check-run.
|
|
24
|
+
|
|
25
|
+
[0.1.0]: https://github.com/2ndSetAI/good-egg/releases/tag/v0.1.0
|
good_egg-0.1.0/CLAUDE.md
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
# Good Egg -- Project Instructions
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
Good Egg is a trust scoring tool for GitHub PR authors. It builds a weighted contribution graph from a user's merged PRs and computes a personalised trust score to assess how established a contributor is relative to a given project. It runs as a GitHub Action, a CLI, a Python library, and an MCP server.
|
|
6
|
+
|
|
7
|
+
## Tech Stack
|
|
8
|
+
|
|
9
|
+
- **Language**: Python 3.12+
|
|
10
|
+
- **Package manager**: uv
|
|
11
|
+
- **Framework**: Pydantic for config/models, Click for CLI, httpx for async HTTP, NetworkX for graph scoring
|
|
12
|
+
- **Testing**: pytest (with pytest-asyncio, respx for HTTP mocking, pytest-cov)
|
|
13
|
+
- **Linting**: ruff
|
|
14
|
+
- **Type checking**: mypy (strict)
|
|
15
|
+
|
|
16
|
+
## Project Structure
|
|
17
|
+
|
|
18
|
+
```
|
|
19
|
+
src/good_egg/ # Main package
|
|
20
|
+
config.py # Pydantic config models, YAML + env var loading
|
|
21
|
+
models.py # Data models (UserProfile, MergedPR, TrustScore, etc.)
|
|
22
|
+
github_client.py # Async GitHub GraphQL/REST client with retry
|
|
23
|
+
graph_builder.py # Bipartite trust graph construction
|
|
24
|
+
scorer.py # Graph-based trust scoring engine
|
|
25
|
+
formatter.py # Output formatters (Markdown, CLI, JSON, check-run)
|
|
26
|
+
action.py # GitHub Action entry point
|
|
27
|
+
cli.py # Click CLI
|
|
28
|
+
mcp_server.py # MCP server for AI assistant integration
|
|
29
|
+
cache.py # SQLite-backed response cache
|
|
30
|
+
exceptions.py # Custom exception hierarchy
|
|
31
|
+
tests/ # pytest test suite (mirrors src/ structure)
|
|
32
|
+
scripts/ # Utility scripts (validation, language multiplier generation)
|
|
33
|
+
docs/ # Documentation (library, action, MCP, config reference)
|
|
34
|
+
examples/ # Example workflows, config files, library usage
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Commands
|
|
38
|
+
|
|
39
|
+
### Development
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
uv run pytest --cov=good_egg -v # Run tests with coverage
|
|
43
|
+
uv run ruff check src/ tests/ scripts/ # Lint
|
|
44
|
+
uv run mypy src/good_egg/ # Type check
|
|
45
|
+
uv run ruff check --fix src/ tests/ scripts/ # Auto-fix lint issues
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### Running
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
good-egg score <username> --repo <owner/repo> # Score a user
|
|
52
|
+
good-egg cache-stats # Cache statistics
|
|
53
|
+
good-egg cache-clear # Clear cache
|
|
54
|
+
good-egg-mcp # Start MCP server
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### Installation
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
pip install good-egg # Core package
|
|
61
|
+
pip install good-egg[mcp] # With MCP server support
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## Code Conventions
|
|
65
|
+
|
|
66
|
+
- Use `from __future__ import annotations` in every module.
|
|
67
|
+
- Type annotations required on all function signatures.
|
|
68
|
+
- Line length: 99 characters (enforced by ruff).
|
|
69
|
+
- Ruff rule set: E, F, I, N, W, UP, B, A, SIM.
|
|
70
|
+
- Tests go in `tests/` with `test_` prefix matching the source module.
|
|
71
|
+
- Prefer editing existing files over creating new ones.
|
|
72
|
+
- Keep changes minimal and focused -- don't refactor surrounding code unless asked.
|
|
73
|
+
|
|
74
|
+
## Configuration
|
|
75
|
+
|
|
76
|
+
- Config class is `GoodEggConfig` in `config.py`, composed of sub-configs: `GraphScoringConfig`, `EdgeWeightConfig`, `RecencyConfig`, `ThresholdConfig`, `CacheTTLConfig`, `LanguageNormalization`, `FetchConfig`.
|
|
77
|
+
- YAML config key for scoring parameters is `graph_scoring` (not "pagerank").
|
|
78
|
+
- Environment variable overrides use `GOOD_EGG_` prefix.
|
|
79
|
+
- The `[mcp]` optional extra adds the `mcp` dependency for the MCP server.
|
|
80
|
+
|
|
81
|
+
## Important Rules
|
|
82
|
+
|
|
83
|
+
- **No AI attribution**: Do not add `Co-Authored-By`, `Signed-off-by`, or any other trailer attributing AI/Claude to commits. Do not sign PR descriptions, comments, or code comments as Claude or any AI assistant. Commits should be attributed solely to the human author.
|
|
84
|
+
- **No "PageRank" branding**: The project uses NetworkX's `nx.pagerank()` internally, but all user-facing names, docs, config keys, and class names use "graph scoring" instead. Do not introduce "PageRank" into any user-facing surface.
|
|
85
|
+
- **Test before committing**: Always run `uv run pytest --cov=good_egg -v` and `uv run ruff check src/ tests/ scripts/` before considering work complete.
|
|
86
|
+
- **Coverage threshold**: Maintain >= 90% test coverage.
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# Contributing to Good Egg
|
|
2
|
+
|
|
3
|
+
## Setup
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
# Clone
|
|
7
|
+
git clone https://github.com/2ndSetAI/good-egg.git
|
|
8
|
+
cd good-egg
|
|
9
|
+
|
|
10
|
+
# Install uv (if not already installed)
|
|
11
|
+
curl -LsSf https://astral.sh/uv/install.sh | sh
|
|
12
|
+
|
|
13
|
+
# Install dependencies
|
|
14
|
+
uv sync
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Project Structure
|
|
18
|
+
|
|
19
|
+
```
|
|
20
|
+
good-egg/
|
|
21
|
+
├── src/good_egg/
|
|
22
|
+
│ ├── action.py # GitHub Action entry point
|
|
23
|
+
│ ├── cache.py # SQLite-backed response cache
|
|
24
|
+
│ ├── cli.py # Click CLI (good-egg score, cache-stats, cache-clear)
|
|
25
|
+
│ ├── config.py # YAML + env var configuration
|
|
26
|
+
│ ├── exceptions.py # Custom exception hierarchy
|
|
27
|
+
│ ├── formatter.py # Markdown, CLI, JSON, check-run formatters
|
|
28
|
+
│ ├── github_client.py # Async GitHub GraphQL/REST client with retry
|
|
29
|
+
│ ├── graph_builder.py # Bipartite trust graph construction
|
|
30
|
+
│ ├── mcp_server.py # MCP server for AI assistant integration
|
|
31
|
+
│ ├── models.py # Pydantic data models
|
|
32
|
+
│ └── scorer.py # Graph-based trust scoring engine
|
|
33
|
+
├── tests/ # pytest test suite
|
|
34
|
+
├── scripts/
|
|
35
|
+
│ └── validate_scoring.py # Validation against real repos
|
|
36
|
+
├── docs/ # Documentation (library, action, MCP, config)
|
|
37
|
+
├── examples/ # Example workflows and config files
|
|
38
|
+
└── CHANGELOG.md # Release history
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Development Workflow
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
# Run tests
|
|
45
|
+
uv run pytest --cov=good_egg -v
|
|
46
|
+
|
|
47
|
+
# Lint
|
|
48
|
+
uv run ruff check src/ tests/ scripts/
|
|
49
|
+
|
|
50
|
+
# Type check
|
|
51
|
+
uv run mypy src/good_egg/
|
|
52
|
+
|
|
53
|
+
# Format (auto-fix)
|
|
54
|
+
uv run ruff check --fix src/ tests/ scripts/
|
|
55
|
+
|
|
56
|
+
# Verify packaging
|
|
57
|
+
uv build
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## Code Style
|
|
61
|
+
|
|
62
|
+
- Ruff enforces style (E, F, I, N, W, UP, B, A, SIM rules)
|
|
63
|
+
- Line length: 99 characters
|
|
64
|
+
- Type annotations required on all function signatures (mypy strict)
|
|
65
|
+
- Use `from __future__ import annotations` in every module
|
|
66
|
+
|
|
67
|
+
## Running the Validation Suite
|
|
68
|
+
|
|
69
|
+
The validation script scores real PR authors from popular repos to check scoring methodology:
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
GITHUB_TOKEN=$(gh auth token) uv run python scripts/validate_scoring.py --sample-size 5
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
This requires `gh` CLI authenticated. Results are written to the `validation/` directory.
|
|
76
|
+
|
|
77
|
+
## Pull Requests
|
|
78
|
+
|
|
79
|
+
1. Create a feature branch from `main`
|
|
80
|
+
2. Make your changes with tests
|
|
81
|
+
3. Ensure `uv run pytest --cov=good_egg -v` passes with >= 90% coverage
|
|
82
|
+
4. Ensure `uv run ruff check src/ tests/ scripts/` is clean
|
|
83
|
+
5. Open a PR with a clear description
|
good_egg-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 2ndSetAI
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
good_egg-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: good-egg
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Trust scoring for GitHub contributors using graph-based ranking on contribution graphs
|
|
5
|
+
Project-URL: Homepage, https://github.com/2ndSetAI/good-egg
|
|
6
|
+
Project-URL: Repository, https://github.com/2ndSetAI/good-egg
|
|
7
|
+
Project-URL: Issues, https://github.com/2ndSetAI/good-egg/issues
|
|
8
|
+
Author-email: Jeff Smith <jeff@2ndset.ai>
|
|
9
|
+
License: MIT
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Keywords: code-review,github,pull-request,security,trust
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Operating System :: OS Independent
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
+
Classifier: Topic :: Security
|
|
18
|
+
Classifier: Topic :: Software Development :: Quality Assurance
|
|
19
|
+
Requires-Python: >=3.12
|
|
20
|
+
Requires-Dist: click>=8.1
|
|
21
|
+
Requires-Dist: httpx>=0.27
|
|
22
|
+
Requires-Dist: networkx>=3.2
|
|
23
|
+
Requires-Dist: numpy>=1.26
|
|
24
|
+
Requires-Dist: pydantic>=2.5
|
|
25
|
+
Requires-Dist: pyyaml>=6.0
|
|
26
|
+
Requires-Dist: scipy>=1.12
|
|
27
|
+
Requires-Dist: tenacity>=8.2
|
|
28
|
+
Provides-Extra: mcp
|
|
29
|
+
Requires-Dist: mcp>=1.0; extra == 'mcp'
|
|
30
|
+
Description-Content-Type: text/markdown
|
|
31
|
+
|
|
32
|
+
# Good Egg
|
|
33
|
+
|
|
34
|
+
<img src="https://raw.githubusercontent.com/2ndSetAI/good-egg/main/assets/egg.jpg" alt="Good Egg" width="200">
|
|
35
|
+
|
|
36
|
+
Trust scoring for GitHub PR authors using graph-based ranking on contribution
|
|
37
|
+
graphs. Good Egg analyses a contributor's merged pull requests across the
|
|
38
|
+
GitHub ecosystem, builds a weighted contribution graph, and computes a
|
|
39
|
+
personalised trust score to surface how established a contributor is relative
|
|
40
|
+
to your project.
|
|
41
|
+
|
|
42
|
+
Good Egg runs as a **GitHub Action**, a **CLI tool**, a **Python library**,
|
|
43
|
+
and an **MCP server** for AI assistant integration.
|
|
44
|
+
|
|
45
|
+
## Installation
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
pip install good-egg
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
To use the MCP server for AI assistant integration:
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
pip install good-egg[mcp]
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## GitHub Action
|
|
58
|
+
|
|
59
|
+
Add Good Egg to any pull request workflow:
|
|
60
|
+
|
|
61
|
+
```yaml
|
|
62
|
+
name: Good Egg
|
|
63
|
+
|
|
64
|
+
on:
|
|
65
|
+
pull_request:
|
|
66
|
+
types: [opened, reopened, synchronize]
|
|
67
|
+
|
|
68
|
+
permissions:
|
|
69
|
+
pull-requests: write
|
|
70
|
+
|
|
71
|
+
jobs:
|
|
72
|
+
score:
|
|
73
|
+
runs-on: ubuntu-latest
|
|
74
|
+
steps:
|
|
75
|
+
- uses: 2ndSetAI/good-egg@v0
|
|
76
|
+
with:
|
|
77
|
+
github-token: ${{ secrets.GITHUB_TOKEN }}
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
Add `checks: write` to permissions if you enable `check-run: true`.
|
|
81
|
+
|
|
82
|
+
### Action Inputs
|
|
83
|
+
|
|
84
|
+
| Input | Description | Default |
|
|
85
|
+
|-------|-------------|---------|
|
|
86
|
+
| `github-token` | GitHub token for API access | `${{ github.token }}` |
|
|
87
|
+
| `config-path` | Path to `.good-egg.yml` config file | _(auto-detected)_ |
|
|
88
|
+
| `comment` | Post a PR comment with the trust score | `true` |
|
|
89
|
+
| `check-run` | Create a check run with the trust score | `false` |
|
|
90
|
+
| `fail-on-low` | Fail the action if trust level is LOW | `false` |
|
|
91
|
+
|
|
92
|
+
### Action Outputs
|
|
93
|
+
|
|
94
|
+
| Output | Description |
|
|
95
|
+
|--------|-------------|
|
|
96
|
+
| `score` | Normalized trust score (0.0 - 1.0) |
|
|
97
|
+
| `trust-level` | Trust level: HIGH, MEDIUM, LOW, UNKNOWN, or BOT |
|
|
98
|
+
| `user` | GitHub username that was scored |
|
|
99
|
+
|
|
100
|
+
See [docs/github-action.md](docs/github-action.md) for advanced usage,
|
|
101
|
+
custom configuration, and using outputs in downstream steps.
|
|
102
|
+
|
|
103
|
+
## CLI
|
|
104
|
+
|
|
105
|
+
```bash
|
|
106
|
+
# Score a PR author
|
|
107
|
+
good-egg score <username> --repo <owner/repo>
|
|
108
|
+
|
|
109
|
+
# With a GitHub token for higher rate limits
|
|
110
|
+
GITHUB_TOKEN=ghp_... good-egg score octocat --repo octocat/Hello-World
|
|
111
|
+
|
|
112
|
+
# JSON output
|
|
113
|
+
good-egg score octocat --repo octocat/Hello-World --json
|
|
114
|
+
|
|
115
|
+
# Verbose output with contribution details
|
|
116
|
+
good-egg score octocat --repo octocat/Hello-World --verbose
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
### Additional Commands
|
|
120
|
+
|
|
121
|
+
```bash
|
|
122
|
+
good-egg cache-stats # Show cache statistics
|
|
123
|
+
good-egg cache-clear # Remove expired cache entries
|
|
124
|
+
good-egg cache-clear --category repo_metadata # Clear specific category
|
|
125
|
+
good-egg --version # Print version
|
|
126
|
+
good-egg --help # Show help
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
### Exit Codes
|
|
130
|
+
|
|
131
|
+
| Code | Meaning |
|
|
132
|
+
|------|---------|
|
|
133
|
+
| 0 | Success |
|
|
134
|
+
| 1 | Error (invalid input, API failure, missing token) |
|
|
135
|
+
|
|
136
|
+
## Python Library
|
|
137
|
+
|
|
138
|
+
```python
|
|
139
|
+
import asyncio
|
|
140
|
+
import os
|
|
141
|
+
from good_egg import score_pr_author
|
|
142
|
+
|
|
143
|
+
async def main() -> None:
|
|
144
|
+
result = await score_pr_author(
|
|
145
|
+
login="octocat",
|
|
146
|
+
repo_owner="octocat",
|
|
147
|
+
repo_name="Hello-World",
|
|
148
|
+
token=os.environ["GITHUB_TOKEN"],
|
|
149
|
+
)
|
|
150
|
+
print(f"Trust level: {result.trust_level}")
|
|
151
|
+
print(f"Score: {result.normalized_score:.2f}")
|
|
152
|
+
|
|
153
|
+
asyncio.run(main())
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
See [docs/library.md](docs/library.md) for full API documentation, custom
|
|
157
|
+
configuration, error handling, and cache usage.
|
|
158
|
+
|
|
159
|
+
## MCP Server
|
|
160
|
+
|
|
161
|
+
Good Egg includes an MCP (Model Context Protocol) server for integration
|
|
162
|
+
with AI assistants like Claude.
|
|
163
|
+
|
|
164
|
+
```bash
|
|
165
|
+
pip install good-egg[mcp]
|
|
166
|
+
GITHUB_TOKEN=ghp_... good-egg-mcp
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
Add to your Claude Desktop configuration (`claude_desktop_config.json`):
|
|
170
|
+
|
|
171
|
+
```json
|
|
172
|
+
{
|
|
173
|
+
"mcpServers": {
|
|
174
|
+
"good-egg": {
|
|
175
|
+
"command": "good-egg-mcp",
|
|
176
|
+
"env": {
|
|
177
|
+
"GITHUB_TOKEN": "ghp_your_token_here"
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
See [docs/mcp-server.md](docs/mcp-server.md) for tool reference and
|
|
185
|
+
Claude Code configuration.
|
|
186
|
+
|
|
187
|
+
## How It Works
|
|
188
|
+
|
|
189
|
+
1. **Fetch** -- Retrieves the user's merged pull requests and the metadata
|
|
190
|
+
of repositories they have contributed to via the GitHub API.
|
|
191
|
+
2. **Build Graph** -- Constructs a directed graph where nodes represent
|
|
192
|
+
users and repositories, and weighted edges encode contributions. Edge
|
|
193
|
+
weights account for recency (exponential decay) and ecosystem size
|
|
194
|
+
(language normalization).
|
|
195
|
+
3. **Score** -- Runs personalised graph scoring seeded from the context
|
|
196
|
+
repository, so contributions to related projects carry more weight.
|
|
197
|
+
4. **Classify** -- Normalizes the raw graph score to a 0-1 range and maps
|
|
198
|
+
it to a trust level.
|
|
199
|
+
|
|
200
|
+
## Trust Levels
|
|
201
|
+
|
|
202
|
+
| Level | Description |
|
|
203
|
+
|-------|-------------|
|
|
204
|
+
| **HIGH** | Established contributor with a strong cross-project track record |
|
|
205
|
+
| **MEDIUM** | Some contribution history, but limited breadth or recency |
|
|
206
|
+
| **LOW** | Little to no prior contribution history -- review manually |
|
|
207
|
+
| **UNKNOWN** | Insufficient data to produce a meaningful score |
|
|
208
|
+
| **BOT** | Detected bot account (e.g. dependabot, renovate) |
|
|
209
|
+
|
|
210
|
+
## Configuration
|
|
211
|
+
|
|
212
|
+
Create a `.good-egg.yml` in your repository root to customize thresholds,
|
|
213
|
+
scoring parameters, and more:
|
|
214
|
+
|
|
215
|
+
```yaml
|
|
216
|
+
thresholds:
|
|
217
|
+
high_trust: 0.7
|
|
218
|
+
medium_trust: 0.3
|
|
219
|
+
new_account_days: 30
|
|
220
|
+
|
|
221
|
+
graph_scoring:
|
|
222
|
+
alpha: 0.85
|
|
223
|
+
|
|
224
|
+
recency:
|
|
225
|
+
half_life_days: 180
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
Environment variables with the `GOOD_EGG_` prefix can override individual
|
|
229
|
+
settings. See [docs/configuration.md](docs/configuration.md) for the full
|
|
230
|
+
reference, and [examples/.good-egg.yml](examples/.good-egg.yml) for a
|
|
231
|
+
complete example config file with all defaults.
|
|
232
|
+
|
|
233
|
+
## Troubleshooting
|
|
234
|
+
|
|
235
|
+
### Rate Limits
|
|
236
|
+
|
|
237
|
+
Good Egg retries automatically on GitHub API rate limits with exponential
|
|
238
|
+
backoff. If you see persistent failures:
|
|
239
|
+
|
|
240
|
+
- Use a GitHub App token instead of `GITHUB_TOKEN` for higher rate limits
|
|
241
|
+
(5000 req/hr vs 1000).
|
|
242
|
+
- Reduce `fetch.max_prs` in your config to lower API usage per scored user.
|
|
243
|
+
|
|
244
|
+
### Required Permissions
|
|
245
|
+
|
|
246
|
+
| Permission | Required For |
|
|
247
|
+
|-----------|-------------|
|
|
248
|
+
| `pull-requests: write` | Posting PR comments |
|
|
249
|
+
| `checks: write` | Creating check runs (when `check-run: true`) |
|
|
250
|
+
|
|
251
|
+
### Common Errors
|
|
252
|
+
|
|
253
|
+
| Error | Cause | Fix |
|
|
254
|
+
|-------|-------|-----|
|
|
255
|
+
| `Rate limit exhausted` | Too many API calls | Wait for reset or use App token |
|
|
256
|
+
| `User not found` | Deleted/renamed account | Action continues with UNKNOWN score |
|
|
257
|
+
| `Could not extract PR number` | Not a PR event | Ensure workflow triggers on `pull_request` |
|
|
258
|
+
| `Invalid GITHUB_REPOSITORY` | Malformed env var | Check Actions environment |
|
|
259
|
+
|
|
260
|
+
## License
|
|
261
|
+
|
|
262
|
+
MIT
|
|
263
|
+
|
|
264
|
+
---
|
|
265
|
+
|
|
266
|
+
Egg image CC BY 2.0 (Flickr: renwest)
|