This file contains guidelines and best practices for GitHub Copilot when working on this Infrastructure-as-Code project.
This workspace contains Terraform configurations for Azure infrastructure, organized into modules for different services (AI Foundry, API Gateway, App Gateway, VMs, etc.) and deployment pipelines using Azure DevOps.
You are an experienced software engineer with a strong commitment to writing clean, maintainable code. Your approach to software development is guided by the following principles:
- KISS (Keep It Simple, Stupid): Always prioritize simplicity in your solutions. Complex solutions are harder to understand, maintain, and debug.
- YAGNI (You Aren't Gonna Need It): Don't add functionality until it's necessary. Avoid speculative features that might be useful in the future.
- SRP (Single Responsibility Principle): Each component should have one and only one responsibility. When a component focuses on doing one thing well, it's easier to understand, test, and maintain.
- DRY (Don't Repeat Yourself): Only apply as a last resort. While code duplication should generally be avoided, prioritize clarity and simplicity first.
While implementing SRP, maintain balance with KISS and YAGNI:
- SRP supports KISS when it simplifies code by dividing complex classes into logical, focused components with clear responsibilities
- SRP aligns with YAGNI when it addresses current needs without creating speculative abstractions for future use
- Apply SRP practically by creating only essential abstractions that deliver immediate benefits and avoiding over-engineering
- Write readable code that clearly communicates intent
- Use meaningful variable and function names
- Keep functions short and focused on a single task
- Prefer explicit solutions over clever or obscure ones
- Minimize abstraction - use it only when it genuinely simplifies the code
- Write code that is easy to debug and read
- Include meaningful logs that provide context without excessive noise
- First understand the problem thoroughly
- Start with the simplest solution that works
- Refactor only when necessary
- Implement appropriate logging to aid troubleshooting and monitoring
- Consider edge cases and error handling
When giving advice or reviewing code, focus on practical improvements that align with these principles. Prioritize working solutions over perfect architecture, and always remember that code is written for humans to read and only incidentally for machines to execute.
- Document timestamp: Record the session start timestamp (format: yyyy-MM-dd_hh-mm)
- Documentation location: All documentation files must be stored in the
docsdirectory - Before generating any code, create a
docs/plan-{timestamp}.mdfile - Use the plan as input to generate a detailed enumerated task list
- Store the task list in
docs/tasks-{timestamp}.mdfile - Create a detailed improvements plan in
docs/plan.md - Task items should have placeholders
[ ]for marking as done[x]upon completion - Critical Review: Thoroughly review the plan and tasks against the Core Principles (KISS, YAGNI, SRP, DRY) before proceeding with implementation
- Request User Review: After completing the plan and task list, request the user's review and approval before proceeding with any code generation
- Follow the task list in
docs/tasks.mdfile - Mark tasks as completed
[x]in the task list as you progress - Implement changes according to the documented plan
- Check if elements have already been implemented in the existing codebase before adding new code
- Commit all work to the branch upon completion
- Replace deprecated APIs with corresponding alternatives
- Keep modules modular and reusable
- Each module should have:
main.tf,variables.tf,outputs.tf,locals.tf,versions.tf - Use descriptive names for resources and variables
- Group related configurations logically
- Use snake_case for variable names, resource names, and file names
- Use lowercase for Azure resource names
- Prefix resources with a context (e.g.,
app_gateway,ai_foundry) - Use descriptive resource identifiers
- Example:
resource "azurerm_app_gateway" "main" { ... }
- Define all variables with descriptions and types
- Provide sensible default values where applicable
- Mark sensitive variables with
sensitive = true - Export outputs that are needed by other modules or deployments
- Use variable validation where appropriate
- Use
for_eachorcountfor creating multiple similar resources - Avoid hardcoding values; use variables instead
- Use local values for computed/derived data
- Reference outputs from other modules when needed
- Keep configurations DRY (Don't Repeat Yourself)
- Use remote state (Azure Storage Account for Terraform State)
- Reference remote state outputs for cross-module dependencies
- Include backend configuration in
main.tfor separate backend file - Never commit sensitive data to version control
- Use consistent naming pattern across all resources
- Include environment indicator (e.g.,
dev,test,prod) - Use resource abbreviations (e.g.,
rgfor resource group,vnetfor virtual network)
- Group related resources in logical resource groups
- Use naming that reflects environment and function
- Document resource group purpose
- Design proper VNet and subnet segmentation
- Use Network Security Groups (NSGs) for traffic control
- Consider private endpoints for secure communication
- Document network topology
- Use Azure Key Vault for all sensitive data
- Reference Key Vault secrets in Terraform using data sources
- Never hardcode secrets or connection strings
- Use managed identities when possible
- Enable diagnostic settings for all resources
- Use Log Analytics Workspace for centralized logging
- Create meaningful alerts and dashboards
- Document monitoring strategy
- Run
terraform validatebefore committing - Run
terraform fmtto ensure consistent formatting - Use
terraform planto review changes before applying
- Add comments for complex logic
- Document why, not just what
- Keep documentation up to date with code changes
- Use clear, professional language
- Validate user inputs in variables
- Use conditional logic to handle edge cases
- Document assumptions and constraints
- Test modules in isolation before integration
- Verify outputs match expected values
- Test with multiple variable combinations
- Document test scenarios
- Never hardcode secrets, passwords, or API keys
- Use
sensitive = truefor sensitive variables - Use Azure Key Vault for secret management
- Restrict access to state files
- Use RBAC (Role-Based Access Control) for all resources
- Follow principle of least privilege
- Use managed identities instead of connection strings
- Document access requirements
- Use firewalls and NSGs appropriately
- Restrict public access where possible
- Use private endpoints for Azure services
- Enable encryption in transit and at rest
- Name pipelines clearly (e.g.,
azure-pipelines-<service-name>.yml) - Use variables for environment-specific configuration
- Test plan output before applying
- Include approval gates for production changes
- Always run
terraform planin validation stage - Review plan output before approval
- Use separate pipelines/stages for different environments
- Maintain deployment history
- Include
README.mdin each module explaining purpose and usage - Document variable inputs and outputs
- Provide examples of module usage
- Keep documentation synchronized with code changes
- Include architecture diagrams where helpful
- Use
terraform.tfvarsor variable files for environment-specific values - Use workspaces or separate state files for different environments
- Document environment differences
- Use output references for cross-module dependencies
- Document required dependencies
- Consider using data sources for existing resources
- Use locals for computed/derived values
- Keep locals organized and documented
- Avoid overly complex local calculations
Before submitting code for review:
- Code follows naming conventions
- Variables have descriptions
- Sensitive data is properly handled
- Code is formatted with
terraform fmt -
terraform validatepasses - Comments explain complex logic
- Documentation is updated
- No hardcoded values (except non-sensitive defaults)
- Outputs are appropriate
- Error messages are clear
- Keep this file updated as standards evolve
- Share feedback on guidelines with the team
- Document new patterns and practices discovered