cicaddy-github 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.
- cicaddy_github-0.1.0/.claude/skills/cicaddy-action/SKILL.md +312 -0
- cicaddy_github-0.1.0/.github/dependabot.yml +24 -0
- cicaddy_github-0.1.0/.github/workflows/changelog.yml +66 -0
- cicaddy_github-0.1.0/.github/workflows/ci.yml +59 -0
- cicaddy_github-0.1.0/.github/workflows/pr-review.yml +45 -0
- cicaddy_github-0.1.0/.github/workflows/release.yml +101 -0
- cicaddy_github-0.1.0/.gitignore +39 -0
- cicaddy_github-0.1.0/.pre-commit-config.yaml +56 -0
- cicaddy_github-0.1.0/CLAUDE.md +31 -0
- cicaddy_github-0.1.0/CODE_OF_CONDUCT.md +37 -0
- cicaddy_github-0.1.0/CONTRIBUTING.md +57 -0
- cicaddy_github-0.1.0/Dockerfile +27 -0
- cicaddy_github-0.1.0/LICENSE +190 -0
- cicaddy_github-0.1.0/PKG-INFO +220 -0
- cicaddy_github-0.1.0/README.md +200 -0
- cicaddy_github-0.1.0/action.yml +54 -0
- cicaddy_github-0.1.0/entrypoint.sh +68 -0
- cicaddy_github-0.1.0/pyproject.toml +62 -0
- cicaddy_github-0.1.0/src/cicaddy_github/__init__.py +3 -0
- cicaddy_github-0.1.0/src/cicaddy_github/config/__init__.py +0 -0
- cicaddy_github-0.1.0/src/cicaddy_github/config/settings.py +193 -0
- cicaddy_github-0.1.0/src/cicaddy_github/github_integration/__init__.py +0 -0
- cicaddy_github-0.1.0/src/cicaddy_github/github_integration/agents.py +268 -0
- cicaddy_github-0.1.0/src/cicaddy_github/github_integration/analyzer.py +281 -0
- cicaddy_github-0.1.0/src/cicaddy_github/github_integration/detector.py +23 -0
- cicaddy_github-0.1.0/src/cicaddy_github/github_integration/tools.py +136 -0
- cicaddy_github-0.1.0/src/cicaddy_github/plugin.py +107 -0
- cicaddy_github-0.1.0/src/cicaddy_github/security/__init__.py +0 -0
- cicaddy_github-0.1.0/src/cicaddy_github/security/leak_detector.py +104 -0
- cicaddy_github-0.1.0/src/cicaddy_github/validation.py +18 -0
- cicaddy_github-0.1.0/tasks/changelog_report.yml +70 -0
- cicaddy_github-0.1.0/tasks/pr_review.yml +91 -0
- cicaddy_github-0.1.0/templates/report_template.html +286 -0
- cicaddy_github-0.1.0/tests/__init__.py +0 -0
- cicaddy_github-0.1.0/tests/conftest.py +42 -0
- cicaddy_github-0.1.0/tests/unit/__init__.py +0 -0
- cicaddy_github-0.1.0/tests/unit/test_analyzer.py +321 -0
- cicaddy_github-0.1.0/tests/unit/test_detector.py +69 -0
- cicaddy_github-0.1.0/tests/unit/test_leak_detector.py +59 -0
- cicaddy_github-0.1.0/tests/unit/test_plugin.py +139 -0
- cicaddy_github-0.1.0/tests/unit/test_settings.py +176 -0
- cicaddy_github-0.1.0/tests/unit/test_tools.py +138 -0
|
@@ -0,0 +1,312 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: cicaddy-action
|
|
3
|
+
description: >
|
|
4
|
+
Use this skill when working with cicaddy-action, the GitHub Action that wraps
|
|
5
|
+
cicaddy for running AI agent tasks in GitHub Actions workflows. Covers the
|
|
6
|
+
action inputs, Docker entrypoint, plugin architecture, task definitions, and
|
|
7
|
+
local development.
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# cicaddy-action
|
|
11
|
+
|
|
12
|
+
GitHub Action that wraps [cicaddy](https://github.com/waynesun09/cicaddy)
|
|
13
|
+
for running AI agent tasks in GitHub Actions workflows. The `cicaddy-github`
|
|
14
|
+
plugin extends cicaddy with GitHub-specific agents, tools, and configuration.
|
|
15
|
+
|
|
16
|
+
## Working Directory
|
|
17
|
+
|
|
18
|
+
- **Repository root**: `cicaddy-action/` (project root)
|
|
19
|
+
- **Plugin source**: `src/cicaddy_github/`
|
|
20
|
+
- **Task definitions**: `tasks/`
|
|
21
|
+
- **GitHub workflows**: `.github/workflows/`
|
|
22
|
+
- **Docker files**: `Dockerfile`, `entrypoint.sh`
|
|
23
|
+
- **Action definition**: `action.yml`
|
|
24
|
+
|
|
25
|
+
## Project Structure
|
|
26
|
+
|
|
27
|
+
```
|
|
28
|
+
cicaddy-action/
|
|
29
|
+
action.yml # GitHub Action definition (inputs/outputs)
|
|
30
|
+
Dockerfile # Container image (python:3.12-slim + uv)
|
|
31
|
+
entrypoint.sh # Maps GitHub Action inputs to cicaddy env vars
|
|
32
|
+
pyproject.toml # Package config (cicaddy-github plugin)
|
|
33
|
+
tasks/
|
|
34
|
+
pr_review.yml # DSPy task for PR code review
|
|
35
|
+
changelog_report.yml # DSPy task for changelog generation
|
|
36
|
+
src/cicaddy_github/
|
|
37
|
+
plugin.py # Entry points: register_agents, get_cli_args, etc.
|
|
38
|
+
config/settings.py # Settings class extending CoreSettings
|
|
39
|
+
github_integration/
|
|
40
|
+
agents.py # GitHubPRAgent, GitHubTaskAgent
|
|
41
|
+
analyzer.py # PyGithub wrapper (diff, PR data, comments)
|
|
42
|
+
detector.py # Auto-detect agent type from GitHub env
|
|
43
|
+
tools.py # Git operations (@tool decorated)
|
|
44
|
+
security/
|
|
45
|
+
leak_detector.py # Secret redaction via detect-secrets
|
|
46
|
+
.github/workflows/
|
|
47
|
+
ci.yml # Lint, test (3.11-3.13), docker build
|
|
48
|
+
pr-review.yml # AI code review on PRs (uses ./action)
|
|
49
|
+
changelog.yml # Changelog report on releases
|
|
50
|
+
release.yml # PyPI publish
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Key Commands
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
# Install with test dependencies
|
|
57
|
+
uv pip install -e ".[test]"
|
|
58
|
+
|
|
59
|
+
# Run tests with coverage
|
|
60
|
+
pytest tests/ -q --cov=src/cicaddy_github
|
|
61
|
+
|
|
62
|
+
# Run all linters (pre-commit)
|
|
63
|
+
pre-commit run --all-files
|
|
64
|
+
|
|
65
|
+
# Build Docker image
|
|
66
|
+
docker build -t cicaddy-action:test .
|
|
67
|
+
|
|
68
|
+
# Test Docker image
|
|
69
|
+
docker run --rm --entrypoint cicaddy cicaddy-action:test --version
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## GitHub Secrets
|
|
73
|
+
|
|
74
|
+
AI API keys must be configured in GitHub repository settings
|
|
75
|
+
(Settings > Secrets and variables > Actions). Two approaches work:
|
|
76
|
+
|
|
77
|
+
**Option 1: Generic secret via `ai_api_key` input (recommended)**
|
|
78
|
+
|
|
79
|
+
Set `AI_API_KEY` as a GitHub secret. The entrypoint maps it to the correct
|
|
80
|
+
provider-specific env var (`GEMINI_API_KEY`, `OPENAI_API_KEY`, or
|
|
81
|
+
`ANTHROPIC_API_KEY`) based on the `ai_provider` input.
|
|
82
|
+
|
|
83
|
+
```yaml
|
|
84
|
+
with:
|
|
85
|
+
ai_provider: gemini
|
|
86
|
+
ai_api_key: ${{ secrets.AI_API_KEY }}
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
**Option 2: Provider-specific secret via `env:`**
|
|
90
|
+
|
|
91
|
+
Set the provider-specific secret directly (e.g. `GEMINI_API_KEY`) and pass
|
|
92
|
+
it as an environment variable. Cicaddy reads these env vars directly.
|
|
93
|
+
|
|
94
|
+
```yaml
|
|
95
|
+
with:
|
|
96
|
+
ai_provider: gemini
|
|
97
|
+
env:
|
|
98
|
+
GEMINI_API_KEY: ${{ secrets.GEMINI_API_KEY }}
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
| Secret | Required | Description |
|
|
102
|
+
|--------|----------|-------------|
|
|
103
|
+
| `AI_API_KEY` | Yes* | Generic AI provider API key (used via `ai_api_key` input) |
|
|
104
|
+
| `GEMINI_API_KEY` | Yes* | Gemini API key (alternative, passed via `env:`) |
|
|
105
|
+
| `OPENAI_API_KEY` | Yes* | OpenAI API key (alternative, passed via `env:`) |
|
|
106
|
+
| `ANTHROPIC_API_KEY` | Yes* | Anthropic API key (alternative, passed via `env:`) |
|
|
107
|
+
| `CONTEXT7_API_KEY` | No | API key for Context7 MCP server (optional) |
|
|
108
|
+
|
|
109
|
+
*One of `AI_API_KEY` or the provider-specific key is required.
|
|
110
|
+
|
|
111
|
+
`GITHUB_TOKEN` is provided automatically by GitHub Actions.
|
|
112
|
+
|
|
113
|
+
## Action Inputs
|
|
114
|
+
|
|
115
|
+
All inputs use **underscores** (not hyphens) so GitHub Actions Docker containers
|
|
116
|
+
can reference them as bash variables (`INPUT_AI_PROVIDER`, `INPUT_AI_API_KEY`, etc.).
|
|
117
|
+
|
|
118
|
+
| Input | Required | Description |
|
|
119
|
+
|-------|----------|-------------|
|
|
120
|
+
| `ai_provider` | Yes | `gemini`, `openai`, `claude` |
|
|
121
|
+
| `ai_model` | Yes | Model identifier |
|
|
122
|
+
| `ai_api_key` | Yes* | AI provider API key (mapped to provider-specific env var) |
|
|
123
|
+
| `task_file` | No | Path to DSPy YAML task file |
|
|
124
|
+
| `task_prompt` | No | Inline task prompt |
|
|
125
|
+
| `post_pr_comment` | No | Post results as PR comment (default: `false`) |
|
|
126
|
+
| `github_token` | No | GitHub token (default: `${{ github.token }}`) |
|
|
127
|
+
| `mcp_servers_config` | No | JSON array of MCP server configs |
|
|
128
|
+
| `slack_webhook_url` | No | Slack webhook URL |
|
|
129
|
+
| `report_template` | No | Custom HTML report template path |
|
|
130
|
+
|
|
131
|
+
*Not required if provider-specific key is set via `env:`.
|
|
132
|
+
|
|
133
|
+
## Entrypoint Flow
|
|
134
|
+
|
|
135
|
+
`entrypoint.sh` bridges GitHub Action inputs to cicaddy environment:
|
|
136
|
+
|
|
137
|
+
1. Exports `AI_PROVIDER` and `AI_MODEL` from `INPUT_*` vars
|
|
138
|
+
2. Maps `INPUT_AI_API_KEY` to provider-specific env var (`GEMINI_API_KEY`, etc.)
|
|
139
|
+
3. Resolves `AI_TASK_FILE` and `REPORT_TEMPLATE` to absolute paths (required
|
|
140
|
+
because step 5 changes the working directory)
|
|
141
|
+
4. Extracts `GITHUB_PR_NUMBER` from `GITHUB_REF` (`refs/pull/<N>/merge`)
|
|
142
|
+
5. Creates `.cicaddy/` subdirectory and `cd`s into it (cicaddy writes reports
|
|
143
|
+
to `../` relative to cwd; this ensures `../` resolves to the writable workspace)
|
|
144
|
+
6. Runs `cicaddy run`
|
|
145
|
+
|
|
146
|
+
### Known Pitfalls
|
|
147
|
+
|
|
148
|
+
- **Relative paths break after `cd .cicaddy/`**: Any file path input (task file,
|
|
149
|
+
report template) must be resolved to an absolute path before the `cd`. The
|
|
150
|
+
entrypoint handles this with a `_to_abs` helper. If new file-path inputs are
|
|
151
|
+
added, they must also use this helper.
|
|
152
|
+
- **Secrets in workflow `run:` blocks**: Never use `${{ secrets.* }}` directly
|
|
153
|
+
in `run:` shell blocks. Pass secrets via `env:` to avoid literal interpolation
|
|
154
|
+
in logs. See `.github/workflows/pr-review.yml` for the correct pattern.
|
|
155
|
+
|
|
156
|
+
## Plugin Architecture
|
|
157
|
+
|
|
158
|
+
The `cicaddy-github` package registers with cicaddy via `pyproject.toml` entry points:
|
|
159
|
+
|
|
160
|
+
```toml
|
|
161
|
+
[project.entry-points."cicaddy.agents"]
|
|
162
|
+
github = "cicaddy_github.plugin:register_agents"
|
|
163
|
+
|
|
164
|
+
[project.entry-points."cicaddy.settings_loader"]
|
|
165
|
+
github = "cicaddy_github.config.settings:load_settings"
|
|
166
|
+
|
|
167
|
+
[project.entry-points."cicaddy.cli_args"]
|
|
168
|
+
github = "cicaddy_github.plugin:get_cli_args"
|
|
169
|
+
|
|
170
|
+
[project.entry-points."cicaddy.env_vars"]
|
|
171
|
+
github = "cicaddy_github.plugin:get_env_vars"
|
|
172
|
+
|
|
173
|
+
[project.entry-points."cicaddy.validators"]
|
|
174
|
+
github = "cicaddy_github.plugin:validate"
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
### Registered Agents
|
|
178
|
+
|
|
179
|
+
| Type | Class | Triggered by |
|
|
180
|
+
|------|-------|--------------|
|
|
181
|
+
| `github_pr` | `GitHubPRAgent` | `GITHUB_EVENT_NAME=pull_request` + `GITHUB_PR_NUMBER` |
|
|
182
|
+
| `github_task` | `GitHubTaskAgent` | `GITHUB_EVENT_NAME` present but not a PR |
|
|
183
|
+
|
|
184
|
+
### Settings
|
|
185
|
+
|
|
186
|
+
`Settings` extends `CoreSettings` with GitHub-specific fields:
|
|
187
|
+
|
|
188
|
+
- `github_token`, `github_repository`, `github_ref`, `github_event_name`
|
|
189
|
+
- `github_sha`, `github_run_id`, `github_pr_number`
|
|
190
|
+
- `post_pr_comment` (bool)
|
|
191
|
+
|
|
192
|
+
All loaded from environment variables via `load_settings()`.
|
|
193
|
+
|
|
194
|
+
## DSPy Task Files
|
|
195
|
+
|
|
196
|
+
Task YAML files define analysis prompts. Inputs use `{{VAR}}` placeholders
|
|
197
|
+
resolved from environment variables.
|
|
198
|
+
|
|
199
|
+
```yaml
|
|
200
|
+
name: pr_code_review
|
|
201
|
+
type: code_review
|
|
202
|
+
version: "1.0"
|
|
203
|
+
|
|
204
|
+
persona: >
|
|
205
|
+
expert code reviewer
|
|
206
|
+
|
|
207
|
+
tools:
|
|
208
|
+
servers:
|
|
209
|
+
- local
|
|
210
|
+
required_tools:
|
|
211
|
+
- read_file
|
|
212
|
+
- glob_files
|
|
213
|
+
|
|
214
|
+
output_format: markdown
|
|
215
|
+
|
|
216
|
+
context: |
|
|
217
|
+
Review the PR diff for the repository...
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
## Workflow Usage
|
|
221
|
+
|
|
222
|
+
```yaml
|
|
223
|
+
- uses: redhat-community-ai-tools/cicaddy-action@v0
|
|
224
|
+
with:
|
|
225
|
+
ai_provider: gemini
|
|
226
|
+
ai_model: gemini-3-flash-preview
|
|
227
|
+
ai_api_key: ${{ secrets.AI_API_KEY }}
|
|
228
|
+
task_file: tasks/pr_review.yml
|
|
229
|
+
post_pr_comment: 'true'
|
|
230
|
+
github_token: ${{ secrets.GITHUB_TOKEN }}
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
## Running Locally
|
|
234
|
+
|
|
235
|
+
Cicaddy can run locally to review PRs without GitHub Actions. Create an env
|
|
236
|
+
file and use `uv run cicaddy run --env-file <file>`.
|
|
237
|
+
|
|
238
|
+
### Env File Template (PR Review)
|
|
239
|
+
|
|
240
|
+
```bash
|
|
241
|
+
# AI Provider
|
|
242
|
+
AI_PROVIDER=gemini
|
|
243
|
+
AI_MODEL=gemini-3-flash-preview
|
|
244
|
+
GEMINI_API_KEY=<key>
|
|
245
|
+
|
|
246
|
+
# GitHub Configuration
|
|
247
|
+
GITHUB_TOKEN=<token> # gh auth token
|
|
248
|
+
GITHUB_REPOSITORY=owner/repo
|
|
249
|
+
GITHUB_EVENT_NAME=pull_request
|
|
250
|
+
GITHUB_PR_NUMBER=42
|
|
251
|
+
|
|
252
|
+
# Agent Settings
|
|
253
|
+
POST_PR_COMMENT=true
|
|
254
|
+
ENABLE_LOCAL_TOOLS=true
|
|
255
|
+
LOCAL_TOOLS_WORKING_DIR=.
|
|
256
|
+
|
|
257
|
+
# Optional: MCP servers
|
|
258
|
+
MCP_SERVERS_CONFIG=[{"name": "context7", "protocol": "http", "endpoint": "https://mcp.context7.com/mcp", "headers": {"CONTEXT7_API_KEY": "<key>"}}]
|
|
259
|
+
|
|
260
|
+
LOG_LEVEL=INFO
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
### Key Commands
|
|
264
|
+
|
|
265
|
+
```bash
|
|
266
|
+
# Install plugin in editable mode (uses live code)
|
|
267
|
+
uv pip install -e ".[test]"
|
|
268
|
+
|
|
269
|
+
# Run a PR review
|
|
270
|
+
uv run cicaddy run --env-file .env.my-review
|
|
271
|
+
|
|
272
|
+
# Validate configuration
|
|
273
|
+
uv run cicaddy validate --env-file .env.my-review
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
### Agent Type Detection
|
|
277
|
+
|
|
278
|
+
The agent type is auto-detected by `_detect_github_agent_type` in
|
|
279
|
+
`src/cicaddy_github/github_integration/detector.py` (registered at priority 40):
|
|
280
|
+
- `GITHUB_EVENT_NAME=pull_request` → `github_pr`
|
|
281
|
+
- `GITHUB_PR_NUMBER` set (fallback) → `github_pr`
|
|
282
|
+
- Otherwise → falls through to core detectors
|
|
283
|
+
|
|
284
|
+
### Additional Env Vars
|
|
285
|
+
|
|
286
|
+
- `AI_TASK_FILE`: Path to DSPy YAML task file for custom workflows
|
|
287
|
+
- `GIT_DIFF_CONTEXT_LINES`: Number of context lines in diffs (default: 10)
|
|
288
|
+
|
|
289
|
+
### MCP Server Config Format
|
|
290
|
+
|
|
291
|
+
JSON array. Each server object has:
|
|
292
|
+
- `name` (string): Server identifier
|
|
293
|
+
- `protocol` (string): `http`, `sse`, `stdio`, or `websocket`
|
|
294
|
+
- `endpoint` (string): Server URL
|
|
295
|
+
- `headers` (object, optional): HTTP headers (e.g. API keys)
|
|
296
|
+
|
|
297
|
+
### Notes
|
|
298
|
+
|
|
299
|
+
- **Never commit env files with secrets.** Use `.env.*` pattern (already in `.gitignore`)
|
|
300
|
+
- `POST_PR_COMMENT=true` requires a token with write access to pull requests
|
|
301
|
+
(`repo` scope includes this; for fine-grained tokens, enable "Pull requests: Write")
|
|
302
|
+
- The `github_pr` agent updates its PR comment in-place on re-runs
|
|
303
|
+
- Use `gh auth token` to generate a GitHub token quickly
|
|
304
|
+
|
|
305
|
+
## Code Style
|
|
306
|
+
|
|
307
|
+
- Python 3.11+ with type hints
|
|
308
|
+
- Ruff for linting and formatting (line-length 100)
|
|
309
|
+
- Google-style docstrings
|
|
310
|
+
- Async methods for I/O operations
|
|
311
|
+
- `@tool` decorator for local tool definitions
|
|
312
|
+
- pytest with pytest-asyncio for testing
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
version: 2
|
|
2
|
+
updates:
|
|
3
|
+
- package-ecosystem: "uv"
|
|
4
|
+
directory: "/"
|
|
5
|
+
schedule:
|
|
6
|
+
interval: "weekly"
|
|
7
|
+
groups:
|
|
8
|
+
python-dependencies:
|
|
9
|
+
patterns:
|
|
10
|
+
- "*"
|
|
11
|
+
|
|
12
|
+
- package-ecosystem: "github-actions"
|
|
13
|
+
directory: "/"
|
|
14
|
+
schedule:
|
|
15
|
+
interval: "weekly"
|
|
16
|
+
groups:
|
|
17
|
+
github-actions:
|
|
18
|
+
patterns:
|
|
19
|
+
- "*"
|
|
20
|
+
|
|
21
|
+
- package-ecosystem: "docker"
|
|
22
|
+
directory: "/"
|
|
23
|
+
schedule:
|
|
24
|
+
interval: "weekly"
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
name: Generate Changelog Report
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
release:
|
|
5
|
+
types: [published]
|
|
6
|
+
workflow_dispatch:
|
|
7
|
+
inputs:
|
|
8
|
+
from_tag:
|
|
9
|
+
description: 'Start tag'
|
|
10
|
+
required: false
|
|
11
|
+
to_tag:
|
|
12
|
+
description: 'End tag (default: latest)'
|
|
13
|
+
required: false
|
|
14
|
+
|
|
15
|
+
permissions:
|
|
16
|
+
contents: read
|
|
17
|
+
pages: write
|
|
18
|
+
id-token: write
|
|
19
|
+
|
|
20
|
+
jobs:
|
|
21
|
+
generate:
|
|
22
|
+
runs-on: ubuntu-latest
|
|
23
|
+
steps:
|
|
24
|
+
- uses: actions/checkout@v6
|
|
25
|
+
with:
|
|
26
|
+
fetch-depth: 0
|
|
27
|
+
|
|
28
|
+
- name: Generate Report
|
|
29
|
+
uses: ./
|
|
30
|
+
id: report
|
|
31
|
+
with:
|
|
32
|
+
ai_provider: gemini
|
|
33
|
+
ai_model: gemini-2.5-flash
|
|
34
|
+
ai_api_key: ${{ secrets.AI_API_KEY }}
|
|
35
|
+
task_file: tasks/changelog_report.yml
|
|
36
|
+
env:
|
|
37
|
+
FROM_TAG: ${{ inputs.from_tag || '' }}
|
|
38
|
+
TO_TAG: ${{ inputs.to_tag || github.event.release.tag_name || 'HEAD' }}
|
|
39
|
+
REPORT_TITLE: "Cicaddy Action — Release Update"
|
|
40
|
+
|
|
41
|
+
- name: Upload report artifact
|
|
42
|
+
uses: actions/upload-artifact@v7
|
|
43
|
+
with:
|
|
44
|
+
name: changelog-report
|
|
45
|
+
path: ${{ steps.report.outputs.report_html }}
|
|
46
|
+
|
|
47
|
+
- name: Prepare Pages
|
|
48
|
+
run: |
|
|
49
|
+
mkdir -p _site
|
|
50
|
+
cp "${{ steps.report.outputs.report_html }}" _site/index.html
|
|
51
|
+
|
|
52
|
+
- name: Upload Pages artifact
|
|
53
|
+
uses: actions/upload-pages-artifact@v4
|
|
54
|
+
with:
|
|
55
|
+
path: _site
|
|
56
|
+
|
|
57
|
+
deploy:
|
|
58
|
+
needs: generate
|
|
59
|
+
runs-on: ubuntu-latest
|
|
60
|
+
environment:
|
|
61
|
+
name: github-pages
|
|
62
|
+
url: ${{ steps.deployment.outputs.page_url }}
|
|
63
|
+
steps:
|
|
64
|
+
- name: Deploy to GitHub Pages
|
|
65
|
+
id: deployment
|
|
66
|
+
uses: actions/deploy-pages@v4
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
|
|
9
|
+
permissions:
|
|
10
|
+
contents: read
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
lint:
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
steps:
|
|
16
|
+
- uses: actions/checkout@v6
|
|
17
|
+
- uses: actions/setup-python@v6
|
|
18
|
+
with:
|
|
19
|
+
python-version: "3.13"
|
|
20
|
+
- uses: astral-sh/setup-uv@v7
|
|
21
|
+
- name: Install dependencies
|
|
22
|
+
run: |
|
|
23
|
+
uv pip install --system pre-commit
|
|
24
|
+
uv pip install --system -e ".[test]"
|
|
25
|
+
- name: Run pre-commit (skip ty)
|
|
26
|
+
run: SKIP=ty pre-commit run --all-files
|
|
27
|
+
- name: Run ty check
|
|
28
|
+
run: uvx ty check --python "$(python3 -c 'import sys; print(sys.prefix)')"
|
|
29
|
+
|
|
30
|
+
test:
|
|
31
|
+
runs-on: ubuntu-latest
|
|
32
|
+
strategy:
|
|
33
|
+
matrix:
|
|
34
|
+
python-version: ["3.11", "3.12", "3.13"]
|
|
35
|
+
steps:
|
|
36
|
+
- uses: actions/checkout@v6
|
|
37
|
+
- uses: actions/setup-python@v6
|
|
38
|
+
with:
|
|
39
|
+
python-version: ${{ matrix.python-version }}
|
|
40
|
+
- uses: astral-sh/setup-uv@v7
|
|
41
|
+
- name: Install dependencies
|
|
42
|
+
run: uv pip install --system -e ".[test]"
|
|
43
|
+
- name: Run tests with coverage
|
|
44
|
+
run: pytest tests/ -q --cov=src/cicaddy_github --cov-report=xml
|
|
45
|
+
- name: Upload coverage
|
|
46
|
+
if: matrix.python-version == '3.13'
|
|
47
|
+
uses: actions/upload-artifact@v7
|
|
48
|
+
with:
|
|
49
|
+
name: coverage-report
|
|
50
|
+
path: coverage.xml
|
|
51
|
+
|
|
52
|
+
docker-build:
|
|
53
|
+
runs-on: ubuntu-latest
|
|
54
|
+
steps:
|
|
55
|
+
- uses: actions/checkout@v6
|
|
56
|
+
- name: Build Docker image
|
|
57
|
+
run: docker build -t cicaddy-action:test .
|
|
58
|
+
- name: Test Docker image runs
|
|
59
|
+
run: docker run --rm --entrypoint cicaddy cicaddy-action:test --version
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
name: AI PR Review
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
pull_request:
|
|
5
|
+
types: [opened, synchronize]
|
|
6
|
+
|
|
7
|
+
permissions:
|
|
8
|
+
contents: read
|
|
9
|
+
pull-requests: write
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
review:
|
|
13
|
+
if: ${{ github.actor != 'dependabot[bot]' }}
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
steps:
|
|
16
|
+
- uses: actions/checkout@v6
|
|
17
|
+
with:
|
|
18
|
+
fetch-depth: 0
|
|
19
|
+
|
|
20
|
+
- name: Build MCP config
|
|
21
|
+
id: mcp
|
|
22
|
+
env:
|
|
23
|
+
CONTEXT7_KEY: ${{ secrets.CONTEXT7_API_KEY }}
|
|
24
|
+
run: |
|
|
25
|
+
# Context7 is optional — only include if secret is configured
|
|
26
|
+
if [ -n "${CONTEXT7_KEY}" ]; then
|
|
27
|
+
echo "config=[{\"name\":\"Context7\",\"protocol\":\"http\",\"endpoint\":\"https://mcp.context7.com/mcp\",\"headers\":{\"CONTEXT7_API_KEY\":\"${CONTEXT7_KEY}\"},\"timeout\":300,\"idle_timeout\":60}]" >> "$GITHUB_OUTPUT"
|
|
28
|
+
else
|
|
29
|
+
echo 'config=[]' >> "$GITHUB_OUTPUT"
|
|
30
|
+
fi
|
|
31
|
+
|
|
32
|
+
- name: AI Code Review
|
|
33
|
+
uses: ./
|
|
34
|
+
id: review
|
|
35
|
+
with:
|
|
36
|
+
ai_provider: gemini
|
|
37
|
+
ai_model: gemini-3-flash-preview
|
|
38
|
+
ai_api_key: ${{ secrets.AI_API_KEY }}
|
|
39
|
+
task_file: tasks/pr_review.yml
|
|
40
|
+
post_pr_comment: 'true'
|
|
41
|
+
github_token: ${{ secrets.GITHUB_TOKEN }}
|
|
42
|
+
mcp_servers_config: ${{ steps.mcp.outputs.config }}
|
|
43
|
+
env:
|
|
44
|
+
ANALYSIS_FOCUS: "general"
|
|
45
|
+
GIT_DIFF_CONTEXT_LINES: "15"
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags:
|
|
6
|
+
- 'v*'
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
contents: write
|
|
10
|
+
packages: write
|
|
11
|
+
id-token: write
|
|
12
|
+
|
|
13
|
+
jobs:
|
|
14
|
+
release-build:
|
|
15
|
+
runs-on: ubuntu-latest
|
|
16
|
+
steps:
|
|
17
|
+
- uses: actions/checkout@v6
|
|
18
|
+
- uses: astral-sh/setup-uv@v7
|
|
19
|
+
- uses: actions/setup-python@v6
|
|
20
|
+
with:
|
|
21
|
+
python-version: "3.13"
|
|
22
|
+
- name: Build release distributions
|
|
23
|
+
run: uv build
|
|
24
|
+
- name: Upload distributions
|
|
25
|
+
uses: actions/upload-artifact@v7
|
|
26
|
+
with:
|
|
27
|
+
name: release-dists
|
|
28
|
+
path: dist/
|
|
29
|
+
|
|
30
|
+
docker-publish:
|
|
31
|
+
runs-on: ubuntu-latest
|
|
32
|
+
steps:
|
|
33
|
+
- uses: actions/checkout@v6
|
|
34
|
+
- name: Set up QEMU
|
|
35
|
+
uses: docker/setup-qemu-action@v4
|
|
36
|
+
- name: Set up Docker Buildx
|
|
37
|
+
uses: docker/setup-buildx-action@v4
|
|
38
|
+
- name: Log in to GHCR
|
|
39
|
+
uses: docker/login-action@v4
|
|
40
|
+
with:
|
|
41
|
+
registry: ghcr.io
|
|
42
|
+
username: ${{ github.actor }}
|
|
43
|
+
password: ${{ secrets.GITHUB_TOKEN }}
|
|
44
|
+
- name: Extract metadata
|
|
45
|
+
id: meta
|
|
46
|
+
uses: docker/metadata-action@v6
|
|
47
|
+
with:
|
|
48
|
+
images: ghcr.io/${{ github.repository }}
|
|
49
|
+
tags: |
|
|
50
|
+
type=semver,pattern={{version}}
|
|
51
|
+
type=semver,pattern={{major}}.{{minor}}
|
|
52
|
+
type=semver,pattern={{major}}
|
|
53
|
+
- name: Build and push Docker image
|
|
54
|
+
uses: docker/build-push-action@v7
|
|
55
|
+
with:
|
|
56
|
+
context: .
|
|
57
|
+
platforms: linux/amd64,linux/arm64
|
|
58
|
+
push: true
|
|
59
|
+
tags: ${{ steps.meta.outputs.tags }}
|
|
60
|
+
labels: ${{ steps.meta.outputs.labels }}
|
|
61
|
+
cache-from: type=gha
|
|
62
|
+
cache-to: type=gha,mode=max
|
|
63
|
+
|
|
64
|
+
github-release:
|
|
65
|
+
needs: [release-build, docker-publish]
|
|
66
|
+
runs-on: ubuntu-latest
|
|
67
|
+
steps:
|
|
68
|
+
- uses: actions/checkout@v6
|
|
69
|
+
- name: Create GitHub Release
|
|
70
|
+
uses: softprops/action-gh-release@v2
|
|
71
|
+
with:
|
|
72
|
+
generate_release_notes: true
|
|
73
|
+
|
|
74
|
+
pypi-publish:
|
|
75
|
+
needs: release-build
|
|
76
|
+
runs-on: ubuntu-latest
|
|
77
|
+
permissions:
|
|
78
|
+
id-token: write
|
|
79
|
+
environment:
|
|
80
|
+
name: pypi
|
|
81
|
+
url: https://pypi.org/p/cicaddy-github
|
|
82
|
+
steps:
|
|
83
|
+
- uses: actions/download-artifact@v8
|
|
84
|
+
with:
|
|
85
|
+
name: release-dists
|
|
86
|
+
path: dist/
|
|
87
|
+
- uses: pypa/gh-action-pypi-publish@release/v1
|
|
88
|
+
with:
|
|
89
|
+
packages-dir: dist/
|
|
90
|
+
|
|
91
|
+
update-major-tag:
|
|
92
|
+
needs: github-release
|
|
93
|
+
runs-on: ubuntu-latest
|
|
94
|
+
steps:
|
|
95
|
+
- uses: actions/checkout@v6
|
|
96
|
+
- name: Update major version tag
|
|
97
|
+
run: |
|
|
98
|
+
TAG="${GITHUB_REF#refs/tags/}"
|
|
99
|
+
MAJOR="${TAG%%.*}"
|
|
100
|
+
git tag -f "$MAJOR" "$TAG"
|
|
101
|
+
git push origin "$MAJOR" --force
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
*.egg-info/
|
|
6
|
+
dist/
|
|
7
|
+
build/
|
|
8
|
+
*.egg
|
|
9
|
+
|
|
10
|
+
# Virtual environments
|
|
11
|
+
.venv/
|
|
12
|
+
venv/
|
|
13
|
+
|
|
14
|
+
# IDE
|
|
15
|
+
.idea/
|
|
16
|
+
.vscode/
|
|
17
|
+
*.swp
|
|
18
|
+
*.swo
|
|
19
|
+
|
|
20
|
+
# Testing
|
|
21
|
+
.coverage
|
|
22
|
+
coverage.xml
|
|
23
|
+
htmlcov/
|
|
24
|
+
.pytest_cache/
|
|
25
|
+
|
|
26
|
+
# OS
|
|
27
|
+
.DS_Store
|
|
28
|
+
Thumbs.db
|
|
29
|
+
|
|
30
|
+
# Environment
|
|
31
|
+
.env
|
|
32
|
+
.env.*
|
|
33
|
+
.env.local
|
|
34
|
+
|
|
35
|
+
# Claude Code local settings (contains developer-specific paths)
|
|
36
|
+
.claude/settings.local.json
|
|
37
|
+
|
|
38
|
+
# UV
|
|
39
|
+
uv.lock
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
repos:
|
|
2
|
+
- repo: https://github.com/pre-commit/pre-commit-hooks
|
|
3
|
+
rev: v6.0.0
|
|
4
|
+
hooks:
|
|
5
|
+
- id: check-yaml
|
|
6
|
+
args: ['--unsafe']
|
|
7
|
+
- id: end-of-file-fixer
|
|
8
|
+
- id: trailing-whitespace
|
|
9
|
+
- id: detect-private-key
|
|
10
|
+
- id: check-added-large-files
|
|
11
|
+
args: ['--maxkb=1000']
|
|
12
|
+
- id: check-merge-conflict
|
|
13
|
+
- id: check-json
|
|
14
|
+
- id: check-toml
|
|
15
|
+
- id: debug-statements
|
|
16
|
+
- id: mixed-line-ending
|
|
17
|
+
|
|
18
|
+
- repo: https://github.com/astral-sh/ruff-pre-commit
|
|
19
|
+
rev: v0.15.0
|
|
20
|
+
hooks:
|
|
21
|
+
- id: ruff
|
|
22
|
+
args: [--fix]
|
|
23
|
+
- id: ruff-format
|
|
24
|
+
|
|
25
|
+
- repo: local
|
|
26
|
+
hooks:
|
|
27
|
+
- id: ty
|
|
28
|
+
name: ty check
|
|
29
|
+
entry: uvx ty check
|
|
30
|
+
language: system
|
|
31
|
+
types: [python]
|
|
32
|
+
pass_filenames: false
|
|
33
|
+
exclude: ^(tests/)
|
|
34
|
+
|
|
35
|
+
- repo: https://github.com/PyCQA/bandit
|
|
36
|
+
rev: 1.9.3
|
|
37
|
+
hooks:
|
|
38
|
+
- id: bandit
|
|
39
|
+
args: ['-c', 'pyproject.toml', '-r', 'src/']
|
|
40
|
+
additional_dependencies: ['bandit[toml]']
|
|
41
|
+
pass_filenames: false
|
|
42
|
+
|
|
43
|
+
- repo: https://github.com/zricethezav/gitleaks
|
|
44
|
+
rev: v8.30.0
|
|
45
|
+
hooks:
|
|
46
|
+
- id: gitleaks
|
|
47
|
+
|
|
48
|
+
- repo: https://github.com/hadolint/hadolint
|
|
49
|
+
rev: v2.13.1-beta
|
|
50
|
+
hooks:
|
|
51
|
+
- id: hadolint-docker
|
|
52
|
+
|
|
53
|
+
- repo: https://github.com/rhysd/actionlint
|
|
54
|
+
rev: v1.7.7
|
|
55
|
+
hooks:
|
|
56
|
+
- id: actionlint
|