Skip to content

docs: second pass - consolidation and deduplication #60

docs: second pass - consolidation and deduplication

docs: second pass - consolidation and deduplication #60

Workflow file for this run

name: Test Scripts
on:
push:
branches: [ main, develop ]
pull_request:
branches: [ main ]
workflow_dispatch: # Allow manual trigger
jobs:
test-windows-scripts:
name: Test Windows PowerShell Scripts
runs-on: windows-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Install Pester and PSScriptAnalyzer
shell: pwsh
run: |
Install-Module -Name Pester -Force -SkipPublisherCheck -Scope CurrentUser
Install-Module -Name PSScriptAnalyzer -Force -SkipPublisherCheck -Scope CurrentUser
Import-Module Pester
Import-Module PSScriptAnalyzer
- name: Enable SSH Agent Service
shell: pwsh
run: |
Write-Host "[i] Enabling SSH agent service for tests..."
# Check if OpenSSH is installed
$sshAgent = Get-Service -Name "ssh-agent" -ErrorAction SilentlyContinue
if (-not $sshAgent) {
Write-Host "[i] Installing OpenSSH..."
Add-WindowsCapability -Online -Name OpenSSH.Client~~~~0.0.1.0
}
# Set service to Manual and start it
Set-Service -Name "ssh-agent" -StartupType Manual
Start-Service -Name "ssh-agent"
# Verify
$service = Get-Service -Name "ssh-agent"
Write-Host "[+] SSH agent status: $($service.Status)"
- name: Run PSScriptAnalyzer
shell: pwsh
run: |
Write-Host "[i] Running PSScriptAnalyzer on PowerShell scripts..." -ForegroundColor Blue
$results = @()
$scripts = Get-ChildItem -Path ".\Windows" -Recurse -Include "*.ps1", "*.psm1" -File
foreach ($script in $scripts) {
$analysis = Invoke-ScriptAnalyzer -Path $script.FullName -Severity Warning, Error
if ($analysis) {
$results += $analysis
}
}
if ($results.Count -gt 0) {
Write-Host ""
Write-Host "[!] PSScriptAnalyzer found $($results.Count) issues:" -ForegroundColor Yellow
$results | Group-Object -Property Severity | ForEach-Object {
Write-Host " $($_.Name): $($_.Count)" -ForegroundColor $(if ($_.Name -eq 'Error') { 'Red' } else { 'Yellow' })
}
Write-Host ""
# Show top issues by rule
Write-Host "[i] Top issues by rule:" -ForegroundColor Blue
$results | Group-Object -Property RuleName | Sort-Object Count -Descending | Select-Object -First 5 | ForEach-Object {
Write-Host " $($_.Name): $($_.Count)" -ForegroundColor Cyan
}
# Fail only on errors, warn on warnings
$errors = $results | Where-Object { $_.Severity -eq 'Error' }
if ($errors.Count -gt 0) {
Write-Host ""
Write-Host "[-] PSScriptAnalyzer found $($errors.Count) errors:" -ForegroundColor Red
$errors | ForEach-Object {
Write-Host " $($_.ScriptName):$($_.Line) - $($_.RuleName)" -ForegroundColor Red
}
exit 1
}
Write-Host ""
Write-Host "[+] No critical errors found (warnings are informational)" -ForegroundColor Green
} else {
Write-Host "[+] PSScriptAnalyzer: No issues found!" -ForegroundColor Green
}
- name: Run Pester tests with coverage
shell: pwsh
run: |
$Config = New-PesterConfiguration
$Config.Run.Path = ".\tests\Windows"
$Config.Output.Verbosity = "Detailed"
# Test results
$Config.TestResult.Enabled = $true
$Config.TestResult.OutputPath = "test-results-windows.xml"
$Config.TestResult.OutputFormat = "NUnitXml"
# Code coverage
$Config.CodeCoverage.Enabled = $true
$Config.CodeCoverage.Path = @(".\Windows\**\*.ps1")
$Config.CodeCoverage.OutputPath = "coverage.xml"
$Config.CodeCoverage.OutputFormat = "JaCoCo"
$Config.Run.PassThru = $true
$Result = Invoke-Pester -Configuration $Config
# Display coverage summary
Write-Host ""
Write-Host "[i] Code Coverage Summary:" -ForegroundColor Blue
Write-Host " Total Commands: $($Result.CodeCoverage.CommandsExecutedCount + $Result.CodeCoverage.CommandsMissedCount)"
Write-Host " Commands Executed: $($Result.CodeCoverage.CommandsExecutedCount)" -ForegroundColor Green
Write-Host " Commands Missed: $($Result.CodeCoverage.CommandsMissedCount)" -ForegroundColor Yellow
if ($Result.CodeCoverage.CommandsAnalyzedCount -gt 0) {
$coveragePercent = [math]::Round(($Result.CodeCoverage.CommandsExecutedCount / $Result.CodeCoverage.CommandsAnalyzedCount) * 100, 2)
Write-Host " Coverage: $coveragePercent%" -ForegroundColor $(if ($coveragePercent -ge 70) { "Green" } elseif ($coveragePercent -ge 50) { "Yellow" } else { "Red" })
}
- name: Upload test results
uses: actions/upload-artifact@v4
if: always()
with:
name: windows-test-results
path: test-results-windows.xml
- name: Upload coverage report
uses: actions/upload-artifact@v4
if: always()
with:
name: coverage-report
path: coverage.xml
- name: Add coverage comment to PR
if: github.event_name == 'pull_request'
uses: madrapps/jacoco-report@v1.7.1
with:
paths: coverage.xml
token: ${{ secrets.GITHUB_TOKEN }}
min-coverage-overall: 70
min-coverage-changed-files: 80
title: 'Code Coverage Report'
update-comment: true
- name: Generate coverage badge
if: github.ref == 'refs/heads/main'
shell: pwsh
run: |
# Calculate coverage percentage
[xml]$coverage = Get-Content coverage.xml
$total = [int]$coverage.report.counter | Where-Object { $_.type -eq "INSTRUCTION" } | Select-Object -ExpandProperty covered
$missed = [int]$coverage.report.counter | Where-Object { $_.type -eq "INSTRUCTION" } | Select-Object -ExpandProperty missed
$percent = if (($total + $missed) -gt 0) { [math]::Round(($total / ($total + $missed)) * 100, 0) } else { 0 }
Write-Host "[i] Coverage: $percent%"
# Badge color
$color = if ($percent -ge 80) { "brightgreen" } elseif ($percent -ge 60) { "green" } elseif ($percent -ge 40) { "yellow" } else { "red" }
# Save for potential badge generation
"COVERAGE_PERCENT=$percent" | Out-File -FilePath $env:GITHUB_ENV -Append
"COVERAGE_COLOR=$color" | Out-File -FilePath $env:GITHUB_ENV -Append
test-linux-scripts:
name: Test Linux Bash Scripts
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Install BATS
run: |
sudo apt-get update
sudo apt-get install -y bats
- name: Run BATS tests
run: |
bats tests/Linux/maintenance.bats
bats tests/Linux/CommonFunctions.bats
bats tests/Linux/SystemHealthCheck.bats
bats tests/Linux/SecurityHardening.bats
bats tests/Linux/ServiceHealthMonitor.bats
- name: Check script syntax (shellcheck)
run: |
sudo apt-get install -y shellcheck
echo "[i] Running shellcheck on Linux scripts..."
# Run shellcheck with specific exclusions for acceptable patterns
# SC2034: Unused variables (often used for configuration)
# SC1091: Cannot follow sourced file (common-functions.sh)
# SC2154: Variable referenced but not assigned (from sourced files)
find Linux -name "*.sh" -type f -exec shellcheck -x \
--exclude=SC2034,SC1091,SC2154,SC2155,SC2046,SC2178,SC2128 \
--severity=warning {} \;
echo "[+] Shellcheck passed"
- name: Verify no emojis in scripts
run: |
echo "[i] Checking for emojis in Linux scripts..."
if grep -rP '[\x{1F300}-\x{1F9FF}]|✅|❌|⚠️|ℹ️' Linux/ --include="*.sh"; then
echo "[-] ERROR: Found emojis in Linux scripts!"
exit 1
else
echo "[+] No emojis found - scripts comply with CLAUDE.md rules"
fi
security-scan:
name: Security Scan for Secrets
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0 # Full history for better detection
- name: Check for hardcoded secrets
run: |
echo "[i] Scanning for hardcoded credentials..."
# Check for potential passwords
if grep -rE 'password\s*=\s*["\x27].*["\x27]' . --exclude-dir=.git --exclude-dir=tests --exclude="*.md"; then
echo "[-] ERROR: Found hardcoded passwords!"
exit 1
fi
# Check for API keys
if grep -rE 'api[_-]?key\s*=\s*["\x27].*["\x27]' . --exclude-dir=.git --exclude-dir=tests --exclude="*.md"; then
echo "[-] ERROR: Found hardcoded API keys!"
exit 1
fi
# Check for private IPs (should use examples only)
if grep -rE '10\.143\.31\.' . --exclude-dir=.git --exclude="*.md" --exclude="CLAUDE.md"; then
echo "[-] ERROR: Found hardcoded private IPs!"
exit 1
fi
echo "[+] No hardcoded secrets found"
- name: Check for SSH private keys
run: |
echo "[i] Scanning for SSH private keys..."
if grep -r "BEGIN.*PRIVATE KEY" . --exclude-dir=.git --exclude-dir=tests --exclude-dir=.github --exclude-dir=.githooks; then
echo "[-] ERROR: Found SSH private keys in repository!"
exit 1
fi
echo "[+] No SSH private keys found"
validate-structure:
name: Validate Repository Structure
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Check required files exist
run: |
echo "[i] Validating repository structure..."
# Required documentation
test -f README.md || (echo "[-] Missing README.md" && exit 1)
test -f .gitignore || (echo "[-] Missing .gitignore" && exit 1)
test -f SECURITY.md || (echo "[-] Missing SECURITY.md" && exit 1)
test -f CONTRIBUTING.md || (echo "[-] Missing CONTRIBUTING.md" && exit 1)
# Required directories
test -d Windows/first-time-setup || (echo "[-] Missing Windows/first-time-setup" && exit 1)
test -d Windows/ssh || (echo "[-] Missing Windows/ssh" && exit 1)
test -d Linux/maintenance || (echo "[-] Missing Linux/maintenance" && exit 1)
test -d tests || (echo "[-] Missing tests directory" && exit 1)
echo "[+] Repository structure is valid"
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y libxml2-utils
- name: Check Windows package exports
run: |
echo "[i] Validating Windows package exports..."
test -f Windows/first-time-setup/winget-packages.json || (echo "[-] Missing winget-packages.json" && exit 1)
test -f Windows/first-time-setup/chocolatey-packages.config || (echo "[-] Missing chocolatey-packages.config" && exit 1)
# Validate JSON syntax
python3 -m json.tool Windows/first-time-setup/winget-packages.json > /dev/null || (echo "[-] Invalid JSON in winget-packages.json" && exit 1)
# Validate XML syntax
xmllint --noout Windows/first-time-setup/chocolatey-packages.config || (echo "[-] Invalid XML in chocolatey-packages.config" && exit 1)
echo "[+] Package exports are valid"
markdown-lint:
name: Lint Markdown Documentation
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Install markdownlint
run: |
sudo npm install -g markdownlint-cli
- name: Run markdownlint
run: |
markdownlint '**/*.md' --ignore node_modules --ignore .git || true
- name: Check for broken links (basic)
run: |
echo "[i] Checking for obviously broken markdown links..."
if grep -r '\[.*\](.*/\s\|.*\s/.*\|\s.*\s)' . --include="*.md" --exclude-dir=.git; then
echo "[!] WARNING: Found potentially malformed markdown links"
else
echo "[+] No obviously broken links found"
fi
test-summary:
name: Test Summary
runs-on: ubuntu-latest
needs: [test-windows-scripts, test-linux-scripts, security-scan, validate-structure]
if: always()
steps:
- name: Check test results
run: |
echo "[*] Test Summary:"
echo " - Windows Scripts: ${{ needs.test-windows-scripts.result }}"
echo " - Linux Scripts: ${{ needs.test-linux-scripts.result }}"
echo " - Security Scan: ${{ needs.security-scan.result }}"
echo " - Structure Validation: ${{ needs.validate-structure.result }}"
if [ "${{ needs.test-windows-scripts.result }}" != "success" ] || \
[ "${{ needs.test-linux-scripts.result }}" != "success" ] || \
[ "${{ needs.security-scan.result }}" != "success" ] || \
[ "${{ needs.validate-structure.result }}" != "success" ]; then
echo "[-] Some tests failed!"
exit 1
fi
echo "[+] All tests passed!"