devs-webhook 1.2.0__tar.gz → 1.2.1__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.
- {devs_webhook-1.2.0 → devs_webhook-1.2.1}/PKG-INFO +1 -1
- {devs_webhook-1.2.0 → devs_webhook-1.2.1}/devs_webhook/config.py +9 -2
- {devs_webhook-1.2.0 → devs_webhook-1.2.1}/devs_webhook/main_cli.py +14 -9
- {devs_webhook-1.2.0 → devs_webhook-1.2.1}/devs_webhook.egg-info/PKG-INFO +1 -1
- {devs_webhook-1.2.0 → devs_webhook-1.2.1}/pyproject.toml +1 -1
- {devs_webhook-1.2.0 → devs_webhook-1.2.1}/LICENSE +0 -0
- {devs_webhook-1.2.0 → devs_webhook-1.2.1}/README.md +0 -0
- {devs_webhook-1.2.0 → devs_webhook-1.2.1}/devs_webhook/__init__.py +0 -0
- {devs_webhook-1.2.0 → devs_webhook-1.2.1}/devs_webhook/app.py +0 -0
- {devs_webhook-1.2.0 → devs_webhook-1.2.1}/devs_webhook/cli/__init__.py +0 -0
- {devs_webhook-1.2.0 → devs_webhook-1.2.1}/devs_webhook/cli/worker.py +0 -0
- {devs_webhook-1.2.0 → devs_webhook-1.2.1}/devs_webhook/core/__init__.py +0 -0
- {devs_webhook-1.2.0 → devs_webhook-1.2.1}/devs_webhook/core/base_dispatcher.py +0 -0
- {devs_webhook-1.2.0 → devs_webhook-1.2.1}/devs_webhook/core/claude_dispatcher.py +0 -0
- {devs_webhook-1.2.0 → devs_webhook-1.2.1}/devs_webhook/core/container_pool.py +0 -0
- {devs_webhook-1.2.0 → devs_webhook-1.2.1}/devs_webhook/core/deduplication.py +0 -0
- {devs_webhook-1.2.0 → devs_webhook-1.2.1}/devs_webhook/core/repository_manager.py +0 -0
- {devs_webhook-1.2.0 → devs_webhook-1.2.1}/devs_webhook/core/task_processor.py +0 -0
- {devs_webhook-1.2.0 → devs_webhook-1.2.1}/devs_webhook/core/test_dispatcher.py +0 -0
- {devs_webhook-1.2.0 → devs_webhook-1.2.1}/devs_webhook/core/webhook_config.py +0 -0
- {devs_webhook-1.2.0 → devs_webhook-1.2.1}/devs_webhook/core/webhook_handler.py +0 -0
- {devs_webhook-1.2.0 → devs_webhook-1.2.1}/devs_webhook/github/__init__.py +0 -0
- {devs_webhook-1.2.0 → devs_webhook-1.2.1}/devs_webhook/github/app_auth.py +0 -0
- {devs_webhook-1.2.0 → devs_webhook-1.2.1}/devs_webhook/github/client.py +0 -0
- {devs_webhook-1.2.0 → devs_webhook-1.2.1}/devs_webhook/github/models.py +0 -0
- {devs_webhook-1.2.0 → devs_webhook-1.2.1}/devs_webhook/github/parser.py +0 -0
- {devs_webhook-1.2.0 → devs_webhook-1.2.1}/devs_webhook/sources/__init__.py +0 -0
- {devs_webhook-1.2.0 → devs_webhook-1.2.1}/devs_webhook/sources/base.py +0 -0
- {devs_webhook-1.2.0 → devs_webhook-1.2.1}/devs_webhook/sources/sqs_source.py +0 -0
- {devs_webhook-1.2.0 → devs_webhook-1.2.1}/devs_webhook/sources/webhook_source.py +0 -0
- {devs_webhook-1.2.0 → devs_webhook-1.2.1}/devs_webhook/utils/__init__.py +0 -0
- {devs_webhook-1.2.0 → devs_webhook-1.2.1}/devs_webhook/utils/async_utils.py +0 -0
- {devs_webhook-1.2.0 → devs_webhook-1.2.1}/devs_webhook/utils/container_logs.py +0 -0
- {devs_webhook-1.2.0 → devs_webhook-1.2.1}/devs_webhook/utils/github.py +0 -0
- {devs_webhook-1.2.0 → devs_webhook-1.2.1}/devs_webhook/utils/logging.py +0 -0
- {devs_webhook-1.2.0 → devs_webhook-1.2.1}/devs_webhook/utils/s3_artifacts.py +0 -0
- {devs_webhook-1.2.0 → devs_webhook-1.2.1}/devs_webhook/utils/serialization.py +0 -0
- {devs_webhook-1.2.0 → devs_webhook-1.2.1}/devs_webhook.egg-info/SOURCES.txt +0 -0
- {devs_webhook-1.2.0 → devs_webhook-1.2.1}/devs_webhook.egg-info/dependency_links.txt +0 -0
- {devs_webhook-1.2.0 → devs_webhook-1.2.1}/devs_webhook.egg-info/entry_points.txt +0 -0
- {devs_webhook-1.2.0 → devs_webhook-1.2.1}/devs_webhook.egg-info/requires.txt +0 -0
- {devs_webhook-1.2.0 → devs_webhook-1.2.1}/devs_webhook.egg-info/top_level.txt +0 -0
- {devs_webhook-1.2.0 → devs_webhook-1.2.1}/setup.cfg +0 -0
- {devs_webhook-1.2.0 → devs_webhook-1.2.1}/tests/test_allowlist.py +0 -0
- {devs_webhook-1.2.0 → devs_webhook-1.2.1}/tests/test_authentication.py +0 -0
- {devs_webhook-1.2.0 → devs_webhook-1.2.1}/tests/test_authorized_users.py +0 -0
- {devs_webhook-1.2.0 → devs_webhook-1.2.1}/tests/test_ci_container_pool.py +0 -0
- {devs_webhook-1.2.0 → devs_webhook-1.2.1}/tests/test_container_logs.py +0 -0
- {devs_webhook-1.2.0 → devs_webhook-1.2.1}/tests/test_single_queue.py +0 -0
- {devs_webhook-1.2.0 → devs_webhook-1.2.1}/tests/test_sqs_burst.py +0 -0
- {devs_webhook-1.2.0 → devs_webhook-1.2.1}/tests/test_webhook_parser.py +0 -0
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
import os
|
|
4
4
|
from pathlib import Path
|
|
5
5
|
from functools import lru_cache
|
|
6
|
-
from typing import List, Optional
|
|
6
|
+
from typing import Dict, List, Optional
|
|
7
7
|
try:
|
|
8
8
|
from pydantic_settings import BaseSettings, SettingsConfigDict
|
|
9
9
|
except ImportError:
|
|
@@ -181,7 +181,14 @@ class WebhookConfig(BaseSettings, BaseConfig):
|
|
|
181
181
|
if self.log_format == "json":
|
|
182
182
|
self.log_format = "console"
|
|
183
183
|
return self
|
|
184
|
-
|
|
184
|
+
|
|
185
|
+
@property
|
|
186
|
+
def container_labels(self) -> Dict[str, str]:
|
|
187
|
+
"""Standard labels applied to containers created by webhook."""
|
|
188
|
+
labels = super().container_labels
|
|
189
|
+
labels["devs.source"] = "webhook"
|
|
190
|
+
return labels
|
|
191
|
+
|
|
185
192
|
# Configuration for Pydantic Settings
|
|
186
193
|
# Note: .env files are optional - environment variables are the primary source
|
|
187
194
|
if SettingsConfigDict:
|
|
@@ -448,23 +448,25 @@ def test(prompt: str, repo: str, host: str, port: int, username: str, password:
|
|
|
448
448
|
|
|
449
449
|
|
|
450
450
|
@cli.command()
|
|
451
|
-
@click.option('--all', 'cleanup_all', is_flag=True, help='Clean up all
|
|
451
|
+
@click.option('--all', 'cleanup_all', is_flag=True, help='Clean up all webhook containers (not just idle ones)')
|
|
452
452
|
@click.option('--max-age-hours', default=None, type=int, help='Override max age threshold (default: from config or 10)')
|
|
453
453
|
@click.option('--idle-minutes', default=None, type=int, help='Override idle timeout (default: from config or 60)')
|
|
454
454
|
@click.option('--dry-run', is_flag=True, help='Show what would be cleaned up without actually doing it')
|
|
455
455
|
def cleanup(cleanup_all: bool, max_age_hours: int, idle_minutes: int, dry_run: bool):
|
|
456
|
-
"""Clean up idle and old containers.
|
|
456
|
+
"""Clean up idle and old webhook containers.
|
|
457
457
|
|
|
458
|
-
This command finds containers
|
|
458
|
+
This command finds containers created by devs-webhook and cleans up those that
|
|
459
459
|
are idle (exited, or running but not processing) and either:
|
|
460
460
|
- Idle for longer than the idle timeout
|
|
461
461
|
- Older than the max age threshold
|
|
462
462
|
|
|
463
|
+
Only cleans up webhook-created containers (not CLI-created ones).
|
|
464
|
+
|
|
463
465
|
Use this after burst mode processing completes, or via cron for periodic cleanup.
|
|
464
466
|
|
|
465
467
|
Examples:
|
|
466
468
|
devs-webhook cleanup # Clean up idle containers exceeding thresholds
|
|
467
|
-
devs-webhook cleanup --all # Clean up ALL
|
|
469
|
+
devs-webhook cleanup --all # Clean up ALL webhook containers
|
|
468
470
|
devs-webhook cleanup --dry-run # Show what would be cleaned up
|
|
469
471
|
devs-webhook cleanup --max-age-hours 2 # Override max age to 2 hours
|
|
470
472
|
"""
|
|
@@ -487,7 +489,7 @@ def cleanup(cleanup_all: bool, max_age_hours: int, idle_minutes: int, dry_run: b
|
|
|
487
489
|
click.echo(f" Max age: {max_age.total_seconds() / 3600:.1f} hours")
|
|
488
490
|
click.echo(f" Idle timeout: {idle_timeout.total_seconds() / 60:.0f} minutes")
|
|
489
491
|
if cleanup_all:
|
|
490
|
-
click.echo(" Mode: Clean ALL
|
|
492
|
+
click.echo(" Mode: Clean ALL webhook containers")
|
|
491
493
|
if dry_run:
|
|
492
494
|
click.echo(" Mode: DRY RUN (no changes will be made)")
|
|
493
495
|
click.echo()
|
|
@@ -498,18 +500,21 @@ def cleanup(cleanup_all: bool, max_age_hours: int, idle_minutes: int, dry_run: b
|
|
|
498
500
|
click.echo(f"❌ Failed to connect to Docker: {e}")
|
|
499
501
|
return
|
|
500
502
|
|
|
501
|
-
# Find
|
|
503
|
+
# Find webhook-created containers only
|
|
502
504
|
try:
|
|
503
|
-
containers = docker.find_containers_by_labels({
|
|
505
|
+
containers = docker.find_containers_by_labels({
|
|
506
|
+
"devs.managed": "true",
|
|
507
|
+
"devs.source": "webhook"
|
|
508
|
+
})
|
|
504
509
|
except Exception as e:
|
|
505
510
|
click.echo(f"❌ Failed to list containers: {e}")
|
|
506
511
|
return
|
|
507
512
|
|
|
508
513
|
if not containers:
|
|
509
|
-
click.echo("✅ No
|
|
514
|
+
click.echo("✅ No webhook containers found")
|
|
510
515
|
return
|
|
511
516
|
|
|
512
|
-
click.echo(f"Found {len(containers)}
|
|
517
|
+
click.echo(f"Found {len(containers)} webhook container(s)")
|
|
513
518
|
|
|
514
519
|
now = datetime.now(tz=timezone.utc)
|
|
515
520
|
cleaned = 0
|
|
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
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|