cicaddy-github 0.5.0__tar.gz → 0.6.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.
- {cicaddy_github-0.5.0 → cicaddy_github-0.6.0}/.agents/skills/cicaddy-action/SKILL.md +1 -1
- {cicaddy_github-0.5.0 → cicaddy_github-0.6.0}/.github/workflows/pr-review.yml +2 -1
- {cicaddy_github-0.5.0 → cicaddy_github-0.6.0}/PKG-INFO +2 -2
- {cicaddy_github-0.5.0 → cicaddy_github-0.6.0}/action.yml +1 -1
- {cicaddy_github-0.5.0 → cicaddy_github-0.6.0}/pyproject.toml +2 -2
- {cicaddy_github-0.5.0 → cicaddy_github-0.6.0}/src/cicaddy_github/__init__.py +1 -1
- {cicaddy_github-0.5.0 → cicaddy_github-0.6.0}/src/cicaddy_github/github_integration/agents.py +52 -2
- cicaddy_github-0.6.0/tests/unit/test_review_delegation_hooks.py +146 -0
- {cicaddy_github-0.5.0 → cicaddy_github-0.6.0}/.github/dependabot.yml +0 -0
- {cicaddy_github-0.5.0 → cicaddy_github-0.6.0}/.github/workflows/changelog.yml +0 -0
- {cicaddy_github-0.5.0 → cicaddy_github-0.6.0}/.github/workflows/ci.yml +0 -0
- {cicaddy_github-0.5.0 → cicaddy_github-0.6.0}/.github/workflows/release.yml +0 -0
- {cicaddy_github-0.5.0 → cicaddy_github-0.6.0}/.gitignore +0 -0
- {cicaddy_github-0.5.0 → cicaddy_github-0.6.0}/.pre-commit-config.yaml +0 -0
- {cicaddy_github-0.5.0 → cicaddy_github-0.6.0}/AGENTS.md +0 -0
- {cicaddy_github-0.5.0 → cicaddy_github-0.6.0}/CLAUDE.md +0 -0
- {cicaddy_github-0.5.0 → cicaddy_github-0.6.0}/CODE_OF_CONDUCT.md +0 -0
- {cicaddy_github-0.5.0 → cicaddy_github-0.6.0}/CONTRIBUTING.md +0 -0
- {cicaddy_github-0.5.0 → cicaddy_github-0.6.0}/Dockerfile +0 -0
- {cicaddy_github-0.5.0 → cicaddy_github-0.6.0}/LICENSE +0 -0
- {cicaddy_github-0.5.0 → cicaddy_github-0.6.0}/README.md +0 -0
- {cicaddy_github-0.5.0 → cicaddy_github-0.6.0}/docs/delegation.md +0 -0
- {cicaddy_github-0.5.0 → cicaddy_github-0.6.0}/docs/providers.md +0 -0
- {cicaddy_github-0.5.0 → cicaddy_github-0.6.0}/entrypoint.sh +0 -0
- {cicaddy_github-0.5.0 → cicaddy_github-0.6.0}/src/cicaddy_github/config/__init__.py +0 -0
- {cicaddy_github-0.5.0 → cicaddy_github-0.6.0}/src/cicaddy_github/config/settings.py +0 -0
- {cicaddy_github-0.5.0 → cicaddy_github-0.6.0}/src/cicaddy_github/github_integration/__init__.py +0 -0
- {cicaddy_github-0.5.0 → cicaddy_github-0.6.0}/src/cicaddy_github/github_integration/analyzer.py +0 -0
- {cicaddy_github-0.5.0 → cicaddy_github-0.6.0}/src/cicaddy_github/github_integration/detector.py +0 -0
- {cicaddy_github-0.5.0 → cicaddy_github-0.6.0}/src/cicaddy_github/github_integration/go_dep_review_tools.py +0 -0
- {cicaddy_github-0.5.0 → cicaddy_github-0.6.0}/src/cicaddy_github/github_integration/tools.py +0 -0
- {cicaddy_github-0.5.0 → cicaddy_github-0.6.0}/src/cicaddy_github/plugin.py +0 -0
- {cicaddy_github-0.5.0 → cicaddy_github-0.6.0}/src/cicaddy_github/security/__init__.py +0 -0
- {cicaddy_github-0.5.0 → cicaddy_github-0.6.0}/src/cicaddy_github/security/leak_detector.py +0 -0
- {cicaddy_github-0.5.0 → cicaddy_github-0.6.0}/src/cicaddy_github/validation.py +0 -0
- {cicaddy_github-0.5.0 → cicaddy_github-0.6.0}/tasks/changelog_report.yml +0 -0
- {cicaddy_github-0.5.0 → cicaddy_github-0.6.0}/tasks/go_dep_impact_review.yml +0 -0
- {cicaddy_github-0.5.0 → cicaddy_github-0.6.0}/tasks/pr_review.yml +0 -0
- {cicaddy_github-0.5.0 → cicaddy_github-0.6.0}/templates/report_template.html +0 -0
- {cicaddy_github-0.5.0 → cicaddy_github-0.6.0}/tests/__init__.py +0 -0
- {cicaddy_github-0.5.0 → cicaddy_github-0.6.0}/tests/conftest.py +0 -0
- {cicaddy_github-0.5.0 → cicaddy_github-0.6.0}/tests/unit/__init__.py +0 -0
- {cicaddy_github-0.5.0 → cicaddy_github-0.6.0}/tests/unit/test_agents.py +0 -0
- {cicaddy_github-0.5.0 → cicaddy_github-0.6.0}/tests/unit/test_analyzer.py +0 -0
- {cicaddy_github-0.5.0 → cicaddy_github-0.6.0}/tests/unit/test_detector.py +0 -0
- {cicaddy_github-0.5.0 → cicaddy_github-0.6.0}/tests/unit/test_go_dep_review.py +0 -0
- {cicaddy_github-0.5.0 → cicaddy_github-0.6.0}/tests/unit/test_leak_detector.py +0 -0
- {cicaddy_github-0.5.0 → cicaddy_github-0.6.0}/tests/unit/test_plugin.py +0 -0
- {cicaddy_github-0.5.0 → cicaddy_github-0.6.0}/tests/unit/test_settings.py +0 -0
- {cicaddy_github-0.5.0 → cicaddy_github-0.6.0}/tests/unit/test_tools.py +0 -0
|
@@ -225,7 +225,7 @@ the `safe-to-review` label. The label is auto-removed on new pushes to prevent
|
|
|
225
225
|
TOCTOU bypasses.
|
|
226
226
|
|
|
227
227
|
```yaml
|
|
228
|
-
- uses: redhat-community-ai-tools/cicaddy-action@v0.
|
|
228
|
+
- uses: redhat-community-ai-tools/cicaddy-action@v0.6.0
|
|
229
229
|
with:
|
|
230
230
|
ai_provider: gemini
|
|
231
231
|
ai_model: gemini-3-flash-preview
|
|
@@ -49,7 +49,7 @@ jobs:
|
|
|
49
49
|
fi
|
|
50
50
|
|
|
51
51
|
- name: AI Code Review
|
|
52
|
-
uses:
|
|
52
|
+
uses: redhat-community-ai-tools/cicaddy-action@v0.5.0
|
|
53
53
|
id: review
|
|
54
54
|
with:
|
|
55
55
|
ai_provider: gemini
|
|
@@ -57,6 +57,7 @@ jobs:
|
|
|
57
57
|
ai_api_key: ${{ secrets.AI_API_KEY }}
|
|
58
58
|
task_file: tasks/pr_review.yml
|
|
59
59
|
post_pr_comment: 'true'
|
|
60
|
+
delegation_mode: auto
|
|
60
61
|
mcp_servers_config: ${{ steps.mcp.outputs.config }}
|
|
61
62
|
env:
|
|
62
63
|
ANALYSIS_FOCUS: "general"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: cicaddy-github
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.6.0
|
|
4
4
|
Summary: GitHub Actions plugin for cicaddy AI agent framework
|
|
5
5
|
Project-URL: Homepage, https://github.com/redhat-community-ai-tools/cicaddy-action
|
|
6
6
|
Project-URL: Repository, https://github.com/redhat-community-ai-tools/cicaddy-action.git
|
|
@@ -9,7 +9,7 @@ Author: Wayne Sun
|
|
|
9
9
|
License: Apache-2.0
|
|
10
10
|
License-File: LICENSE
|
|
11
11
|
Requires-Python: >=3.11
|
|
12
|
-
Requires-Dist: cicaddy>=0.
|
|
12
|
+
Requires-Dist: cicaddy>=0.10.0
|
|
13
13
|
Requires-Dist: detect-secrets>=1.4.0
|
|
14
14
|
Requires-Dist: pygithub>=2.1.0
|
|
15
15
|
Provides-Extra: test
|
|
@@ -78,4 +78,4 @@ runs:
|
|
|
78
78
|
using: 'docker'
|
|
79
79
|
image: 'Dockerfile'
|
|
80
80
|
# After first GHCR publish, switch to pre-built image for faster startup:
|
|
81
|
-
# image: 'docker://ghcr.io/redhat-community-ai-tools/cicaddy-action:0.
|
|
81
|
+
# image: 'docker://ghcr.io/redhat-community-ai-tools/cicaddy-action:0.6.0'
|
|
@@ -4,14 +4,14 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "cicaddy-github"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.6.0"
|
|
8
8
|
description = "GitHub Actions plugin for cicaddy AI agent framework"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.11"
|
|
11
11
|
license = {text = "Apache-2.0"}
|
|
12
12
|
authors = [{name = "Wayne Sun"}]
|
|
13
13
|
dependencies = [
|
|
14
|
-
"cicaddy>=0.
|
|
14
|
+
"cicaddy>=0.10.0",
|
|
15
15
|
"PyGithub>=2.1.0",
|
|
16
16
|
"detect-secrets>=1.4.0",
|
|
17
17
|
]
|
{cicaddy_github-0.5.0 → cicaddy_github-0.6.0}/src/cicaddy_github/github_integration/agents.py
RENAMED
|
@@ -173,9 +173,36 @@ class GitHubPRAgent(BaseAIAgent):
|
|
|
173
173
|
self.pr_number = settings.github_pr_number if settings else os.getenv("GITHUB_PR_NUMBER")
|
|
174
174
|
self.leak_detector = LeakDetector()
|
|
175
175
|
|
|
176
|
+
# Delegation hooks — forward to cicaddy core's BaseReviewAgent.
|
|
177
|
+
#
|
|
178
|
+
# This class inherits from BaseAIAgent (not BaseReviewAgent) because it
|
|
179
|
+
# handles GitHub platform integration inline. We forward review-specific
|
|
180
|
+
# delegation hooks as explicit unbound method calls to keep all delegation
|
|
181
|
+
# logic in cicaddy core.
|
|
182
|
+
|
|
176
183
|
def _get_agent_type(self) -> str:
|
|
177
184
|
"""PR review agents use the 'review' delegation registry."""
|
|
178
|
-
|
|
185
|
+
from cicaddy.agent.base_review_agent import (
|
|
186
|
+
BaseReviewAgent as _CoreReviewAgent,
|
|
187
|
+
)
|
|
188
|
+
|
|
189
|
+
return _CoreReviewAgent._get_agent_type(self) # ty: ignore[invalid-argument-type]
|
|
190
|
+
|
|
191
|
+
def _get_delegation_context(self, context: dict[str, Any]) -> dict[str, Any]:
|
|
192
|
+
"""Shape context for review delegation triage."""
|
|
193
|
+
from cicaddy.agent.base_review_agent import (
|
|
194
|
+
BaseReviewAgent as _CoreReviewAgent,
|
|
195
|
+
)
|
|
196
|
+
|
|
197
|
+
return _CoreReviewAgent._get_delegation_context(self, context) # ty: ignore[invalid-argument-type]
|
|
198
|
+
|
|
199
|
+
def _post_process_plan(self, plan: Any, registry: dict[str, Any]) -> Any:
|
|
200
|
+
"""Ensure general-reviewer is always included in review plans."""
|
|
201
|
+
from cicaddy.agent.base_review_agent import (
|
|
202
|
+
BaseReviewAgent as _CoreReviewAgent,
|
|
203
|
+
)
|
|
204
|
+
|
|
205
|
+
return _CoreReviewAgent._post_process_plan(self, plan, registry) # ty: ignore[invalid-argument-type, unresolved-attribute]
|
|
179
206
|
|
|
180
207
|
async def _setup_local_tools(self):
|
|
181
208
|
"""Setup local tools for PR review."""
|
|
@@ -433,9 +460,32 @@ class GitHubGoDepReviewAgent(BaseAIAgent):
|
|
|
433
460
|
self.pr_number = getattr(settings, "github_pr_number", None) if settings else None
|
|
434
461
|
self.leak_detector = LeakDetector()
|
|
435
462
|
|
|
463
|
+
# Delegation hooks — forward to cicaddy core's BaseReviewAgent.
|
|
464
|
+
# See GitHubPRAgent docstring for rationale.
|
|
465
|
+
|
|
436
466
|
def _get_agent_type(self) -> str:
|
|
437
467
|
"""Dependency review agents use the 'review' delegation registry."""
|
|
438
|
-
|
|
468
|
+
from cicaddy.agent.base_review_agent import (
|
|
469
|
+
BaseReviewAgent as _CoreReviewAgent,
|
|
470
|
+
)
|
|
471
|
+
|
|
472
|
+
return _CoreReviewAgent._get_agent_type(self) # ty: ignore[invalid-argument-type]
|
|
473
|
+
|
|
474
|
+
def _get_delegation_context(self, context: dict[str, Any]) -> dict[str, Any]:
|
|
475
|
+
"""Shape context for review delegation triage."""
|
|
476
|
+
from cicaddy.agent.base_review_agent import (
|
|
477
|
+
BaseReviewAgent as _CoreReviewAgent,
|
|
478
|
+
)
|
|
479
|
+
|
|
480
|
+
return _CoreReviewAgent._get_delegation_context(self, context) # ty: ignore[invalid-argument-type]
|
|
481
|
+
|
|
482
|
+
def _post_process_plan(self, plan: Any, registry: dict[str, Any]) -> Any:
|
|
483
|
+
"""Ensure general-reviewer is always included in review plans."""
|
|
484
|
+
from cicaddy.agent.base_review_agent import (
|
|
485
|
+
BaseReviewAgent as _CoreReviewAgent,
|
|
486
|
+
)
|
|
487
|
+
|
|
488
|
+
return _CoreReviewAgent._post_process_plan(self, plan, registry) # ty: ignore[invalid-argument-type, unresolved-attribute]
|
|
439
489
|
|
|
440
490
|
async def _setup_local_tools(self):
|
|
441
491
|
"""Setup local tools including git and dependency review tools."""
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
"""Tests for review agent delegation hook forwarding to cicaddy core."""
|
|
2
|
+
|
|
3
|
+
from unittest.mock import MagicMock
|
|
4
|
+
|
|
5
|
+
import pytest
|
|
6
|
+
from cicaddy.delegation.registry import SubAgentSpec
|
|
7
|
+
from cicaddy.delegation.triage import DelegationEntry, DelegationPlan
|
|
8
|
+
|
|
9
|
+
from cicaddy_github.github_integration.agents import (
|
|
10
|
+
GitHubGoDepReviewAgent,
|
|
11
|
+
GitHubPRAgent,
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
# _post_process_plan exists in cicaddy core >= 0.9.0 (PR #50).
|
|
15
|
+
# CI may install an older release; skip tests that depend on it.
|
|
16
|
+
_has_post_process = hasattr(
|
|
17
|
+
__import__("cicaddy.agent.base_review_agent", fromlist=["BaseReviewAgent"]).BaseReviewAgent,
|
|
18
|
+
"_post_process_plan",
|
|
19
|
+
)
|
|
20
|
+
_skip_no_post_process = pytest.mark.skipif(
|
|
21
|
+
not _has_post_process,
|
|
22
|
+
reason="cicaddy core missing _post_process_plan (needs >= 0.9.0)",
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def _make_pr_agent():
|
|
27
|
+
"""Create a minimal GitHubPRAgent with mocked settings."""
|
|
28
|
+
settings = MagicMock()
|
|
29
|
+
settings.github_pr_number = "123"
|
|
30
|
+
agent = GitHubPRAgent.__new__(GitHubPRAgent)
|
|
31
|
+
agent.settings = settings
|
|
32
|
+
agent.pr_number = "123"
|
|
33
|
+
return agent
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def _make_dep_review_agent():
|
|
37
|
+
"""Create a minimal GitHubGoDepReviewAgent with mocked settings."""
|
|
38
|
+
settings = MagicMock()
|
|
39
|
+
agent = GitHubGoDepReviewAgent.__new__(GitHubGoDepReviewAgent)
|
|
40
|
+
agent.settings = settings
|
|
41
|
+
agent.pr_number = "456"
|
|
42
|
+
return agent
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
class TestPRAgentDelegationHooks:
|
|
46
|
+
"""Verify GitHubPRAgent delegation hooks forward to cicaddy core."""
|
|
47
|
+
|
|
48
|
+
def test_get_agent_type_returns_review(self):
|
|
49
|
+
agent = _make_pr_agent()
|
|
50
|
+
assert agent._get_agent_type() == "review"
|
|
51
|
+
|
|
52
|
+
def test_get_delegation_context_extracts_diff(self):
|
|
53
|
+
agent = _make_pr_agent()
|
|
54
|
+
context = {
|
|
55
|
+
"diff": ("diff --git a/main.go b/main.go\n+import fmt\n"),
|
|
56
|
+
"diff_lines": 2,
|
|
57
|
+
"analysis_type": "pull_request",
|
|
58
|
+
"pull_request": {"title": "Fix bug"},
|
|
59
|
+
}
|
|
60
|
+
result = agent._get_delegation_context(context)
|
|
61
|
+
assert "diff" in result
|
|
62
|
+
assert result["changed_files"] == ["main.go"]
|
|
63
|
+
assert result["analysis_type"] == "pull_request"
|
|
64
|
+
|
|
65
|
+
@_skip_no_post_process
|
|
66
|
+
def test_post_process_plan_injects_general_reviewer(self):
|
|
67
|
+
agent = _make_pr_agent()
|
|
68
|
+
plan = DelegationPlan(
|
|
69
|
+
entries=[
|
|
70
|
+
DelegationEntry(
|
|
71
|
+
agent_name="security-reviewer",
|
|
72
|
+
categories=["security"],
|
|
73
|
+
rationale="test",
|
|
74
|
+
priority=10,
|
|
75
|
+
)
|
|
76
|
+
]
|
|
77
|
+
)
|
|
78
|
+
registry = {
|
|
79
|
+
"security-reviewer": SubAgentSpec(
|
|
80
|
+
name="security-reviewer",
|
|
81
|
+
persona="sec",
|
|
82
|
+
description="Security review",
|
|
83
|
+
categories=["security"],
|
|
84
|
+
priority=10,
|
|
85
|
+
agent_type="review",
|
|
86
|
+
),
|
|
87
|
+
"general-reviewer": SubAgentSpec(
|
|
88
|
+
name="general-reviewer",
|
|
89
|
+
persona="eng",
|
|
90
|
+
description="General review",
|
|
91
|
+
categories=["code_quality"],
|
|
92
|
+
priority=100,
|
|
93
|
+
agent_type="review",
|
|
94
|
+
),
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
result = agent._post_process_plan(plan, registry)
|
|
98
|
+
names = [e.agent_name for e in result.entries]
|
|
99
|
+
assert "general-reviewer" in names
|
|
100
|
+
assert len(result.entries) == 2
|
|
101
|
+
|
|
102
|
+
@_skip_no_post_process
|
|
103
|
+
def test_post_process_plan_no_duplicate(self):
|
|
104
|
+
agent = _make_pr_agent()
|
|
105
|
+
plan = DelegationPlan(
|
|
106
|
+
entries=[
|
|
107
|
+
DelegationEntry(
|
|
108
|
+
agent_name="general-reviewer",
|
|
109
|
+
categories=["code_quality"],
|
|
110
|
+
rationale="test",
|
|
111
|
+
priority=100,
|
|
112
|
+
)
|
|
113
|
+
]
|
|
114
|
+
)
|
|
115
|
+
registry = {
|
|
116
|
+
"general-reviewer": SubAgentSpec(
|
|
117
|
+
name="general-reviewer",
|
|
118
|
+
persona="eng",
|
|
119
|
+
description="General review",
|
|
120
|
+
categories=["code_quality"],
|
|
121
|
+
priority=100,
|
|
122
|
+
agent_type="review",
|
|
123
|
+
),
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
result = agent._post_process_plan(plan, registry)
|
|
127
|
+
assert len(result.entries) == 1
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
class TestGoDepReviewAgentDelegationHooks:
|
|
131
|
+
"""Verify GitHubGoDepReviewAgent delegation hooks forward to cicaddy core."""
|
|
132
|
+
|
|
133
|
+
def test_get_agent_type_returns_review(self):
|
|
134
|
+
agent = _make_dep_review_agent()
|
|
135
|
+
assert agent._get_agent_type() == "review"
|
|
136
|
+
|
|
137
|
+
def test_get_delegation_context_extracts_diff(self):
|
|
138
|
+
agent = _make_dep_review_agent()
|
|
139
|
+
context = {
|
|
140
|
+
"diff": ("diff --git a/go.mod b/go.mod\n+require example.com/pkg v1.2.0\n"),
|
|
141
|
+
"diff_lines": 2,
|
|
142
|
+
"analysis_type": "go_dependency_review",
|
|
143
|
+
}
|
|
144
|
+
result = agent._get_delegation_context(context)
|
|
145
|
+
assert result["changed_files"] == ["go.mod"]
|
|
146
|
+
assert result["analysis_type"] == "go_dependency_review"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{cicaddy_github-0.5.0 → cicaddy_github-0.6.0}/src/cicaddy_github/github_integration/__init__.py
RENAMED
|
File without changes
|
{cicaddy_github-0.5.0 → cicaddy_github-0.6.0}/src/cicaddy_github/github_integration/analyzer.py
RENAMED
|
File without changes
|
{cicaddy_github-0.5.0 → cicaddy_github-0.6.0}/src/cicaddy_github/github_integration/detector.py
RENAMED
|
File without changes
|
|
File without changes
|
{cicaddy_github-0.5.0 → cicaddy_github-0.6.0}/src/cicaddy_github/github_integration/tools.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|