Best Practices and Production
The Script That Broke Production
Code Organization and Structure
Script Template
<#
.SYNOPSIS
Brief description of what the script does.
.DESCRIPTION
Detailed description including prerequisites, dependencies, and expected behavior.
.PARAMETER ParameterName
Description of what this parameter does.
.EXAMPLE
.\Script-Name.ps1 -Parameter "Value"
Description of what this example does.
.NOTES
Author: Your Name
Date: 2024-01-15
Version: 1.0.0
.LINK
https://docs.yourcompany.com/scripts/script-name
#>
#Requires -Version 7.0
#Requires -Modules Az.Compute
[CmdletBinding(SupportsShouldProcess=$true)]
param(
[Parameter(Mandatory=$true, HelpMessage="Enter the resource name")]
[ValidateNotNullOrEmpty()]
[string]$ResourceName,
[Parameter(Mandatory=$false)]
[ValidateSet("Development", "Staging", "Production")]
[string]$Environment = "Development"
)
#region Configuration
$ErrorActionPreference = "Stop"
$ProgressPreference = "SilentlyContinue" # Faster execution
$logPath = "C:\Logs\$(Split-Path -Leaf $PSCommandPath)-$(Get-Date -Format 'yyyy-MM-dd').log"
$configPath = "C:\Config\config.json"
#endregion
#region Functions
function Write-ScriptLog {
[CmdletBinding()]
param(
[Parameter(Mandatory=$true)]
[string]$Message,
[Parameter(Mandatory=$false)]
[ValidateSet("INFO", "WARNING", "ERROR")]
[string]$Level = "INFO"
)
$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
$logMessage = "$timestamp [$Level] $Message"
# Write to file
$logMessage | Out-File -FilePath $logPath -Append
# Write to console
switch ($Level) {
"ERROR" { Write-Error $Message }
"WARNING" { Write-Warning $Message }
default { Write-Verbose $Message }
}
}
function Test-Prerequisites {
[CmdletBinding()]
param()
Write-ScriptLog "Checking prerequisites..."
# Check required modules
$requiredModules = @("Az.Compute", "Az.Storage")
foreach ($module in $requiredModules) {
if (-not (Get-Module -Name $module -ListAvailable)) {
throw "Required module not found: $module"
}
}
# Check configuration file
if (-not (Test-Path $configPath)) {
throw "Configuration file not found: $configPath"
}
Write-ScriptLog "Prerequisites validated successfully"
}
#endregion
#region Main Script
try {
Write-ScriptLog "Script started: $PSCommandPath"
Write-ScriptLog "Parameters: ResourceName=$ResourceName, Environment=$Environment"
# Validate prerequisites
Test-Prerequisites
# Load configuration
$config = Get-Content $configPath | ConvertFrom-Json
Write-ScriptLog "Configuration loaded"
# Main logic here
if ($PSCmdlet.ShouldProcess($ResourceName, "Process resource")) {
# Your code here
Write-ScriptLog "Processing $ResourceName in $Environment environment"
}
Write-ScriptLog "Script completed successfully"
exit 0
}
catch {
Write-ScriptLog "Script failed: $_" -Level "ERROR"
Write-ScriptLog $_.ScriptStackTrace -Level "ERROR"
exit 1
}
finally {
Write-ScriptLog "Script execution ended"
}
#endregionNaming Conventions
PowerShell Style Guide
PSScriptAnalyzer
Installation
Usage
Custom Rules
Testing with Pester
Installation
Basic Test
Running Tests
Secrets Management
Using Environment Variables
Using Azure Key Vault
Using Secret Management Module
CI/CD Integration
GitHub Actions Example
Azure DevOps Example
Performance Optimization
Measure Performance
Optimization Tips
Documentation
Comment Your Code
README.md for Script Repositories
Usage
Configuration
Troubleshooting
Contributing
License
Last updated