feat: improve dependency preflight error messages#200
Conversation
- Report all missing dependencies at once instead of exiting on first - Map executables to human-readable package names (dot → Graphviz) - Add OS-specific installation instructions (brew, apt, Windows links) - Link to official installation docs and README - Add unit tests for check_dependencies and OS detection
There was a problem hiding this comment.
Pull request overview
Note
Copilot was unable to run its full agentic suite in this review.
Adds more user-friendly dependency preflight checks by grouping missing tools and emitting OS-specific install instructions, plus unit tests covering dependency detection and OS family classification.
Changes:
- Added
_get_os_family()to classify OS for install guidance (macOS, Debian-like, WSL, Windows, etc.). - Enhanced
check_dependencies()to report all missing tools at once and print OS-specific install instructions + docs links. - Introduced new tests for both dependency checking and OS-family detection.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 5 comments.
| File | Description |
|---|---|
modules/helpers.py |
Adds OS detection helper and expands dependency checks to print grouped, OS-specific installation instructions. |
tests/test_dependencies.py |
Adds unit tests covering dependency detection and _get_os_family() behavior. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| missing = [] | ||
| for exe, (name, pkg) in dependency_info.items(): | ||
| location = shutil.which(exe) or os.path.isfile(exe) | ||
| if location: | ||
| click.echo(f" {exe} command detected: {location}") | ||
| else: |
| click.echo(" https://patrickchugh.github.io/terravision/installation/") | ||
| click.echo(" https://github.com/patrickchugh/terravision#install\n") | ||
|
|
||
| exit(1) |
| if os_family == "macos": | ||
| for pkg in packages_to_install: | ||
| if pkg == "graphviz": | ||
| click.echo(" brew install graphviz") | ||
| elif pkg == "git": | ||
| click.echo(" brew install git") | ||
| elif pkg == "terraform": | ||
| click.echo(" brew tap hashicorp/tap") | ||
| click.echo(" brew install hashicorp/terraform") | ||
| elif os_family in ("debian", "wsl"): | ||
| apt_packages = [] | ||
| for pkg in packages_to_install: | ||
| if pkg == "graphviz": | ||
| apt_packages.append("graphviz") | ||
| apt_packages.append("libgvplugin-neato-layout8") | ||
| elif pkg == "git": | ||
| apt_packages.append("git") | ||
| elif pkg == "terraform": | ||
| click.echo(" # Terraform install steps:") | ||
| click.echo(" # https://developer.hashicorp.com/terraform/install") | ||
| if apt_packages: | ||
| click.echo(" sudo apt update") | ||
| click.echo(f" sudo apt install {' '.join(apt_packages)}") | ||
| elif os_family == "windows": | ||
| click.echo(" # Download and install from the official websites:") | ||
| for pkg in packages_to_install: | ||
| if pkg == "graphviz": | ||
| click.echo(" # Graphviz: https://graphviz.org/download/") | ||
| elif pkg == "git": | ||
| click.echo(" # Git: https://git-scm.com/download/win") | ||
| elif pkg == "terraform": | ||
| click.echo( | ||
| " # Terraform: https://developer.hashicorp.com/terraform/install" | ||
| ) | ||
| else: | ||
| for pkg in packages_to_install: | ||
| if pkg == "graphviz": | ||
| click.echo(" # Install Graphviz using your package manager") | ||
| click.echo(" # e.g. sudo apt install graphviz (Debian/Ubuntu)") | ||
| click.echo(" # sudo yum install graphviz (RHEL/CentOS)") | ||
| elif pkg == "git": | ||
| click.echo(" # Install Git using your package manager") | ||
| elif pkg == "terraform": | ||
| click.echo( | ||
| " # Install Terraform: https://developer.hashicorp.com/terraform/install" | ||
| ) |
| if pkg == "graphviz": | ||
| apt_packages.append("graphviz") | ||
| apt_packages.append("libgvplugin-neato-layout8") |
| with pytest.raises(SystemExit) as exc_info: | ||
| check_dependencies() | ||
|
|
||
| assert exc_info.value.code == 1 |
|
Thanks for the pr @ScaferuZ - can you please refactor check_dependencies so it not a long list of if/else statements. Consider centralising instructions in a data structure and looping through the list |
|
@ScaferuZ Will you be making the changes ? |
hi, for some reason theres no notification on my end, sorry. i will be making the changes, thanks for the feedback! |
Resolve check_dependencies conflict: combine the data-driven DEPENDENCIES table with upstream OpenTofu engine support. The terraform entry uses an empty executables list and resolves its binary via get_tf_binary() at call time, so dependency detection honors the --engine flag (terraform or tofu).
Better dependency error message
Type of Change
Checklist
All Submissions:
AI Assistance Declaration
Tools used: OpenCode Go
Model: Kimi K2.6
Scope:
Report all missing dependencies at once instead of exiting on first
Map executables to human-readable package names (dot → Graphviz)
Add OS-specific installation instructions (brew, apt, Windows links)
Link to official installation docs and README
Add unit tests for check_dependencies and OS detection
Checklist for Changes to Core Features:
Bad : Adding support for GCP and Azure system wide
Good: Just adding Azure resource handler for VNets
(not core feature)