Skip to content

Test Scripts - Mac, Linux and Windows #118

Test Scripts - Mac, Linux and Windows

Test Scripts - Mac, Linux and Windows #118

Workflow file for this run

name: Test Scripts - Mac, Linux and Windows
permissions:
contents: read
on:
schedule:
# Run daily at 2 AM UTC
- cron: '0 2 * * *'
pull_request:
branches:
- main
workflow_dispatch:
jobs:
test-mac:
name: Test mac/run.sh on macOS
if: false
runs-on: macos-latest
timeout-minutes: 15
environment: BrowserStack
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Python 3.12
uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Set up Bash
run: |
echo "Bash version:"
bash --version
- name: Validate shell script syntax
run: |
echo "Validating mac/run.sh syntax..."
bash -n mac/run.sh
echo "✅ mac/run.sh syntax is valid"
- name: Validate supporting scripts syntax
run: |
echo "Validating supporting scripts..."
bash -n mac/common-utils.sh
bash -n mac/logging-utils.sh
bash -n mac/env-setup-run.sh
bash -n mac/user-interaction.sh
bash -n mac/env-prequisite-checks.sh
echo "✅ All supporting scripts are valid"
- name: Check if scripts are executable
run: |
chmod +x mac/run.sh
chmod +x mac/common-utils.sh
chmod +x mac/logging-utils.sh
chmod +x mac/env-setup-run.sh
chmod +x mac/user-interaction.sh
chmod +x mac/env-prequisite-checks.sh
echo "✅ All scripts are executable"
- name: Run ShellCheck on mac scripts
run: |
brew install shellcheck
echo "Running ShellCheck on mac scripts..."
shellcheck -x mac/run.sh || true
shellcheck -x mac/common-utils.sh || true
shellcheck -x mac/logging-utils.sh || true
shellcheck -x mac/env-setup-run.sh || true
shellcheck -x mac/user-interaction.sh || true
shellcheck -x mac/env-prequisite-checks.sh || true
echo "✅ ShellCheck analysis complete"
- name: Verify required dependencies
run: |
echo "Checking required dependencies..."
command -v bash && echo "✅ bash found"
command -v curl && echo "✅ curl found"
command -v git && echo "✅ git found"
command -v bc && echo "✅ bc found"
echo "All required dependencies are available"
- name: Test script sourcing (dry run)
run: |
set -e
echo "Testing script sourcing..."
bash -c "source mac/common-utils.sh && echo '✅ common-utils.sh sourced successfully'"
echo "✅ Script sourcing successful"
- name: Integration Test - Silent Mode Execution
if: success()
env:
BROWSERSTACK_USERNAME: ${{ secrets.BROWSERSTACK_USERNAME }}
BROWSERSTACK_ACCESS_KEY: ${{ secrets.BROWSERSTACK_ACCESS_KEY }}
TURL: https://bstackdemo.com
run: |
echo "Running integration tests in silent mode..."
# Set default values if secrets are not provided
BROWSERSTACK_USERNAME="${BROWSERSTACK_USERNAME:-test_user}"
BROWSERSTACK_ACCESS_KEY="${BROWSERSTACK_ACCESS_KEY:-test_key}"
export BROWSERSTACK_USERNAME
export BROWSERSTACK_ACCESS_KEY
export TURL
# Test configurations
test_configs=(
"web java"
"app java"
"web python"
"app python"
"web nodejs"
"app nodejs"
)
for config in "${test_configs[@]}"; do
read -r test_type tech_stack <<< "$config"
echo "================================"
echo "Testing: mac/run.sh --silent $test_type $tech_stack"
echo "================================"
# Run with timeout and capture exit code (macOS compatible)
bash mac/run.sh --silent "$test_type" "$tech_stack" >> "/tmp/run_test_${test_type}_${tech_stack}.log" 2>&1 &
job_pid=$!
# Wait with 600 second timeout using sleep loop (macOS compatible)
count=0
max_wait=600
while kill -0 "$job_pid" 2>/dev/null && [ $count -lt $max_wait ]; do
sleep 1
count=$((count + 1))
done
# Check if process is still running after timeout
if kill -0 "$job_pid" 2>/dev/null; then
echo "⚠️ mac/run.sh --silent $test_type $tech_stack timed out after 600 seconds"
kill -9 "$job_pid" 2>/dev/null || true
exit_code=124
else
wait "$job_pid" || exit_code=$?
fi
if [ -z "$exit_code" ] || [ "$exit_code" -eq 0 ] || [ "$exit_code" -eq 124 ]; then
echo "✅ mac/run.sh --silent $test_type $tech_stack completed (exit code: ${exit_code:-0})"
else
echo "⚠️ mac/run.sh --silent $test_type $tech_stack exited with code: $exit_code"
if [ -f "/tmp/run_test_${test_type}_${tech_stack}.log" ]; then
echo "Log output (last 20 lines):"
tail -n 20 "/tmp/run_test_${test_type}_${tech_stack}.log"
fi
fi
unset exit_code
done
echo "✅ All integration tests completed"
- name: Sync BrowserStack logs to workspace
if: always()
run: |
mkdir -p ${{ github.workspace }}/bs-logs
if [ -d ~/.browserstack/NOW/logs ]; then
cp -R ~/.browserstack/NOW/logs/* ${{ github.workspace }}/bs-logs/ || true
else
echo "No logs found in ~/.browserstack/NOW/logs"
fi
- name: Upload BrowserStack Logs as Artifacts
if: always()
uses: actions/upload-artifact@v4
with:
name: browserstack-logs-macos
path: |
${{ github.workspace }}/bs-logs
/tmp/run_test_*.log
retention-days: 30
if-no-files-found: ignore
test-windows:
name: Test win/run.ps1 on Windows
runs-on: windows-latest
timeout-minutes: 25
environment: BrowserStack
env:
ACTIONS_STEP_DEBUG: true
defaults:
run:
shell: powershell
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Node.js 20.x
uses: actions/setup-node@v4
with:
node-version: '20'
- name: Set up Python 3.12
uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Check PowerShell version
run: |
$PSVersionTable.PSVersion
Write-Host "✅ PowerShell version check complete"
- name: Enable PowerShell debug logging
run: |
Write-Host "Enabling PowerShell debug and verbose logging..."
$DebugPreference = "Continue"
$VerbosePreference = "Continue"
$ErrorActionPreference = "Continue"
Write-Host "✅ Debug logging enabled"
Write-Debug "Debug logging is now active"
Write-Verbose "Verbose logging is now active"
- name: Validate PowerShell script syntax
run: |
Write-Host "Validating win/run.ps1 syntax..."
$ScriptPath = "win/run.ps1"
$null = [System.Management.Automation.PSParser]::Tokenize((Get-Content -Raw $ScriptPath), [ref]$null)
Write-Host "✅ win/run.ps1 syntax is valid"
- name: Validate supporting PowerShell scripts syntax
run: |
Write-Host "Validating supporting PowerShell scripts..."
$Scripts = @(
"win/common-utils.ps1",
"win/logging-utils.ps1",
"win/env-prequisite-checks.ps1",
"win/user-interaction.ps1",
"win/env-setup-run.ps1",
"win/device-machine-allocation.ps1"
)
foreach ($Script in $Scripts) {
$null = [System.Management.Automation.PSParser]::Tokenize((Get-Content -Raw $Script), [ref]$null)
Write-Host "✅ $Script syntax is valid"
}
- name: Run PSScriptAnalyzer
run: |
$DebugPreference = "Continue"
$VerbosePreference = "Continue"
Write-Host "Installing PSScriptAnalyzer if needed..."
if (-not (Get-Module -ListAvailable -Name PSScriptAnalyzer)) {
Install-Module -Name PSScriptAnalyzer -Force -SkipPublisherCheck -Scope CurrentUser -Verbose
}
Write-Host "Running PSScriptAnalyzer..."
Invoke-ScriptAnalyzer -Path "win" -Recurse -ReportSummary -ErrorAction Continue -Verbose
Write-Host "✅ PSScriptAnalyzer analysis complete (continuing even if issues are found)"
- name: Check script file encoding
run: |
Write-Host "Checking PowerShell script encoding..."
$ScriptPath = "win/run.ps1"
$bytes = [System.IO.File]::ReadAllBytes($ScriptPath)
$encoding = "Unknown / ASCII / UTF-8 without BOM"
if ($bytes.Length -ge 3 -and $bytes[0] -eq 0xEF -and $bytes[1] -eq 0xBB -and $bytes[2] -eq 0xBF) {
$encoding = "UTF-8 with BOM"
} elseif ($bytes.Length -ge 2 -and $bytes[0] -eq 0xFF -and $bytes[1] -eq 0xFE) {
$encoding = "UTF-16 LE"
} elseif ($bytes.Length -ge 2 -and $bytes[0] -eq 0xFE -and $bytes[1] -eq 0xFF) {
$encoding = "UTF-16 BE"
}
Write-Host "Detected encoding (heuristic): $encoding"
Write-Host "✅ Encoding check complete"
- name: Verify required dependencies
run: |
Write-Host "Checking required dependencies..."
if (Get-Command curl.exe -ErrorAction SilentlyContinue) { Write-Host "✅ curl found" } else { Write-Host "⚠️ curl not found" }
if (Get-Command git.exe -ErrorAction SilentlyContinue) { Write-Host "✅ git found" } else { Write-Host "⚠️ git not found" }
Write-Host "✅ PowerShell dependencies verified"
- name: Check initial system resources
run: |
Write-Host "=== Initial System Resources ==="
# Get system memory info
$os = Get-CimInstance Win32_OperatingSystem
$totalMemoryGB = [math]::Round($os.TotalVisibleMemorySize / 1MB, 2)
$freeMemoryGB = [math]::Round($os.FreePhysicalMemory / 1MB, 2)
$usedMemoryGB = [math]::Round(($os.TotalVisibleMemorySize - $os.FreePhysicalMemory) / 1MB, 2)
$memoryPercent = [math]::Round(($usedMemoryGB / $totalMemoryGB) * 100, 2)
Write-Host "Total Physical Memory: $totalMemoryGB GB"
Write-Host "Free Physical Memory: $freeMemoryGB GB"
Write-Host "Used Physical Memory: $usedMemoryGB GB ($memoryPercent%)"
# Get CPU info
$cpu = Get-CimInstance Win32_Processor
Write-Host "CPU Name: $($cpu.Name)"
Write-Host "CPU Cores: $($cpu.NumberOfCores)"
Write-Host "CPU Logical Processors: $($cpu.NumberOfLogicalProcessors)"
# Get current CPU usage (average over 3 samples)
Write-Host "Measuring CPU usage..."
$cpuSamples = @()
for ($i = 0; $i -lt 3; $i++) {
$cpuSample = (Get-Counter '\Processor(_Total)\% Processor Time').CounterSamples[0].CookedValue
$cpuSamples += $cpuSample
Start-Sleep -Seconds 1
}
$avgCpu = [math]::Round(($cpuSamples | Measure-Object -Average).Average, 2)
Write-Host "Current CPU Usage: $avgCpu%"
# Get disk space
$disk = Get-CimInstance Win32_LogicalDisk -Filter "DeviceID='C:'"
$freeDiskGB = [math]::Round($disk.FreeSpace / 1GB, 2)
$totalDiskGB = [math]::Round($disk.Size / 1GB, 2)
$usedDiskGB = [math]::Round(($disk.Size - $disk.FreeSpace) / 1GB, 2)
Write-Host "C: Drive Free Space: $freeDiskGB GB / $totalDiskGB GB"
Write-Host "✅ Initial resource check complete"
- name: Integration Test - Silent Mode Execution
if: success()
env:
BROWSERSTACK_USERNAME: ${{ secrets.BROWSERSTACK_USERNAME }}
BROWSERSTACK_ACCESS_KEY: ${{ secrets.BROWSERSTACK_ACCESS_KEY }}
TURL: https://bstackdemo.com
run: |
$DebugPreference = "Continue"
$VerbosePreference = "Continue"
$ErrorActionPreference = "Continue"
Write-Host "Running integration tests in silent mode..."
Write-Debug "Debug logging enabled for integration tests"
Write-Verbose "Verbose logging enabled for integration tests"
# Use defaults if secrets are missing (for local / dry runs)
$BrowserStackUsername = if ($env:BROWSERSTACK_USERNAME) { $env:BROWSERSTACK_USERNAME } else { "test_user" }
$BrowserStackAccessKey = if ($env:BROWSERSTACK_ACCESS_KEY) { $env:BROWSERSTACK_ACCESS_KEY } else { "test_key" }
$TestUrl = $env:TURL
Write-Debug "BrowserStack Username: $BrowserStackUsername"
Write-Verbose "Test URL: $TestUrl"
$env:BROWSERSTACK_USERNAME = $BrowserStackUsername
$env:BROWSERSTACK_ACCESS_KEY = $BrowserStackAccessKey
$env:TURL = $TestUrl
# Absolute path is safer in CI
$scriptPath = Join-Path $env:GITHUB_WORKSPACE "win\run.ps1"
Write-Debug "Script path: $scriptPath"
$testConfigs = @(
@("web", "java"),
@("app", "java"),
@("web", "python"),
@("app", "python"),
@("web", "nodejs"),
@("app", "nodejs")
)
# Function to get system resources
function Get-SystemResources {
$os = Get-CimInstance Win32_OperatingSystem
$totalMemoryGB = [math]::Round($os.TotalVisibleMemorySize / 1MB, 2)
$freeMemoryGB = [math]::Round($os.FreePhysicalMemory / 1MB, 2)
$usedMemoryGB = [math]::Round(($os.TotalVisibleMemorySize - $os.FreePhysicalMemory) / 1MB, 2)
$memoryPercent = [math]::Round(($usedMemoryGB / $totalMemoryGB) * 100, 2)
$cpuSample = (Get-Counter '\Processor(_Total)\% Processor Time' -ErrorAction SilentlyContinue).CounterSamples[0].CookedValue
$cpuUsage = [math]::Round($cpuSample, 2)
# Get PowerShell process memory
$pwshProcess = Get-Process -Id $PID -ErrorAction SilentlyContinue
$pwshMemoryMB = if ($pwshProcess) { [math]::Round($pwshProcess.WorkingSet64 / 1MB, 2) } else { 0 }
return @{
TotalMemoryGB = $totalMemoryGB
FreeMemoryGB = $freeMemoryGB
UsedMemoryGB = $usedMemoryGB
MemoryPercent = $memoryPercent
CpuUsage = $cpuUsage
PwshMemoryMB = $pwshMemoryMB
}
}
$overallFailed = $false
$logRoot = Join-Path $env:TEMP "now-tests"
$resourceLogPath = Join-Path $logRoot "resource_usage.log"
New-Item -ItemType Directory -Force -Path $logRoot | Out-Null
# Log initial resources
$initialResources = Get-SystemResources
Write-Host "=== Initial Resources Before Tests ==="
Write-Host "Memory: $($initialResources.UsedMemoryGB) GB / $($initialResources.TotalMemoryGB) GB ($($initialResources.MemoryPercent)%)"
Write-Host "CPU: $($initialResources.CpuUsage)%"
Write-Host "PowerShell Memory: $($initialResources.PwshMemoryMB) MB"
"$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') - INITIAL - Memory: $($initialResources.UsedMemoryGB)GB/$($initialResources.TotalMemoryGB)GB ($($initialResources.MemoryPercent)%), CPU: $($initialResources.CpuUsage)%, Pwsh: $($initialResources.PwshMemoryMB)MB" | Out-File -FilePath $resourceLogPath -Append
foreach ($config in $testConfigs) {
$testType = $config[0]
$techStack = $config[1]
Write-Host "================================"
Write-Host "Testing: $scriptPath --silent $testType $techStack"
Write-Host "================================"
Write-Debug "Test type: $testType, Tech stack: $techStack"
# Get resources before test
$resourcesBefore = Get-SystemResources
Write-Host "--- Resources Before Test ---"
Write-Host "Memory: $($resourcesBefore.UsedMemoryGB) GB / $($resourcesBefore.TotalMemoryGB) GB ($($resourcesBefore.MemoryPercent)%)"
Write-Host "CPU: $($resourcesBefore.CpuUsage)%"
Write-Host "PowerShell Memory: $($resourcesBefore.PwshMemoryMB) MB"
"$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') - BEFORE [$testType/$techStack] - Memory: $($resourcesBefore.UsedMemoryGB)GB/$($resourcesBefore.TotalMemoryGB)GB ($($resourcesBefore.MemoryPercent)%), CPU: $($resourcesBefore.CpuUsage)%, Pwsh: $($resourcesBefore.PwshMemoryMB)MB" | Out-File -FilePath $resourceLogPath -Append
$logPath = Join-Path $logRoot "run_test_${testType}_${techStack}.log"
Write-Verbose "Log path: $logPath"
# Start background resource monitoring
$monitorJob = Start-Job -ScriptBlock {
param($logFile, $testName)
$endTime = (Get-Date).AddMinutes(10) # Monitor for max 10 minutes
while ((Get-Date) -lt $endTime) {
try {
$os = Get-CimInstance Win32_OperatingSystem
$usedMemoryGB = [math]::Round(($os.TotalVisibleMemorySize - $os.FreePhysicalMemory) / 1MB, 2)
$totalMemoryGB = [math]::Round($os.TotalVisibleMemorySize / 1MB, 2)
$memoryPercent = [math]::Round(($usedMemoryGB / $totalMemoryGB) * 100, 2)
$cpuSample = (Get-Counter '\Processor(_Total)\% Processor Time' -ErrorAction SilentlyContinue).CounterSamples[0].CookedValue
$cpuUsage = [math]::Round($cpuSample, 2)
"$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') - MONITOR [$testName] - Memory: $usedMemoryGB GB/$totalMemoryGB GB ($memoryPercent%), CPU: $cpuUsage%" | Out-File -FilePath $logFile -Append
} catch {
# Ignore errors in monitoring
}
Start-Sleep -Seconds 30 # Sample every 30 seconds
}
} -ArgumentList $resourceLogPath, "${testType}_${techStack}"
Write-Debug "Executing script: $scriptPath --silent $testType $techStack"
$startTime = Get-Date
& $scriptPath --silent $testType $techStack 2>&1 | Tee-Object -FilePath $logPath -Append
$exitCode = $LASTEXITCODE
$endTime = Get-Date
$duration = $endTime - $startTime
Write-Debug "Script exit code: $exitCode"
# Stop monitoring job
Stop-Job -Job $monitorJob -ErrorAction SilentlyContinue
Remove-Job -Job $monitorJob -ErrorAction SilentlyContinue
# Get resources after test
Start-Sleep -Seconds 2 # Brief pause to let system settle
$resourcesAfter = Get-SystemResources
Write-Host "--- Resources After Test ---"
Write-Host "Memory: $($resourcesAfter.UsedMemoryGB) GB / $($resourcesAfter.TotalMemoryGB) GB ($($resourcesAfter.MemoryPercent)%)"
Write-Host "CPU: $($resourcesAfter.CpuUsage)%"
Write-Host "PowerShell Memory: $($resourcesAfter.PwshMemoryMB) MB"
Write-Host "Test Duration: $($duration.TotalSeconds) seconds"
$memoryDelta = [math]::Round($resourcesAfter.UsedMemoryGB - $resourcesBefore.UsedMemoryGB, 2)
$cpuDelta = [math]::Round($resourcesAfter.CpuUsage - $resourcesBefore.CpuUsage, 2)
Write-Host "Memory Change: $memoryDelta GB"
Write-Host "CPU Change: $cpuDelta%"
"$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') - AFTER [$testType/$techStack] - Memory: $($resourcesAfter.UsedMemoryGB)GB/$($resourcesAfter.TotalMemoryGB)GB ($($resourcesAfter.MemoryPercent)%), CPU: $($resourcesAfter.CpuUsage)%, Pwsh: $($resourcesAfter.PwshMemoryMB)MB, Duration: $([math]::Round($duration.TotalSeconds, 2))s, MemoryDelta: ${memoryDelta}GB, CpuDelta: ${cpuDelta}%" | Out-File -FilePath $resourceLogPath -Append
if ($exitCode -eq 0) {
Write-Host "✅ $testType / $techStack completed (exit code: $exitCode)"
} else {
Write-Host "⚠️ $testType / $techStack exited with code: $exitCode"
$overallFailed = $true
if (Test-Path $logPath) {
Write-Host "Log output (last 20 lines):"
Get-Content -Path $logPath -Tail 20
}
}
}
if ($overallFailed) {
Write-Error "One or more configurations failed."
exit 1
}
Write-Host "✅ All integration tests completed successfully"
# Log final resources
$finalResources = Get-SystemResources
Write-Host "=== Final Resources After All Tests ==="
Write-Host "Memory: $($finalResources.UsedMemoryGB) GB / $($finalResources.TotalMemoryGB) GB ($($finalResources.MemoryPercent)%)"
Write-Host "CPU: $($finalResources.CpuUsage)%"
Write-Host "PowerShell Memory: $($finalResources.PwshMemoryMB) MB"
$totalMemoryDelta = [math]::Round($finalResources.UsedMemoryGB - $initialResources.UsedMemoryGB, 2)
$totalCpuDelta = [math]::Round($finalResources.CpuUsage - $initialResources.CpuUsage, 2)
Write-Host "Total Memory Change: $totalMemoryDelta GB"
Write-Host "Total CPU Change: $totalCpuDelta%"
"$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') - FINAL - Memory: $($finalResources.UsedMemoryGB)GB/$($finalResources.TotalMemoryGB)GB ($($finalResources.MemoryPercent)%), CPU: $($finalResources.CpuUsage)%, Pwsh: $($finalResources.PwshMemoryMB)MB, TotalMemoryDelta: ${totalMemoryDelta}GB, TotalCpuDelta: ${totalCpuDelta}%" | Out-File -FilePath $resourceLogPath -Append
Write-Host "Resource usage log saved to: $resourceLogPath"
- name: Check final system resources
if: always()
run: |
Write-Host "=== Final System Resources ==="
# Get system memory info
$os = Get-CimInstance Win32_OperatingSystem
$totalMemoryGB = [math]::Round($os.TotalVisibleMemorySize / 1MB, 2)
$freeMemoryGB = [math]::Round($os.FreePhysicalMemory / 1MB, 2)
$usedMemoryGB = [math]::Round(($os.TotalVisibleMemorySize - $os.FreePhysicalMemory) / 1MB, 2)
$memoryPercent = [math]::Round(($usedMemoryGB / $totalMemoryGB) * 100, 2)
Write-Host "Total Physical Memory: $totalMemoryGB GB"
Write-Host "Free Physical Memory: $freeMemoryGB GB"
Write-Host "Used Physical Memory: $usedMemoryGB GB ($memoryPercent%)"
# Get current CPU usage
Write-Host "Measuring CPU usage..."
$cpuSamples = @()
for ($i = 0; $i -lt 3; $i++) {
$cpuSample = (Get-Counter '\Processor(_Total)\% Processor Time').CounterSamples[0].CookedValue
$cpuSamples += $cpuSample
Start-Sleep -Seconds 1
}
$avgCpu = [math]::Round(($cpuSamples | Measure-Object -Average).Average, 2)
Write-Host "Current CPU Usage: $avgCpu%"
# Get top processes by memory
Write-Host "`n=== Top 10 Processes by Memory Usage ==="
Get-Process | Sort-Object WorkingSet64 -Descending | Select-Object -First 10 | Format-Table -Property Name, @{Name="Memory(MB)";Expression={[math]::Round($_.WorkingSet64 / 1MB, 2)}}, CPU, Id -AutoSize
# Get top processes by CPU
Write-Host "=== Top 10 Processes by CPU Usage ==="
Get-Process | Sort-Object CPU -Descending | Select-Object -First 10 | Format-Table -Property Name, CPU, @{Name="Memory(MB)";Expression={[math]::Round($_.WorkingSet64 / 1MB, 2)}}, Id -AutoSize
Write-Host "✅ Final resource check complete"
- name: Sync BrowserStack logs to workspace (Windows)
if: always()
run: |
$DebugPreference = "Continue"
$VerbosePreference = "Continue"
$dest = Join-Path $env:GITHUB_WORKSPACE "bs-logs"
Write-Debug "Destination directory: $dest"
New-Item -ItemType Directory -Force -Path $dest -Verbose | Out-Null
$bsLogPath = Join-Path $env:USERPROFILE ".browserstack\NOW\logs"
$tempLogDir = Join-Path $env:TEMP "now-tests"
Write-Debug "BrowserStack log path: $bsLogPath"
Write-Debug "Temp log directory: $tempLogDir"
if (Test-Path $bsLogPath) {
Write-Host "Copying logs from $bsLogPath"
Write-Verbose "Copying logs from $bsLogPath to $dest"
Copy-Item -Path (Join-Path $bsLogPath "*") -Destination $dest -Recurse -Force -ErrorAction SilentlyContinue -Verbose
} else {
Write-Host "No logs found at $bsLogPath"
Write-Debug "BrowserStack logs directory does not exist"
}
if (Test-Path $tempLogDir) {
Write-Host "Copying integration logs from $tempLogDir"
Write-Verbose "Copying integration logs from $tempLogDir to $dest"
Copy-Item -Path (Join-Path $tempLogDir "*") -Destination $dest -Recurse -Force -ErrorAction SilentlyContinue -Verbose
} else {
Write-Debug "Temp log directory does not exist"
}
# Copy resource usage log if it exists
$resourceLogPath = Join-Path $tempLogDir "resource_usage.log"
if (Test-Path $resourceLogPath) {
Write-Host "Copying resource usage log"
Copy-Item -Path $resourceLogPath -Destination $dest -Force -ErrorAction SilentlyContinue -Verbose
}
- name: Display resource usage summary
if: always()
run: |
$resourceLogPath = Join-Path $env:TEMP "now-tests\resource_usage.log"
if (Test-Path $resourceLogPath) {
Write-Host "=== Resource Usage Summary ==="
Write-Host "`nFull resource usage log:"
Get-Content -Path $resourceLogPath
Write-Host "`n✅ Resource usage summary displayed"
} else {
Write-Host "Resource usage log not found at $resourceLogPath"
}
- name: Upload BrowserStack Logs as Artifacts
if: always()
uses: actions/upload-artifact@v4
with:
name: browserstack-logs-windows
path: ${{ github.workspace }}/bs-logs
retention-days: 30
if-no-files-found: ignore
test-linux:
name: Test mac/run.sh on Linux
if: false
runs-on: ubuntu-latest
timeout-minutes: 15
environment: BrowserStack
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Python 3.12
uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Set up Bash
run: |
echo "Bash version:"
bash --version
- name: Validate shell script syntax
run: |
echo "Validating mac/run.sh syntax..."
bash -n mac/run.sh
echo "✅ mac/run.sh syntax is valid"
- name: Validate supporting scripts syntax
run: |
echo "Validating supporting scripts..."
bash -n mac/common-utils.sh
bash -n mac/logging-utils.sh
bash -n mac/env-setup-run.sh
bash -n mac/user-interaction.sh
bash -n mac/env-prequisite-checks.sh
echo "✅ All supporting scripts are valid"
- name: Check if scripts are executable
run: |
chmod +x mac/run.sh
chmod +x mac/common-utils.sh
chmod +x mac/logging-utils.sh
chmod +x mac/env-setup-run.sh
chmod +x mac/user-interaction.sh
chmod +x mac/env-prequisite-checks.sh
echo "✅ All scripts are executable"
- name: Install ShellCheck
run: |
echo "Installing ShellCheck..."
sudo apt-get update
sudo apt-get install -y shellcheck
shellcheck --version
- name: Run ShellCheck on mac scripts
run: |
echo "Running ShellCheck on mac scripts..."
shellcheck -x mac/run.sh || true
shellcheck -x mac/common-utils.sh || true
shellcheck -x mac/logging-utils.sh || true
shellcheck -x mac/env-setup-run.sh || true
shellcheck -x mac/user-interaction.sh || true
shellcheck -x mac/env-prequisite-checks.sh || true
echo "✅ ShellCheck analysis complete"
- name: Verify required dependencies
run: |
echo "Checking required dependencies..."
command -v bash && echo "✅ bash found"
command -v curl && echo "✅ curl found"
command -v git && echo "✅ git found"
command -v bc && echo "✅ bc found"
echo "All required dependencies are available"
- name: Test script sourcing (dry run)
run: |
set -e
echo "Testing script sourcing..."
bash -c "source mac/common-utils.sh && echo '✅ common-utils.sh sourced successfully'"
echo "✅ Script sourcing successful"
- name: Integration Test - Silent Mode Execution
if: success()
env:
BROWSERSTACK_USERNAME: ${{ secrets.BROWSERSTACK_USERNAME }}
BROWSERSTACK_ACCESS_KEY: ${{ secrets.BROWSERSTACK_ACCESS_KEY }}
TURL: https://bstackdemo.com
run: |
echo "Running integration tests in silent mode..."
# Set default values if secrets are not provided
BROWSERSTACK_USERNAME="${BROWSERSTACK_USERNAME:-test_user}"
BROWSERSTACK_ACCESS_KEY="${BROWSERSTACK_ACCESS_KEY:-test_key}"
export BROWSERSTACK_USERNAME
export BROWSERSTACK_ACCESS_KEY
export TURL
# Test configurations
test_configs=(
"web java"
"app java"
"web python"
"app python"
"web nodejs"
"app nodejs"
)
for config in "${test_configs[@]}"; do
read -r test_type tech_stack <<< "$config"
echo "================================"
echo "Testing: mac/run.sh --silent $test_type $tech_stack"
echo "================================"
# Run with timeout and capture exit code (using timeout command on Linux)
timeout 600 bash mac/run.sh --silent "$test_type" "$tech_stack" >> "/tmp/run_test_${test_type}_${tech_stack}.log" 2>&1 &
job_pid=$!
wait "$job_pid" || exit_code=$?
if [ -z "$exit_code" ] || [ "$exit_code" -eq 0 ] || [ "$exit_code" -eq 124 ]; then
echo "✅ mac/run.sh --silent $test_type $tech_stack completed (exit code: ${exit_code:-0})"
else
echo "⚠️ mac/run.sh --silent $test_type $tech_stack exited with code: $exit_code"
if [ -f "/tmp/run_test_${test_type}_${tech_stack}.log" ]; then
echo "Log output (last 20 lines):"
tail -n 20 "/tmp/run_test_${test_type}_${tech_stack}.log"
fi
fi
unset exit_code
done
echo "✅ All integration tests completed"
- name: Sync BrowserStack logs to workspace
if: always()
run: |
mkdir -p ${{ github.workspace }}/bs-logs
if [ -d ~/.browserstack/NOW/logs ]; then
cp -R ~/.browserstack/NOW/logs/* ${{ github.workspace }}/bs-logs/ || true
else
echo "No logs found in ~/.browserstack/NOW/logs"
fi
- name: Upload BrowserStack Logs as Artifacts
if: always()
uses: actions/upload-artifact@v4
with:
name: browserstack-logs-linux
path: |
${{ github.workspace }}/bs-logs
/tmp/run_test_*.log
retention-days: 30
if-no-files-found: ignore
test-summary:
name: Test Summary
runs-on: ubuntu-latest
needs: [test-mac, test-linux, test-windows]
if: always()
steps:
- name: Check test results
run: |
echo "=== Test Results Summary ==="
echo "macOS Tests: ${{ needs.test-mac.result }}"
echo "Linux Tests: ${{ needs.test-linux.result }}"
echo "Windows Tests: ${{ needs.test-windows.result }}"
if [ "${{ needs.test-mac.result }}" = "failure" ] || [ "${{ needs.test-linux.result }}" = "failure" ] || [ "${{ needs.test-windows.result }}" = "failure" ]; then
echo "❌ Some tests failed"
exit 1
fi
echo "✅ All tests passed!"
- name: Notify success
if: success()
run: |
echo "✅ All script validations passed successfully!"
echo "- mac/run.sh and supporting scripts validated on macOS and Linux"
echo "- win/run.ps1 and supporting scripts validated on Windows"