Skip to content

Commit fe15c6d

Browse files
committed
kpd: add --dry-run-list-candidates-only option for debugging
Add a new command-line option that allows users to run KPD in dry-run mode to list candidate patches without processing them. This is useful for debugging issues with patch detection and understanding what patches KPD would process. The dry-run mode: - Fetches relevant subjects from Patchwork using the same logic as normal operation - Lists all candidate patches with their series information - Exits without creating PRs or making any changes - Provides clear output showing patch subjects, series IDs, and metadata This helps diagnose issues like patches being outside the lookback window or problems with the Patchwork API integration. Generated-by: Claude AI Signed-off-by: Luis Chamberlain <[email protected]>
1 parent ee1959d commit fe15c6d

File tree

5 files changed

+144
-9
lines changed

5 files changed

+144
-9
lines changed

CLAUDE.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,9 @@ poetry run flake8
4141
# Run with configuration
4242
poetry run python -m kernel_patches_daemon --config <config_path> --label-color configs/labels.json
4343

44+
# Dry run mode: List candidate patches only (useful for debugging)
45+
poetry run python -m kernel_patches_daemon --config <config_path> --label-color configs/labels.json --dry-run-list-candidates-only
46+
4447
# Purge all PRs and branches (destructive)
4548
poetry run python -m kernel_patches_daemon --config <config_path> --action purge
4649
```
@@ -83,6 +86,7 @@ docker pull ghcr.io/kernel-patches/kernel-patches-daemon:latest
8386
- Key sections: `patchwork`, `branches`, `tag_to_branch_mapping`, `mirror_dir`
8487
- Authentication: GitHub Apps preferred over personal tokens
8588
- Mirror setup: Uses `mirror_dir` with fallback repositories for bandwidth optimization
89+
- Lookback period: Recommended 14-21 days for kernel projects (default 7 may be too short)
8690

8791
### Testing Structure
8892

@@ -93,6 +97,11 @@ docker pull ghcr.io/kernel-patches/kernel-patches-daemon:latest
9397

9498
## Development Notes
9599

100+
### Debugging and Troubleshooting
101+
- Use `--dry-run-list-candidates-only` for debugging patch detection issues
102+
- Check project ID type consistency (should be strings in config, auto-converted to int)
103+
- Verify lookback period is appropriate for the project's patch lifecycle
104+
96105
### Code Style
97106
- Uses `black` formatter (enforced)
98107
- Python 3.10+ required

CONFIG.md

Lines changed: 68 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
## Overview
44

5-
This document provides detailed configuration options for Kernel Patches Daemon (KPD).
5+
This document provides detailed configuration options for Kernel Patches Daemon (KPD). For comprehensive deployment guidance including GitHub organization setup and security considerations, see the [kdevops KPD integration documentation](https://github.com/linux-kdevops/kdevops/blob/main/docs/kernel-ci/kernel-ci-kpd.md).
66

77
## Configuration File Structure
88

@@ -16,6 +16,16 @@ KPD uses a JSON configuration file with the following main sections:
1616
- `mirror_dir`: Optional mirror directory for bandwidth optimization
1717
- `email`: Optional email configuration
1818

19+
### Patchwork Configuration
20+
21+
The `patchwork` section includes:
22+
- `server`: Patchwork server hostname (e.g., "patchwork.kernel.org")
23+
- `project`: Project name or ID (can be string or integer)
24+
- `lookback`: Number of days to look back for patches (default: 7, recommended: 14-21 for kernel projects)
25+
- `search_patterns`: List of search criteria for filtering patches
26+
- `api_username`: Username for Patchwork API authentication
27+
- `api_token`: API token for write operations
28+
1929
## Branch Configuration
2030

2131
Each branch in the `branches` section supports the following options:
@@ -74,16 +84,65 @@ For each branch, you can specify a `mirror_fallback_repo` as an alternative path
7484
- Ideal for corporate environments with NFS-mounted git repositories
7585
- Reduces storage requirements for multiple repository clones
7686

77-
## Github personal tokens
87+
## Authentication
88+
89+
### GitHub Apps (Recommended)
90+
91+
KPD supports GitHub Apps for authentication, which provides better security and more granular permissions compared to personal access tokens. A GitHub App requires the following permissions:
92+
93+
**Repository Permissions:**
94+
- **Content**: Read and write access to repository content (for creating branches and updating files)
95+
- **Pull requests**: Read and write access to manage pull requests
96+
- **Workflows**: Read access to workflow runs and write access to trigger workflows
97+
98+
**Organization Permissions (if applicable):**
99+
- **Members**: Read access to organization members (for team-based access control)
100+
101+
### GitHub Personal Tokens (Legacy)
102+
103+
While you may use [GitHub personal tokens](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token) to authenticate KPD, GitHub Apps are strongly recommended for production deployments.
104+
105+
### Security Best Practices
106+
107+
- **Disable webhooks** on the GitHub App for enhanced security
108+
- **Limit repository access** to only the repositories that need KPD integration
109+
- **Use environment variables** or secure secret management for tokens and keys
110+
- **Regularly rotate** authentication credentials
111+
- **Monitor access logs** and audit permissions periodically
112+
113+
For detailed GitHub App setup instructions, including security considerations and organizational policies, refer to the [kdevops documentation](https://github.com/linux-kdevops/kdevops/blob/main/docs/kernel-ci/kernel-ci-kpd.md).
114+
115+
## Configuration Validation
116+
117+
KPD validates configuration on startup and will report specific errors for:
118+
- Missing required fields
119+
- Invalid JSON syntax
120+
- Malformed URLs or paths
121+
- Conflicting branch configurations
122+
- Authentication credential issues
123+
124+
## Troubleshooting Common Configuration Issues
125+
126+
**Authentication Failures:**
127+
- Verify GitHub App installation and permissions
128+
- Check token expiration dates
129+
- Ensure repository access is properly configured
130+
131+
**Mirror Setup Issues:**
132+
- Verify mirror directory paths exist and are readable
133+
- Check git repository validity in mirror directories
134+
- Ensure proper file permissions on mirror directories
78135

79-
You may use [Github personal token](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token)
80-
to authenticate KPD to github, but using [Github App](https://docs.github.com/en/apps/creating-github-apps/authenticating-with-a-github-app/about-authentication-with-a-github-app) is preferrable.
136+
**Branch Configuration Problems:**
137+
- Validate upstream and CI repository URLs
138+
- Verify branch names exist in respective repositories
139+
- Check for conflicting tag-to-branch mappings
81140

82-
When using a GH app, it needs to have the following read and write access:
83-
- Content (write to repo)
84-
- Pull request (create PRs)
85-
- Workflow
141+
**Patch Detection Issues:**
142+
- Check lookback period is appropriate (7 days may be too short for kernel projects)
143+
- Confirm search patterns match the patches you expect to process
144+
- Use `--dry-run-list-candidates-only` to debug patch detection
86145

87146
## Example Configuration
88147

89-
See the `configs/` directory for complete configuration examples.
148+
See the `configs/` directory for complete configuration examples demonstrating various deployment scenarios.

README.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,10 +77,19 @@ poetry run python -m kernel_patches_daemon --config <config_path> --label-color
7777

7878
### Debugging and Testing
7979
```bash
80+
# Dry run mode: List candidate patches without processing them
81+
poetry run python -m kernel_patches_daemon --config <config_path> --label-color configs/labels.json --dry-run-list-candidates-only
82+
8083
# Purge all existing PRs and branches (destructive operation)
8184
poetry run python -m kernel_patches_daemon --config <config_path> --action purge
8285
```
8386

87+
The dry-run mode is particularly useful for:
88+
- Debugging patch detection issues
89+
- Verifying configuration changes
90+
- Understanding what patches KPD would process
91+
- Testing with new patchwork instances
92+
8493
## Docker
8594

8695
Kernel Patches Daemon is available as pre-build image:

kernel_patches_daemon/__main__.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,11 @@ def parse_args() -> argparse.Namespace:
9696
choices=["start", "purge"],
9797
help="Purge will kill all existing PRs and delete all branches",
9898
)
99+
parser.add_argument(
100+
"--dry-run-list-candidates-only",
101+
action="store_true",
102+
help="Dry run mode: list candidate patches only and exit",
103+
)
99104
args = parser.parse_args()
100105
return args
101106

@@ -132,6 +137,19 @@ def parse_args() -> argparse.Namespace:
132137
logger.exception("Failed to purge")
133138
exit(1)
134139

140+
if args.dry_run_list_candidates_only:
141+
try:
142+
from kernel_patches_daemon.github_sync import GithubSync
143+
144+
github_sync = GithubSync(kpd_config=kpd_config, labels_cfg=labels_cfg)
145+
import asyncio
146+
147+
asyncio.run(github_sync.dry_run_list_candidates())
148+
exit(0)
149+
except Exception:
150+
logger.exception("Failed to list candidates")
151+
exit(1)
152+
135153
daemon = KernelPatchesDaemon(
136154
kpd_config=kpd_config,
137155
labels_cfg=labels_cfg,

kernel_patches_daemon/github_sync.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -373,3 +373,43 @@ async def sync_patches(self) -> None:
373373
if worker._is_relevant_pr(pr):
374374
self.increment_counter("prs_total")
375375
processed_prs.add(1)
376+
377+
async def dry_run_list_candidates(self) -> None:
378+
"""
379+
Dry run mode: List candidate patches only without processing them.
380+
"""
381+
logger.info("Starting dry run to list candidate patches...")
382+
383+
# Fetch relevant subjects from Patchwork
384+
self.subjects = await self.pw.get_relevant_subjects()
385+
386+
if not self.subjects:
387+
logger.info("No candidate patches found.")
388+
print("No candidate patches found.")
389+
return
390+
391+
logger.info(f"Found {len(self.subjects)} candidate patch subjects:")
392+
print(f"Found {len(self.subjects)} candidate patch subjects:")
393+
print("=" * 60)
394+
395+
for i, subject in enumerate(self.subjects, 1):
396+
print(f"{i}. Subject: {subject.subject}")
397+
398+
# Get the latest series for this subject
399+
try:
400+
latest_series = await subject.latest_series()
401+
if latest_series:
402+
print(f" Series ID: {latest_series.id}")
403+
print(f" Series Name: {latest_series.name}")
404+
print(f" Version: {latest_series.version}")
405+
print(f" Date: {latest_series.date}")
406+
print(f" URL: {latest_series.web_url}")
407+
else:
408+
print(" No series found for this subject")
409+
except Exception as e:
410+
print(f" Error fetching series: {e}")
411+
412+
print()
413+
414+
print("=" * 60)
415+
logger.info("Dry run completed.")

0 commit comments

Comments
 (0)