-
Notifications
You must be signed in to change notification settings - Fork 0
Add CLI commands to list and clone jobs from repositories #187
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
21fa856
ae3972a
952f093
83071cd
4410128
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,346 @@ | ||||||||||
| """Jobs command for DeepWork CLI.""" | ||||||||||
|
|
||||||||||
| import shutil | ||||||||||
| import tempfile | ||||||||||
| from pathlib import Path | ||||||||||
| from urllib.parse import urlparse | ||||||||||
|
|
||||||||||
| import click | ||||||||||
| from git import Repo | ||||||||||
| from rich.console import Console | ||||||||||
| from rich.table import Table | ||||||||||
|
|
||||||||||
| from deepwork.cli.sync import SyncError, sync_skills | ||||||||||
| from deepwork.core.parser import ParseError, parse_job_definition | ||||||||||
| from deepwork.utils.fs import ensure_dir, fix_permissions | ||||||||||
|
|
||||||||||
| console = Console() | ||||||||||
|
|
||||||||||
|
|
||||||||||
| class JobsError(Exception): | ||||||||||
| """Exception raised for jobs command errors.""" | ||||||||||
|
|
||||||||||
| pass | ||||||||||
|
|
||||||||||
|
|
||||||||||
| def _is_github_url(source: str) -> bool: | ||||||||||
| """ | ||||||||||
| Check if source is a GitHub URL. | ||||||||||
|
|
||||||||||
| Args: | ||||||||||
| source: Source path or URL | ||||||||||
|
|
||||||||||
| Returns: | ||||||||||
| True if source is a GitHub URL, False otherwise | ||||||||||
| """ | ||||||||||
| try: | ||||||||||
| parsed = urlparse(source) | ||||||||||
| # Check for exact match on github.com or GitHub Enterprise subdomains | ||||||||||
| is_github = ( | ||||||||||
| parsed.scheme in ("http", "https") | ||||||||||
| and (parsed.netloc == "github.com" or parsed.netloc.endswith(".github.com")) | ||||||||||
| ) | ||||||||||
| return is_github | ||||||||||
| except ValueError: | ||||||||||
| return False | ||||||||||
|
|
||||||||||
|
|
||||||||||
| def _get_deepwork_default_library() -> Path: | ||||||||||
| """ | ||||||||||
| Get the default library/jobs path from the deepwork package. | ||||||||||
|
|
||||||||||
| Returns: | ||||||||||
| Path to library/jobs in deepwork package | ||||||||||
| """ | ||||||||||
| # Try to find the library/jobs in the deepwork package | ||||||||||
| deepwork_root = Path(__file__).parent.parent.parent.parent | ||||||||||
| library_path = deepwork_root / "library" / "jobs" | ||||||||||
|
|
||||||||||
| if library_path.exists(): | ||||||||||
| return library_path | ||||||||||
|
|
||||||||||
| # Fallback: try to clone from GitHub | ||||||||||
| raise JobsError( | ||||||||||
| "Could not find library/jobs in deepwork package. " | ||||||||||
| "Please specify a source path or URL." | ||||||||||
| ) | ||||||||||
|
|
||||||||||
|
|
||||||||||
| def _resolve_source(source: str | None) -> Path: | ||||||||||
| """ | ||||||||||
| Resolve source to a local path, cloning if necessary. | ||||||||||
|
|
||||||||||
| Args: | ||||||||||
| source: Source path, URL, or None (default to deepwork library) | ||||||||||
|
|
||||||||||
| Returns: | ||||||||||
| Path to the jobs directory | ||||||||||
|
|
||||||||||
| Raises: | ||||||||||
| JobsError: If source cannot be resolved | ||||||||||
| """ | ||||||||||
| if source is None: | ||||||||||
| # Default to deepwork library/jobs | ||||||||||
| return _get_deepwork_default_library() | ||||||||||
|
|
||||||||||
| # Check if it's a local path | ||||||||||
| source_path = Path(source) | ||||||||||
| if source_path.exists(): | ||||||||||
| if source_path.is_dir(): | ||||||||||
| # If pointing to a repo root, look for jobs in standard locations | ||||||||||
| if (source_path / ".deepwork" / "jobs").exists(): | ||||||||||
| return source_path / ".deepwork" / "jobs" | ||||||||||
| if (source_path / "library" / "jobs").exists(): | ||||||||||
| return source_path / "library" / "jobs" | ||||||||||
|
||||||||||
| return source_path / "library" / "jobs" | |
| return source_path / "library" / "jobs" | |
| if (source_path / "jobs").exists(): | |
| return source_path / "jobs" |
Copilot
AI
Jan 30, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
GitCommandError is imported locally inside the try block, while Repo is imported at the module level (line 9). This is inconsistent and unnecessary. Both imports come from the same git package and should be imported together at the module level for consistency.
Move the GitCommandError import to line 9 to match the existing import style.
Copilot
AI
Jan 30, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The temporary directory created for cloned repositories is never cleaned up after use. When cloning from a GitHub URL, a temp directory is created and a path inside it is returned. This temp directory persists on disk even after the command completes, leading to a resource leak.
The issue affects both the list and clone commands when using GitHub URLs. The temp directories will accumulate in the system's temp folder over time.
Consider using a context manager or storing the temp directory reference so it can be cleaned up after the command completes. One approach would be to use tempfile.TemporaryDirectory() as a context manager at the command level, or implement a cleanup mechanism that tracks and removes the temp directory after the jobs have been copied.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Misleading comment: The comment states "Fallback: try to clone from GitHub" but the code immediately raises a JobsError without attempting any GitHub cloning. The comment should be removed or updated to accurately reflect that this is an error path when the local library cannot be found.