Contributing to TerraVision¶
Thank you for your interest in TerraVision.
Who can contribute¶
TerraVision accepts pull requests only from collaborators the maintainer has invited. TerraVision's GitHub policy does not allow anyone else to open a pull request on this repository.
Everyone can still help:
- Report a bug in GitHub Issues, with a
tfdata.jsonfile attached, as Reporting a bug describes. - Ask for a feature or a missing resource type in Issues.
- Ask questions and share ideas in GitHub Discussions.
- Report a security problem privately, as the Security Policy describes.
Reporting a bug¶
Attach a tfdata.json file to every bug report. It holds everything TerraVision read from your Terraform, so the maintainer can replay your run exactly with terravision draw --source tfdata.json, without your code, cloud credentials or provider versions. It is the quickest way to get a bug fixed.
- Run the command that shows the problem again, with
--debugadded:
TerraVision writes tfdata.json to the folder you ran the command from. It writes the file even when the run fails, with whatever it had built by then.
-
Open
tfdata.jsonin a text editor and use find and replace on anything sensitive: account and subscription IDs, domain names, IP ranges, resource names, and variable values from your.tfvarsfiles. Replace each value the same way everywhere it appears (every123456789012with111111111111, for example), so the resources still connect as they did. -
Attach the file to the issue, with the TerraVision version (
terravision --version) and the command you ran. If you cannot share it at all, attach a minimal Terraform folder that shows the problem instead.
To work on TerraVision as a collaborator, start a discussion in Discussions saying what you would like to work on.
The rest of this guide is for collaborators.
Table of Contents¶
- Who can contribute
- Code of Conduct
- Getting Started
- Development Workflow
- Code Standards
- Testing Requirements
- Adding a gallery example
- Pull Request Process
- AI-Assisted Development
- Architecture Guidelines
Code of Conduct¶
By participating in this project, you agree to maintain a respectful and collaborative environment for all contributors.
Getting Started¶
Development Setup¶
Follow the canonical installation instructions: Installation → Method 4: Install from Source with Poetry. That covers system prerequisites, Poetry install, and repo clone.
Then, from the repo root, enable the project's git hooks:
Optional extras for AI-annotation work:
- Ollama — for testing
--ai-annotate ollamalocally. See Installation → Ollama. - AWS account with Bedrock access — for testing
--ai-annotate bedrock. Authentication uses the standardboto3credential chain, so any AWS-CLI-compatible setup works (env vars,~/.aws/credentials, IAM role, SSO). Region and model id are overridable viaTV_BEDROCK_REGIONandTV_BEDROCK_MODEL_ID. - An OpenAI-compatible endpoint — for testing
--ai-annotate restapi. SetTV_RESTAPI_URL,TV_RESTAPI_KEY, andTV_RESTAPI_MODELto point at OpenAI, an Anthropic-via-LiteLLM proxy, a local vLLM/LM Studio, or any custom shim that speaks the OpenAI chat-completions schema.
Running Tests¶
# Run all tests
poetry run pytest tests -v
# Run non-slow tests (for quick validation)
poetry run pytest -m "not slow"
# Run specific test file
poetry run pytest tests/test_provider_detection.py -v
# Run with coverage
poetry run pytest tests --cov=modules
Development Workflow¶
- Create a feature branch from
mainin this repository. Collaborators have write access, so no fork is needed - Make your changes following the code standards below
- Write tests for new functionality
- Run the test suite to ensure all tests pass
- Format your code with Black
- Submit a pull request to the
mainbranch
Branch Naming¶
Use descriptive branch names:
feature/add-azure-supportfix/security-group-parsingdocs/update-readmerefactor/provider-detection
Commit Messages¶
Write clear, descriptive commit messages:
Add support for GCP Cloud Run resources
- Implement Cloud Run handler in resource_handlers_gcp.py
- Map the Cloud Run types to their icons in resource_classes/gcp/terraform_icons.yml
- Update cloud_config_gcp.py with special resources
- Add integration tests for Cloud Run
Code Standards¶
Python Style Guide¶
TerraVision uses Black for code formatting with the following configuration:
- Line length: 88 characters
- Follow PEP 8 conventions
- Use type hints where appropriate
- Write docstrings for public functions
Formatting¶
# Check formatting (what CI runs)
poetry run black --check -v modules
# Auto-format code
poetry run black modules
# Run all pre-commit hooks
pre-commit run --all-files
Code Organization¶
- Provider-specific code goes in
modules/config/cloud_config_<provider>.pyandmodules/resource_handlers_<provider>.py - Shared utilities belong in
modules/helpers.py - Icons are PNG files in
resource_images/<provider>/; which Terraform type draws with which icon isresource_classes/<provider>/terraform_icons.yml, and the icon classes inicons.pyare generated byscripts/generate_icon_classes.py - Tests mirror the module structure in
tests/
Import Order¶
Use isort conventions (automatically applied by pre-commit):
- Standard library imports
- Third-party imports
- Local application imports
Testing Requirements¶
Test Coverage¶
- All new features must include tests
- Bug fixes should include regression tests
- Aim for >80% code coverage on new code
Test Types¶
Unit Tests (tests/*_unit_test.py):
def test_provider_detection():
tfdata = {"all_resource": [{"type": "aws_instance"}]}
result = detect_providers(tfdata)
assert "aws" in result["providers"]
Integration Tests (tests/integration_test.py):
- Test the full pipeline with real Terraform code
- Mark as slow:
@pytest.mark.slow
Provider Tests (tests/test_<provider>_*.py):
- Validate provider-specific functionality
- Test config loading and resource handlers
Running Tests Locally¶
Before submitting a PR, ensure:
# All tests pass
poetry run pytest tests -v
# Code is formatted
poetry run black --check -v modules
# Pre-commit hooks pass
pre-commit run --all-files
Adding a gallery example¶
The gallery examples live in examples/graphs/. Name a new one <cloud>-<pattern>, with the cloud aws, azure or gcp, and match the depth of the existing ones: 25 to 50 nodes, a CIDR range on every network and subnet, managed services reached through private endpoints, and two or three flows. An example consists of five files:
examples/graphs/<name>.tvg.json: the graph (Graph Format)examples/graphs/<name>.annotations.yml: its title, CIDR ranges (update:), arrow labels (connect:) and numbered flows (flows:)examples/graphs/<name>.pngandexamples/graphs/<name>.svg: the rendersdocs/assets/gallery/<name>.webp: the web-sized copy the gallery page shows
plus a section in docs/gallery.md, in the same format as the others (heading with its anchor, description, image, "Ask your AI assistant:" prompt, the reproduce commands and the Download line), and a row in the table in examples/graphs/README.md. Write the graph and annotations, the gallery section and the README row by hand; the rest is generated:
# Validate, render the PNG and SVG, make the WebP, set the image size in
# docs/gallery.md and regenerate the example list in docs/llms.txt
poetry run python scripts/render_examples.py
# Check every example is complete and draws without warnings
poetry run pytest tests/test_examples_gallery.py
render_examples.py prints every warning: a flow step or arrow label that draws nothing, a node listed in two boxes, a network or subnet with no CIDR range. Fix them in the graph or annotations and run it again. The Hugging Face dataset is built from the same files with scripts/hf_dataset/build_dataset.py.
Pull Request Process¶
Before Submitting¶
- Code follows Black formatting standards
- All tests pass locally
- New tests added for new functionality
- Documentation updated (README.md, AGENTS.md if architecture changed)
- Pre-commit hooks pass
- No unnecessary dependencies added
- AI assistance disclosed (see below)
PR Description Template¶
## Description
Brief description of changes
## Type of Change
- [ ] Bug fix
- [ ] New feature
- [ ] Breaking change
- [ ] Documentation update
## Testing
Describe testing performed
## AI Assistance
- Tools used: [e.g., Claude Code, GitHub Copilot]
- Model: [e.g., Claude Sonnet 4.5, GPT-4]
- Scope: [e.g., "Generated test cases", "Refactored function X"]
## Checklist
- [ ] Tests pass
- [ ] Code formatted with Black
- [ ] Documentation updated
Review Process¶
- Any major revamps to code or new ideas not discussed with a maintainer will be rejected
- Github passes Automated CI runs on all PRs (Black check, pytest suite)
- The maintainer's approval is required to merge:
mainneeds a review from the code owner in.github/CODEOWNERS, and a push after the approval needs approving again - You address review feedback promptly
- Keep PRs focused and reasonably sized - try to implement only one specific change per PR so it rollback will be easier.
AI-Assisted Development¶
TerraVision welcomes the use of AI tools for development! AI assistance can accelerate development, improve code quality, and help with documentation.
Disclosure Requirement¶
All AI use for coding must be disclosed in pull requests. Please include:
- Tools used: Name of AI tool(s) (e.g., Claude Code, GitHub Copilot, ChatGPT, Cursor)
- Model and version: Specific model used (e.g., Claude Sonnet 4.5, GPT-4 Turbo, Llama 3.1 70B)
- Scope of assistance: What the AI helped with (e.g., "Generated test fixtures", "Refactored VPC handler", "Wrote docstrings")
Example Disclosure¶
## AI Assistance
- **Tools**: Claude Code CLI
- **Model**: Claude Sonnet 4.5 (claude-sonnet-4-5-20250929)
- **Scope**:
- Generated initial implementation of Azure resource handlers
- Created unit tests for provider detection
- Assisted with debugging Terraform graph parsing logic
Why Disclose?¶
- Transparency: Helps maintainers understand the development process
- Quality: Allows reviewers to pay extra attention to AI-generated code
- Learning: Helps the community learn what AI tools work well for this project
- Best practices: Establishes a culture of responsible AI use
AI Best Practices¶
- Always review and test AI-generated code thoroughly
- Ensure AI-generated code follows TerraVision's architecture patterns
- Verify that AI suggestions align with provider-specific conventions
- Use AI to augment your skills, not replace understanding
Architecture Guidelines¶
Adding New Cloud Providers¶
When adding support for a new cloud provider:
- Create
modules/config/cloud_config_<provider>.pywith required constants: PROVIDER_PREFIX,ICON_LIBRARY,SPECIAL_RESOURCES, etc.- Create
modules/resource_handlers_<provider>.pywith handler functions - Add provider prefix to
PROVIDER_PREFIXESinprovider_detector.py - Add icons to
resource_images/<provider>/<category>/, add the provider toCLOUDSinscripts/generate_icon_classes.pyand run it, and map Terraform types inresource_classes/<provider>/terraform_icons.yml - Add tests in
tests/test_provider_detection.pyandtests/test_<provider>_resources.py
Multi-Cloud Support Pattern¶
TerraVision uses dynamic provider detection and configuration loading:
# Detect provider from resource prefixes
provider = get_primary_provider_or_default(tfdata)
# Load provider-specific configuration
config = load_config(provider)
# Use provider-specific constants
icons = config.ICON_LIBRARY
special_resources = config.SPECIAL_RESOURCES
Resource Handler Pattern¶
Special resources (VPCs, security groups, networks) follow a handler pattern:
# In cloud_config_<provider>.py
SPECIAL_RESOURCES = {
"provider_resource_type": "handler_function_name",
}
# In resource_handlers_<provider>.py
def handler_function_name(tfdata, resource):
# Implementation
return tfdata
Debug Workflow¶
When debugging issues:
# Generate debug output
python terravision.py draw --source <path> --debug
# Inspect tfdata.json
cat tfdata.json | jq '.graphdict'
# Replay from debug file (skips terraform init/plan)
python terravision.py draw --source tfdata.json
Project Structure¶
terravision/
├── modules/
│ ├── config/ # Provider-specific configurations
│ │ ├── cloud_config_aws.py
│ │ ├── cloud_config_azure.py
│ │ └── cloud_config_gcp.py
│ ├── resource_handlers_*.py # Provider resource handlers
│ ├── resource_transformers.py # Reusable Core graph transformers for all providers
│ ├── provider_detector.py # Provider detection logic
│ ├── config_loader.py # Dynamic config loading
│ ├── graphmaker.py # Core graph construction
│ ├── drawing.py # Graphviz rendering
│ └── helpers.py # Utility functions
├── resource_classes/ # Icon classes and Terraform type mappings by provider
│ ├── aws/
│ ├── azure/
│ ├── gcp/
│ └── generic/
├── tests/ # Test suite
├── terravision.py # Main CLI entry point
└── pyproject.toml # Poetry dependencies
Getting Help¶
- Documentation: See [docs/ folder for more detailed info
- Issues: Search existing issues or create a new one
- Discussions: Use GitHub Discussions for questions
- Examples: Check
tests/fixtures/for example Terraform code
License¶
By contributing to TerraVision, you agree that your contributions will be licensed under the same license as the project.
Thank you for contributing to TerraVision!