-
Notifications
You must be signed in to change notification settings - Fork 1
create cli #48
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?
create cli #48
Conversation
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.
Pull request overview
This pull request introduces a comprehensive command-line interface (CLI) for the OpenFire fire engineering library, enabling users to create, manage, and run fire engineering projects from the terminal.
Key Changes:
- Adds a new
ofireCLI command with four subcommands:new,run,docs, andversion - Implements project scaffolding that creates complete Streamlit-based fire engineering applications with virtual environments
- Includes comprehensive test suite with cross-platform testing across Python 3.8-3.12 and Ubuntu/Windows/macOS
Reviewed changes
Copilot reviewed 13 out of 15 changed files in this pull request and generated 10 comments.
Show a summary per file
| File | Description |
|---|---|
crates/python_api/ofire/cli.py |
Main CLI entry point defining argument parsing and command routing |
crates/python_api/ofire/__main__.py |
Module entry point enabling python -m ofire execution |
crates/python_api/ofire/__init__.py |
Package initialization importing Rust modules |
crates/python_api/ofire/project.py |
Core project management logic including validation, scaffolding, and virtual environment setup |
crates/python_api/ofire/templates/main.py |
Streamlit application template with smoke layer analysis example |
crates/python_api/ofire/templates/agents_template.md |
AI agent guidance template for generated projects |
crates/python_api/tests/test_cli.py |
Comprehensive CLI test suite covering all commands and cross-platform scenarios |
crates/python_api/tests/conftest.py |
Pytest fixtures for CLI testing including temp directories and command runner |
crates/python_api/tests/__init__.py |
Empty test package initialization |
crates/python_api/pyproject.toml |
Adds CLI entry point, test dependencies, and pytest configuration |
.github/workflows/test.yaml |
Extends CI to run CLI tests across multiple OS and Python versions |
crates/python_api/docs/cli.rst |
Complete CLI documentation with examples and workflows |
crates/python_api/docs/index.rst |
Updates documentation index to include CLI section |
crates/python_api/README_TESTING.md |
Testing guide explaining how to run and develop CLI tests |
Comments suppressed due to low confidence (1)
crates/python_api/ofire/project.py:3
- Import of 'json' is not used.
import json
| @@ -0,0 +1,439 @@ | |||
| """OpenFire project creation and management logic.""" | |||
|
|
|||
| import json | |||
Copilot
AI
Dec 19, 2025
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 json module is imported but never used in this file. Remove the unused import to keep the code clean.
| import json |
| def scaffold_new_project(project_name: str, target_dir: str) -> None: | ||
| """Scaffold a new OpenFire project with all required files and setup.""" | ||
| try: | ||
| # Validate project name for security | ||
| validated_project_name = validate_project_name(project_name) | ||
|
|
||
| print(f"Creating OpenFire project: {validated_project_name}") | ||
| print(f"Target directory: {target_dir}") |
Copilot
AI
Dec 19, 2025
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 target_dir parameter is not validated before use. A malicious user could potentially provide a path with special characters or path traversal sequences that, when combined with project_name via .resolve(), could lead to unexpected behavior. Consider adding validation to ensure target_dir is a valid, safe directory path before using it.
| def run_fire_app(target: str = None) -> None: | ||
| """Run a fire engineering application.""" | ||
| if target is None: | ||
| # Default to main.py | ||
| target = "main.py" | ||
| print("Running fire engineering app (main.py)") | ||
| elif target.startswith(('http://', 'https://')): | ||
| # URL provided | ||
| print(f"Running fire engineering app from URL: {target}") | ||
| elif os.path.exists(target): | ||
| # File path provided | ||
| print(f"Running fire engineering app: {target}") | ||
| else: | ||
| # Assume it's a file that might not exist yet | ||
| print(f"Running fire engineering app: {target}") | ||
|
|
||
| try: | ||
| # Build the command to run the web app | ||
| cmd = [sys.executable, '-m', 'streamlit', 'run', target] |
Copilot
AI
Dec 19, 2025
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 target parameter is passed directly to subprocess without validation when it's a URL. This could allow arbitrary code execution if a malicious URL is provided. While streamlit itself may handle this, consider validating the URL format and potentially restricting to trusted domains, or at least warning the user before executing remote code.
| [project.optional-dependencies] | ||
| test = [ | ||
| "pytest>=7.0", | ||
| "pytest-subprocess>=1.5.0", |
Copilot
AI
Dec 19, 2025
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 pytest-subprocess>=1.5.0 dependency is listed in the test dependencies but is not imported or used anywhere in the test files. If this library is not needed for the current test implementation, consider removing it to reduce unnecessary dependencies. If it's intended for future use, add a comment explaining this.
| "pytest-subprocess>=1.5.0", |
| def ofire_available(): | ||
| """Check if ofire CLI is available and properly installed.""" | ||
| try: | ||
| result = subprocess.run( |
Copilot
AI
Dec 19, 2025
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.
Variable result is not used.
| result = subprocess.run( | |
| subprocess.run( |
| import shutil | ||
| import subprocess | ||
| import sys | ||
| import os |
Copilot
AI
Dec 19, 2025
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.
Import of 'os' is not used.
| import os |
| @@ -0,0 +1,212 @@ | |||
| import pytest | |||
| import subprocess | |||
Copilot
AI
Dec 19, 2025
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.
Import of 'subprocess' is not used.
| import subprocess |
| @@ -0,0 +1,212 @@ | |||
| import pytest | |||
| import subprocess | |||
| import sys | |||
Copilot
AI
Dec 19, 2025
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.
Import of 'sys' is not used.
| import sys |
| import subprocess | ||
| import sys | ||
| import os | ||
| from pathlib import Path |
Copilot
AI
Dec 19, 2025
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.
Import of 'Path' is not used.
| from pathlib import Path |
| except (subprocess.TimeoutExpired, subprocess.SubprocessError): | ||
| pass |
Copilot
AI
Dec 19, 2025
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.
'except' clause does nothing but pass and there is no explanatory comment.
| except (subprocess.TimeoutExpired, subprocess.SubprocessError): | |
| pass | |
| except (subprocess.TimeoutExpired, subprocess.SubprocessError) as exc: | |
| # Failed to query pip for the latest ofire version; fall back to default. | |
| print( | |
| "Warning: Could not determine latest 'ofire' version from pip; " | |
| "using default version 0.1.0.", | |
| file=sys.stderr, | |
| ) | |
| print(f" Reason: {exc}", file=sys.stderr) |
No description provided.