cicaddy-github 0.3.0__tar.gz → 0.3.2__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.
Files changed (43) hide show
  1. {cicaddy_github-0.3.0 → cicaddy_github-0.3.2}/.claude/skills/cicaddy-action/SKILL.md +6 -2
  2. {cicaddy_github-0.3.0 → cicaddy_github-0.3.2}/.github/workflows/pr-review.yml +22 -4
  3. {cicaddy_github-0.3.0 → cicaddy_github-0.3.2}/CLAUDE.md +10 -0
  4. {cicaddy_github-0.3.0 → cicaddy_github-0.3.2}/Dockerfile +1 -0
  5. {cicaddy_github-0.3.0 → cicaddy_github-0.3.2}/PKG-INFO +26 -22
  6. {cicaddy_github-0.3.0 → cicaddy_github-0.3.2}/README.md +24 -20
  7. {cicaddy_github-0.3.0 → cicaddy_github-0.3.2}/entrypoint.sh +16 -1
  8. {cicaddy_github-0.3.0 → cicaddy_github-0.3.2}/pyproject.toml +2 -2
  9. {cicaddy_github-0.3.0 → cicaddy_github-0.3.2}/src/cicaddy_github/github_integration/detector.py +1 -1
  10. {cicaddy_github-0.3.0 → cicaddy_github-0.3.2}/tests/unit/test_detector.py +10 -0
  11. {cicaddy_github-0.3.0 → cicaddy_github-0.3.2}/.github/dependabot.yml +0 -0
  12. {cicaddy_github-0.3.0 → cicaddy_github-0.3.2}/.github/workflows/changelog.yml +0 -0
  13. {cicaddy_github-0.3.0 → cicaddy_github-0.3.2}/.github/workflows/ci.yml +0 -0
  14. {cicaddy_github-0.3.0 → cicaddy_github-0.3.2}/.github/workflows/release.yml +0 -0
  15. {cicaddy_github-0.3.0 → cicaddy_github-0.3.2}/.gitignore +0 -0
  16. {cicaddy_github-0.3.0 → cicaddy_github-0.3.2}/.pre-commit-config.yaml +0 -0
  17. {cicaddy_github-0.3.0 → cicaddy_github-0.3.2}/CODE_OF_CONDUCT.md +0 -0
  18. {cicaddy_github-0.3.0 → cicaddy_github-0.3.2}/CONTRIBUTING.md +0 -0
  19. {cicaddy_github-0.3.0 → cicaddy_github-0.3.2}/LICENSE +0 -0
  20. {cicaddy_github-0.3.0 → cicaddy_github-0.3.2}/action.yml +0 -0
  21. {cicaddy_github-0.3.0 → cicaddy_github-0.3.2}/src/cicaddy_github/__init__.py +0 -0
  22. {cicaddy_github-0.3.0 → cicaddy_github-0.3.2}/src/cicaddy_github/config/__init__.py +0 -0
  23. {cicaddy_github-0.3.0 → cicaddy_github-0.3.2}/src/cicaddy_github/config/settings.py +0 -0
  24. {cicaddy_github-0.3.0 → cicaddy_github-0.3.2}/src/cicaddy_github/github_integration/__init__.py +0 -0
  25. {cicaddy_github-0.3.0 → cicaddy_github-0.3.2}/src/cicaddy_github/github_integration/agents.py +0 -0
  26. {cicaddy_github-0.3.0 → cicaddy_github-0.3.2}/src/cicaddy_github/github_integration/analyzer.py +0 -0
  27. {cicaddy_github-0.3.0 → cicaddy_github-0.3.2}/src/cicaddy_github/github_integration/tools.py +0 -0
  28. {cicaddy_github-0.3.0 → cicaddy_github-0.3.2}/src/cicaddy_github/plugin.py +0 -0
  29. {cicaddy_github-0.3.0 → cicaddy_github-0.3.2}/src/cicaddy_github/security/__init__.py +0 -0
  30. {cicaddy_github-0.3.0 → cicaddy_github-0.3.2}/src/cicaddy_github/security/leak_detector.py +0 -0
  31. {cicaddy_github-0.3.0 → cicaddy_github-0.3.2}/src/cicaddy_github/validation.py +0 -0
  32. {cicaddy_github-0.3.0 → cicaddy_github-0.3.2}/tasks/changelog_report.yml +0 -0
  33. {cicaddy_github-0.3.0 → cicaddy_github-0.3.2}/tasks/pr_review.yml +0 -0
  34. {cicaddy_github-0.3.0 → cicaddy_github-0.3.2}/templates/report_template.html +0 -0
  35. {cicaddy_github-0.3.0 → cicaddy_github-0.3.2}/tests/__init__.py +0 -0
  36. {cicaddy_github-0.3.0 → cicaddy_github-0.3.2}/tests/conftest.py +0 -0
  37. {cicaddy_github-0.3.0 → cicaddy_github-0.3.2}/tests/unit/__init__.py +0 -0
  38. {cicaddy_github-0.3.0 → cicaddy_github-0.3.2}/tests/unit/test_agents.py +0 -0
  39. {cicaddy_github-0.3.0 → cicaddy_github-0.3.2}/tests/unit/test_analyzer.py +0 -0
  40. {cicaddy_github-0.3.0 → cicaddy_github-0.3.2}/tests/unit/test_leak_detector.py +0 -0
  41. {cicaddy_github-0.3.0 → cicaddy_github-0.3.2}/tests/unit/test_plugin.py +0 -0
  42. {cicaddy_github-0.3.0 → cicaddy_github-0.3.2}/tests/unit/test_settings.py +0 -0
  43. {cicaddy_github-0.3.0 → cicaddy_github-0.3.2}/tests/unit/test_tools.py +0 -0
@@ -219,15 +219,19 @@ context: |
219
219
 
220
220
  ## Workflow Usage
221
221
 
222
+ The PR review workflow uses `pull_request_target` so secrets are available for
223
+ fork PRs. Internal PRs run automatically; fork PRs require a maintainer to add
224
+ the `safe-to-review` label. The label is auto-removed on new pushes to prevent
225
+ TOCTOU bypasses.
226
+
222
227
  ```yaml
223
- - uses: redhat-community-ai-tools/cicaddy-action@v0
228
+ - uses: redhat-community-ai-tools/cicaddy-action@v0.3.2
224
229
  with:
225
230
  ai_provider: gemini
226
231
  ai_model: gemini-3-flash-preview
227
232
  ai_api_key: ${{ secrets.AI_API_KEY }}
228
233
  task_file: tasks/pr_review.yml
229
234
  post_pr_comment: 'true'
230
- github_token: ${{ secrets.GITHUB_TOKEN }}
231
235
  ```
232
236
 
233
237
  ## Running Locally
@@ -1,16 +1,35 @@
1
1
  name: AI PR Review
2
2
 
3
3
  on:
4
- pull_request:
5
- types: [opened, synchronize]
4
+ pull_request_target:
5
+ types: [opened, synchronize, labeled]
6
6
 
7
7
  permissions:
8
8
  contents: read
9
9
  pull-requests: write
10
10
 
11
11
  jobs:
12
+ remove-label-on-push:
13
+ if: >-
14
+ github.event.action == 'synchronize' &&
15
+ github.event.pull_request.head.repo.full_name != github.repository &&
16
+ contains(github.event.pull_request.labels.*.name, 'safe-to-review')
17
+ runs-on: ubuntu-latest
18
+ permissions:
19
+ pull-requests: write
20
+ steps:
21
+ - name: Remove safe-to-review label on new push from fork
22
+ env:
23
+ GH_TOKEN: ${{ github.token }}
24
+ run: gh pr edit "${{ github.event.pull_request.number }}" --repo "${{ github.repository }}" --remove-label "safe-to-review"
25
+
12
26
  review:
13
- if: ${{ github.actor != 'dependabot[bot]' }}
27
+ if: >-
28
+ github.actor != 'dependabot[bot]' &&
29
+ (
30
+ (github.event.pull_request.head.repo.full_name == github.repository && github.event.action != 'labeled') ||
31
+ (github.event.action == 'labeled' && github.event.label.name == 'safe-to-review')
32
+ )
14
33
  runs-on: ubuntu-latest
15
34
  steps:
16
35
  - uses: actions/checkout@v6
@@ -38,7 +57,6 @@ jobs:
38
57
  ai_api_key: ${{ secrets.AI_API_KEY }}
39
58
  task_file: tasks/pr_review.yml
40
59
  post_pr_comment: 'true'
41
- github_token: ${{ secrets.GITHUB_TOKEN }}
42
60
  mcp_servers_config: ${{ steps.mcp.outputs.config }}
43
61
  env:
44
62
  ANALYSIS_FOCUS: "general"
@@ -27,5 +27,15 @@ GitHub Action that wraps cicaddy for running AI agent tasks in GitHub Actions wo
27
27
  - Test files in `tests/unit/`
28
28
  - Fixtures in `tests/conftest.py`
29
29
 
30
+ ## Release Checklist
31
+ - **Bump `version` in `pyproject.toml` BEFORE tagging** — the release workflow builds from the checked-out source, so the `pyproject.toml` version must match the git tag. If the version doesn't match, PyPI will reject the upload (either as a duplicate or a mismatch).
32
+ - When bumping the version for a release, also update all `cicaddy-action@vX.Y.Z` version references in `README.md` and `.claude/skills/cicaddy-action/SKILL.md` to match the new version.
33
+
34
+ ## PR Review Workflow Security
35
+ - The PR review workflow uses `pull_request_target` so secrets are available for fork PRs.
36
+ - Internal PRs (same repo) run automatically; fork PRs require the `safe-to-review` label.
37
+ - The label is auto-removed on `synchronize` (new pushes from forks) to prevent TOCTOU bypasses.
38
+ - The workflow never checks out or executes untrusted PR code — cicaddy fetches the diff via the GitHub API.
39
+
30
40
  ## Reference Repos
31
41
  - [cicaddy core](https://github.com/waynesun09/cicaddy)
@@ -11,6 +11,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends git && \
11
11
 
12
12
  COPY pyproject.toml README.md LICENSE ./
13
13
  COPY src ./src
14
+ COPY tasks ./tasks
14
15
  COPY entrypoint.sh ./
15
16
 
16
17
  RUN uv pip install --system --no-cache . && \
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cicaddy-github
3
- Version: 0.3.0
3
+ Version: 0.3.2
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.3.0
12
+ Requires-Dist: cicaddy>=0.3.0
13
13
  Requires-Dist: detect-secrets>=1.4.0
14
14
  Requires-Dist: pygithub>=2.1.0
15
15
  Provides-Extra: test
@@ -32,59 +32,63 @@ GitHub Action that wraps [cicaddy](https://github.com/waynesun09/cicaddy) for ru
32
32
 
33
33
  ## Quick Start
34
34
 
35
- ### Changelog Report on Release
35
+ ### AI PR Review
36
+
37
+ This example uses the `pull_request` trigger, which works for in-repo PRs
38
+ (branches pushed to the same repository). For fork PR support, see
39
+ `.github/workflows/pr-review.yml` which uses `pull_request_target` with
40
+ a `safe-to-review` label gate.
36
41
 
37
42
  ```yaml
38
- name: Generate Changelog
43
+ name: PR Review
39
44
 
40
45
  on:
41
- release:
42
- types: [published]
46
+ pull_request:
47
+ types: [opened, synchronize]
48
+
49
+ permissions:
50
+ pull-requests: write
43
51
 
44
52
  jobs:
45
- changelog:
53
+ review:
46
54
  runs-on: ubuntu-latest
47
55
  steps:
48
56
  - uses: actions/checkout@v4
49
57
  with:
50
58
  fetch-depth: 0
51
59
 
52
- - uses: redhat-community-ai-tools/cicaddy-action@v0
60
+ - uses: redhat-community-ai-tools/cicaddy-action@v0.3.2
53
61
  with:
54
62
  ai_provider: gemini
55
- ai_model: gemini-2.5-flash
63
+ ai_model: gemini-3-flash-preview
56
64
  ai_api_key: ${{ secrets.AI_API_KEY }}
57
- task_file: tasks/changelog_report.yml
65
+ task_file: tasks/pr_review.yml
66
+ post_pr_comment: 'true'
58
67
  ```
59
68
 
60
- ### AI PR Review
69
+ ### Changelog Report on Release
61
70
 
62
71
  ```yaml
63
- name: PR Review
72
+ name: Generate Changelog
64
73
 
65
74
  on:
66
- pull_request:
67
- types: [opened, synchronize]
68
-
69
- permissions:
70
- pull-requests: write
75
+ release:
76
+ types: [published]
71
77
 
72
78
  jobs:
73
- review:
79
+ changelog:
74
80
  runs-on: ubuntu-latest
75
81
  steps:
76
82
  - uses: actions/checkout@v4
77
83
  with:
78
84
  fetch-depth: 0
79
85
 
80
- - uses: redhat-community-ai-tools/cicaddy-action@v0
86
+ - uses: redhat-community-ai-tools/cicaddy-action@v0.3.2
81
87
  with:
82
88
  ai_provider: gemini
83
89
  ai_model: gemini-3-flash-preview
84
90
  ai_api_key: ${{ secrets.AI_API_KEY }}
85
- task_file: tasks/pr_review.yml
86
- post_pr_comment: 'true'
87
- github_token: ${{ secrets.GITHUB_TOKEN }}
91
+ task_file: tasks/changelog_report.yml
88
92
  ```
89
93
 
90
94
  ## Inputs
@@ -12,59 +12,63 @@ GitHub Action that wraps [cicaddy](https://github.com/waynesun09/cicaddy) for ru
12
12
 
13
13
  ## Quick Start
14
14
 
15
- ### Changelog Report on Release
15
+ ### AI PR Review
16
+
17
+ This example uses the `pull_request` trigger, which works for in-repo PRs
18
+ (branches pushed to the same repository). For fork PR support, see
19
+ `.github/workflows/pr-review.yml` which uses `pull_request_target` with
20
+ a `safe-to-review` label gate.
16
21
 
17
22
  ```yaml
18
- name: Generate Changelog
23
+ name: PR Review
19
24
 
20
25
  on:
21
- release:
22
- types: [published]
26
+ pull_request:
27
+ types: [opened, synchronize]
28
+
29
+ permissions:
30
+ pull-requests: write
23
31
 
24
32
  jobs:
25
- changelog:
33
+ review:
26
34
  runs-on: ubuntu-latest
27
35
  steps:
28
36
  - uses: actions/checkout@v4
29
37
  with:
30
38
  fetch-depth: 0
31
39
 
32
- - uses: redhat-community-ai-tools/cicaddy-action@v0
40
+ - uses: redhat-community-ai-tools/cicaddy-action@v0.3.2
33
41
  with:
34
42
  ai_provider: gemini
35
- ai_model: gemini-2.5-flash
43
+ ai_model: gemini-3-flash-preview
36
44
  ai_api_key: ${{ secrets.AI_API_KEY }}
37
- task_file: tasks/changelog_report.yml
45
+ task_file: tasks/pr_review.yml
46
+ post_pr_comment: 'true'
38
47
  ```
39
48
 
40
- ### AI PR Review
49
+ ### Changelog Report on Release
41
50
 
42
51
  ```yaml
43
- name: PR Review
52
+ name: Generate Changelog
44
53
 
45
54
  on:
46
- pull_request:
47
- types: [opened, synchronize]
48
-
49
- permissions:
50
- pull-requests: write
55
+ release:
56
+ types: [published]
51
57
 
52
58
  jobs:
53
- review:
59
+ changelog:
54
60
  runs-on: ubuntu-latest
55
61
  steps:
56
62
  - uses: actions/checkout@v4
57
63
  with:
58
64
  fetch-depth: 0
59
65
 
60
- - uses: redhat-community-ai-tools/cicaddy-action@v0
66
+ - uses: redhat-community-ai-tools/cicaddy-action@v0.3.2
61
67
  with:
62
68
  ai_provider: gemini
63
69
  ai_model: gemini-3-flash-preview
64
70
  ai_api_key: ${{ secrets.AI_API_KEY }}
65
- task_file: tasks/pr_review.yml
66
- post_pr_comment: 'true'
67
- github_token: ${{ secrets.GITHUB_TOKEN }}
71
+ task_file: tasks/changelog_report.yml
68
72
  ```
69
73
 
70
74
  ## Inputs
@@ -36,7 +36,15 @@ _to_abs() {
36
36
  }
37
37
 
38
38
  if [[ -n "${INPUT_TASK_FILE}" ]]; then
39
- export AI_TASK_FILE="$(_to_abs "${INPUT_TASK_FILE}")"
39
+ _ws_path="$(_to_abs "${INPUT_TASK_FILE}")"
40
+ if [[ -f "${_ws_path}" ]]; then
41
+ export AI_TASK_FILE="${_ws_path}"
42
+ elif [[ -f "/app/${INPUT_TASK_FILE}" ]]; then
43
+ # Fall back to bundled task files shipped with the action
44
+ export AI_TASK_FILE="/app/${INPUT_TASK_FILE}"
45
+ else
46
+ export AI_TASK_FILE="${_ws_path}"
47
+ fi
40
48
  fi
41
49
  export AI_TASK_PROMPT="${INPUT_TASK_PROMPT}"
42
50
  if [[ -n "${INPUT_REPORT_TEMPLATE}" ]]; then
@@ -50,6 +58,13 @@ export POST_PR_COMMENT="${INPUT_POST_PR_COMMENT:-false}"
50
58
  # Extract PR number from GITHUB_REF (e.g. refs/pull/123/merge -> 123)
51
59
  if [[ "${GITHUB_REF}" =~ ^refs/pull/([0-9]+)/ ]]; then
52
60
  export GITHUB_PR_NUMBER="${BASH_REMATCH[1]}"
61
+ elif [[ -n "${GITHUB_EVENT_PATH}" && -f "${GITHUB_EVENT_PATH}" ]]; then
62
+ # For pull_request_target, GITHUB_REF is the base branch, not refs/pull/N/merge.
63
+ # Extract PR number from the event payload JSON instead.
64
+ PR_NUM=$(python3 -c "import json,sys; e=json.load(open(sys.argv[1])); print(e.get('pull_request',{}).get('number',''))" "${GITHUB_EVENT_PATH}" 2>/dev/null || true)
65
+ if [[ -n "${PR_NUM}" ]]; then
66
+ export GITHUB_PR_NUMBER="${PR_NUM}"
67
+ fi
53
68
  fi
54
69
 
55
70
  # Enable local tools (git operations) and set working directory
@@ -4,14 +4,14 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "cicaddy-github"
7
- version = "0.3.0"
7
+ version = "0.3.2"
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.3.0",
14
+ "cicaddy>=0.3.0",
15
15
  "PyGithub>=2.1.0",
16
16
  "detect-secrets>=1.4.0",
17
17
  ]
@@ -10,7 +10,7 @@ logger = get_logger(__name__)
10
10
  def _detect_github_agent_type(settings) -> str | None:
11
11
  """Detect GitHub-specific agent types from Actions environment variables."""
12
12
  event = os.getenv("GITHUB_EVENT_NAME")
13
- if event == "pull_request":
13
+ if event in ("pull_request", "pull_request_target"):
14
14
  logger.info(f"Detected pull request context: GITHUB_EVENT_NAME={event}")
15
15
  return "github_pr"
16
16
 
@@ -17,6 +17,16 @@ class TestDetectGitHubAgentType:
17
17
  result = _detect_github_agent_type(settings)
18
18
  assert result == "github_pr"
19
19
 
20
+ def test_pull_request_target_event_returns_github_pr(self):
21
+ """GITHUB_EVENT_NAME=pull_request_target returns github_pr."""
22
+ from cicaddy_github.github_integration.detector import _detect_github_agent_type
23
+
24
+ settings = MagicMock()
25
+ settings.github_pr_number = None
26
+ with patch.dict(os.environ, {"GITHUB_EVENT_NAME": "pull_request_target"}):
27
+ result = _detect_github_agent_type(settings)
28
+ assert result == "github_pr"
29
+
20
30
  def test_push_event_returns_none(self):
21
31
  """GITHUB_EVENT_NAME=push returns None (falls through to TaskAgent)."""
22
32
  from cicaddy_github.github_integration.detector import _detect_github_agent_type
File without changes