Purpose: These instructions guide GitHub Copilot's code suggestions and responses for this repository.
Scope: Applies to all files (**/*).
When generating code or providing suggestions, Copilot should:
- Prioritize security and maintainability over brevity
- Include appropriate error handling and logging
- Follow the language-specific conventions outlined below
- Generate tests alongside implementation code
- Include inline documentation for complex logic
- When suggesting code fixes, explain the issue first, then provide the solution
- Include examples of both correct and incorrect implementations
- For security-related suggestions, always explain the vulnerability being addressed
- When multiple solutions exist, present trade-offs between them
- Clarity over cleverness: Write code that is easy to read and maintain.
- Contextual comments: Explain the rationale and business logic, not just the implementation.
- Robust error handling: Provide clear, actionable messages and recovery paths.
- Architecture notes: Document design decisions, trade‑offs, and high‑level diagrams where useful.
- Performance awareness: Note algorithmic complexity and potential optimizations.
- Test-Driven Development for critical components.
- Edge case coverage: Null values, empty inputs, boundary conditions.
- Descriptive test names with clear scenario descriptions.
- Integration and end‑to‑end tests for complex workflows.
- Input validation: Sanitize and validate all external inputs.
- Least privilege: Restrict permissions to the minimum required.
- Secrets management: Store sensitive data in secure vaults or environment variables.
- Encryption: Protect data at rest and in transit.
- Audit logging: Record security‑relevant events for traceability.
Input Validation Example:
# CORRECT
def process_user_input(user_id: str) -> dict:
if not user_id or not user_id.isalnum():
raise ValueError("Invalid user ID format")
# Parameterized query
return db.query("SELECT * FROM users WHERE id = ?", [user_id])
# INCORRECT
def process_user_input(user_id: str) -> dict:
# SQL injection vulnerability
return db.query(f"SELECT * FROM users WHERE id = '{user_id}'")Begin each script with a help comment block:
<#
.SYNOPSIS Brief summary
.DESCRIPTION Detailed purpose and usage
.PARAMETER Parameter descriptions
.EXAMPLE Usage examples
.NOTES Author, date, version
.LINK Related documentation or repository
#>- Adhere to PEP 8 and automatic formatting (Black, 88 char line length).
- Use type hints and Google or NumPy–style docstrings.
- List dependencies in
requirements.txtorpyproject.toml. - Document virtual environment setup and activation.
- Use ES6+ features and TypeScript for type safety.
- Enforce ESLint and Prettier configuration.
- Document functions and modules with JSDoc comments.
- Prefer async/await patterns with proper error handling.
- Follow Microsoft naming and formatting conventions.
- Use XML documentation comments on public APIs.
- Apply async/await and dependency injection patterns.
Priorities: Security, Operational Excellence, Performance, Reliability, Cost.
- Place all Bicep files under
infra/. - Use single‑purpose, reusable modules.
- Default
targetScope = 'resourceGroup'and parameterize regions.
Module Organization Example:
infra/
├── main.bicep
├── modules/
│ ├── storage/
│ │ └── storageAccount.bicep
│ ├── network/
│ │ └── vnet.bicep
│ └── compute/
│ └── appService.bicep
Template Metadata (include in each file):
metadata name = 'resourceName'
metadata description = 'Template purpose'
metadata owner = 'Team or Individual'
metadata version = '1.0.0'
metadata lastUpdated = 'YYYY-MM-DD'
metadata documentation = 'Link to docs'Naming Conventions:
- Parameters:
paramName(camelCase). - Variables:
varName(camelCase). - Outputs:
outputName.
Parameter Best Practices:
- Include
@descriptionfor each parameter. - Use
@allowed,@minLength/@maxLengthand@minValue/@maxValuewhere applicable. - Provide sensible defaults and conditional values based on environment.
- NEVER provide default values for secure parameters (except empty strings or newGuid()).
- When referencing parameters between modules, ensure they're actually defined in the target module.
- Check parameter definitions in module files before passing values.
Resource Naming Example:
// CORRECT
param storageAccountPrefix string
var storageAccountName = '${storageAccountPrefix}${uniqueString(resourceGroup().id)}'
// INCORRECT
var storageAccountName = 'mystorageaccount123' // Hardcoded namesFunction Restrictions:
- Function
utcNow()can ONLY be used as parameter default values, never in variable declarations or resource properties. - Examples of correct usage:
param deploymentDate string = utcNow('yyyy-MM-dd') - Examples of incorrect usage:
var currentDate = utcNow('yyyy-MM-dd')ortags: { deployedOn: utcNow() } - Use
environment().suffixesfor service hostnames (like database.windows.net) to ensure cloud portability.
Resource Declarations:
- Use parent/child relationships with the
parentproperty, not string formatting like'${parent.name}/childName'. - Avoid unnecessary string interpolation like
'${singleVariable}'(use the variable directly). - Remove all unused variables and resources.
- Avoid unnecessary
dependsOnarrays - Bicep automatically handles most dependencies through property references.
Module References:
- When calling a module, verify all parameters exist in the target module.
- Use IDE features (if available) to validate parameter names before deployment.
- When updating module interfaces, ensure all calling code is updated accordingly.
- For complex integrations like Key Vault access policies, prefer separate modules with specific responsibilities.
Tagging and Defaults:
var defaultTags = union(tags, {
Environment: environment
Owner: 'TeamName'
Application: 'AppName'
})- Parameters: Always include
@description, use@secure()for secrets - Functions:
utcNow()only in parameter defaults - Dependencies: Let Bicep infer dependencies, avoid manual
dependsOn - Validation: Always run
az bicep buildbefore deployment - Modules: Verify parameter compatibility between parent and child modules
Bicep Deployment Workflow: Follow this systematic approach for all Bicep deployments:
-
Build - Compile Bicep to ARM template (optional for validation):
az bicep build --file main.bicep
-
Validate - Check syntax and catch errors early:
az bicep build --file main.bicep
- Review all linter warnings, even if they don't block compilation
- Address "no-unused-vars", "no-hardcoded-env-urls", "no-unnecessary-dependson", and "secure-parameter-default" warnings
-
Preview - Review changes before deployment:
az deployment group what-if --resource-group <rg> --template-file main.bicep
-
Deploy - Execute the deployment:
az deployment group create --resource-group <rg> --template-file main.bicep
Important Notes:
- The
az bicepcommands automatically transpile Bicep to JSON, so explicit JSON conversion is not required - Always run what-if deployments in production environments
- For container registries, set credentials via scripts post-deployment rather than within Bicep
- Avoid using
listCredentials()directly in module parameters
- Use Terraform v1.9+ features.
- Organize code with
main.tf,variables.tf,outputs.tf, andREADME.md. - Define variable
typeanddescriptionfor every input. - Mark sensitive outputs with
sensitive = true. - Enforce
terraform fmtandterraform validatein CI pipelines. - Use pre-commit hooks for formatting and security checks.
- Integrate with GitHub Actions or Azure Pipelines.
- Include
lint,format,validate,test, andsecurity scansteps. - Implement safe deployment strategies: canary, blue‑green, or ring deployments.
- Use feature flags for incremental rollouts and easy rollback.
- Never hardcode secrets or passwords in scripts or templates.
- For PowerShell scripts that require passwords:
- Use
Read-Host -AsSecureStringto capture passwords securely. - Validate password complexity requirements without storing plaintext.
- Use SecureString conversion only when absolutely necessary and clear variables immediately.
- Consider using KeyVault references when possible instead of direct password input.
- Use
- For Bicep templates:
- Use
@secure()annotation for all password and secret parameters. - Never provide defaults for secure parameters.
- Consider using KeyVault references for production deployments.
- Use
- Maintain a clear
README.mdwith project overview, setup, and usage. - Keep architecture diagrams and deployment guides up to date.
- Enable logging, monitoring, and alerting from day one.
- Version APIs and infrastructure changes using semantic versioning.
- Readability: Is the code easy to follow?
- Tests: Are there adequate unit and integration tests?
- Security: Are inputs validated and secrets secured?
- Performance: Are any obvious bottlenecks addressed?
- Documentation: Are public interfaces and modules documented?
- Compliance: Does it follow the guidelines above?
- Bicep Validation:
- Run
az bicep build --file main.bicepto catch all errors and warnings - Verify all module parameter references match the actual module parameters
- Ensure
utcNow()is only used in parameter default values - Remove unnecessary dependsOn entries
- Check that Key Vault references and permission assignments are properly configured
- Avoid using
listCredentials()directly in module parameters - For container registries, set credentials via scripts post-deployment rather than within Bicep
- Run
Follow conventional commits format:
feat:New featuresfix:Bug fixesdocs:Documentation changesrefactor:Code refactoringtest:Test additions/modificationschore:Maintenance tasks
## Summary
Brief description of changes
## Type of Change
- [ ] Bug fix
- [ ] New feature
- [ ] Breaking change
- [ ] Documentation update
## Testing
- [ ] Unit tests pass
- [ ] Integration tests pass
- [ ] Manual testing completed
## Security Considerations
- [ ] No hardcoded secrets
- [ ] Input validation implemented
- [ ] Permissions verifiedCopilot should NOT generate:
- Code with hardcoded credentials or connection strings
- Synchronous code when async alternatives exist
- Direct database queries without parameterization
- Console.log or print statements in production code
- Generic error messages like "An error occurred"
- Code that bypasses security validations
- Comments that simply restate the code
- Use verbose logging
- Enable detailed error messages
- Use local development containers
- Minimize logging verbosity
- Use structured logging (JSON format)
- Generic error messages for users
- Enable application insights or equivalent monitoring
| Language | Linter | Formatter | Test Framework |
|---|---|---|---|
| PowerShell | PSScriptAnalyzer | - | Pester |
| Python | pylint/flake8 | Black | pytest |
| JavaScript | ESLint | Prettier | Jest |
| C# | Roslyn Analyzers | dotnet format | xUnit |
| Bicep | bicep build | - | - |
| Terraform | tflint | terraform fmt | terratest |
Instructions Version: 1.0.0 Last Updated: 2025-06-19 Maintained By: jonathan-vella Review Schedule: Quarterly
For questions or improvements to these instructions, please open an issue or PR.