diff --git a/.github/actions/setup-dependencies/action.yml b/.github/actions/setup-dependencies/action.yml index 56233e6..fc5d13c 100644 --- a/.github/actions/setup-dependencies/action.yml +++ b/.github/actions/setup-dependencies/action.yml @@ -1,4 +1,6 @@ name: Setup dependencies +description: Download dependent libraries + runs: using: composite steps: diff --git a/.github/actions/setup-powershell/action.yml b/.github/actions/setup-powershell/action.yml new file mode 100644 index 0000000..064d870 --- /dev/null +++ b/.github/actions/setup-powershell/action.yml @@ -0,0 +1,52 @@ +name: Setup PowerShell +description: Setup PowerShell (Core) at a given version +inputs: + version: + description: Powershell version to install + required: true + +runs: + using: composite + steps: + # Download the powershell '.tar.gz' archive + - run: curl -L -o /tmp/powershell.tar.gz https://github.com/PowerShell/PowerShell/releases/download/v${{ inputs.version }}/powershell-${{ inputs.version }}-linux-x64.tar.gz + shell: bash + + # Create the target folder where powershell will be placed + - run: sudo mkdir -p /opt/microsoft/powershell/${{ inputs.version }} + shell: bash + + # Expand powershell to the target folder + - run: sudo tar zxf /tmp/powershell.tar.gz -C /opt/microsoft/powershell/${{ inputs.version }} + shell: bash + + # Set execute permissions + - run: sudo chmod +x /opt/microsoft/powershell/${{ inputs.version }}/pwsh + shell: bash + + # Unlink the original pwsh binary already present in the system + - run: sudo unlink /usr/bin/pwsh + shell: bash + + # Create the symbolic link that points to pwsh + - run: sudo ln -s /opt/microsoft/powershell/${{ inputs.version }}/pwsh /usr/bin/pwsh + shell: bash + + # Verify the installation by checking the `pwsh` command version. + - run: | + pwsh --version + [[ "$(pwsh --version)" == "PowerShell ${{ inputs.version == '6.0.0' && 'v6.0.0' || inputs.version }}" ]] + shell: bash + + # Setup old OpenSSL necessary for .NET Core 2.1. + - if: ${{ startsWith(inputs.version, '6.') }} + shell: bash + run: | + wget http://archive.ubuntu.com/ubuntu/pool/main/o/openssl1.0/libssl1.0.0_1.0.2n-1ubuntu5_amd64.deb + sudo dpkg -i libssl1.0.0_1.0.2n-1ubuntu5_amd64.deb + + # Verify the installation by using the `pwsh` shell. + - run: | + $PSVersionTable + if ( $PSVersionTable.PSVersion.ToString() -ne "${{ inputs.version }}" ) { exit 1 } + shell: pwsh diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 9608a4d..7ee6440 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -10,16 +10,36 @@ on: jobs: test: - name: ${{ matrix.os }} - ${{ matrix.shell }} - runs-on: ${{ matrix.os }}-latest + name: ${{ matrix.os }} - ${{ matrix.shell }} ${{ matrix.version }} + runs-on: ${{ matrix.os == 'ubuntu' && 'ubuntu-latest' || matrix.os == 'macos' && 'macos-latest' || matrix.os == 'windows' && 'windows-latest' || matrix.os }} strategy: fail-fast: false matrix: - os: [ubuntu, windows, macos] + # Test all Powershell (core) versions on Ubuntu. + # See https://github.com/getsentry/sentry-powershell/issues/13 and PR #12 about the disabled versions. + os: [ubuntu] shell: [pwsh] + version: + - '7.4.0' + - '7.3.0' + - '7.2.0' + # - '7.1.0' + # - '7.0.0' + - '6.2.0' + - '6.1.0' + # - '6.0.0' + # And test all built-in PowerShell/Windows Powershell versions on latest CI runner images include: + - os: ubuntu + shell: pwsh + - os: macos + shell: pwsh - os: windows + shell: pwsh + - os: windows-2019 + shell: powershell + - os: windows-2022 # same as windows-latest as of 02/2024 shell: powershell defaults: @@ -32,23 +52,48 @@ jobs: - name: Setup dependencies uses: ./.github/actions/setup-dependencies + - name: Setup PowerShell ${{ matrix.version }} + if: ${{ matrix.version != '' }} + uses: ./.github/actions/setup-powershell + with: + version: ${{ matrix.version }} + + - run: $PSVersionTable + # We don't test module loading with Pester because we're unable to unload the module between tests. # Testing as a separate step allows unloads it automatically at the step end. - name: Module loading run: | + . ./tools/settings.ps1 # Loading the first time Get-Item ./module/Sentry.psd1 | Import-Module -PassThru # This needs to return actual types (method overloads) - '[Sentry.SentrySdk]::init' + [Sentry.SentrySdk]::init # Loading the second time must be possible, without errors Get-Item ./module/Sentry.psd1 | Import-Module # And accessing APIs must still work too - '[Sentry.SentrySdk]::init' + [Sentry.SentrySdk]::init - name: Unit tests run: | + . ./tools/settings.ps1 Get-Item ./module/Sentry.psd1 | Import-Module - $config = New-PesterConfiguration - $config.Run.Path = "tests" - $config.TestResult.Enabled = $true - Invoke-Pester -Configuration $config + + # Pester doesn't work on PowerShell 6.0 so our testing here is extremely limited. + # Also, PowerShell 6.1 doesn't break when there's an error, regardless of the $ErrorActionPreference. + if (("${{ matrix.version }}" -eq "6.0.0") -or ("${{ matrix.version }}" -eq "6.1.0")) + { + if ([Sentry.SentrySdk].GetType().Name -ne 'RuntimeType') { throw "Invalid type on Sentry.SentrySdk" } + [Sentry.SentrySdk]::init('https://key@host/1') + if (-not [Sentry.SentrySdk]::IsEnabled) { throw "Sentry isn't enabled after init" } + [Sentry.SentrySdk]::close() + if ([Sentry.SentrySdk]::IsEnabled) { throw "Sentry is still enabled after close" } + Write-Host -ForegroundColor Green "All tests successful" + } + else + { + $config = New-PesterConfiguration + $config.Run.Path = "tests" + $config.TestResult.Enabled = $true + Invoke-Pester -Configuration $config + } diff --git a/dependencies/download.ps1 b/dependencies/download.ps1 index cb24ce5..adec923 100644 --- a/dependencies/download.ps1 +++ b/dependencies/download.ps1 @@ -1,6 +1,4 @@ -Set-StrictMode -Version latest -$ErrorActionPreference = 'Stop' - +. "$PSScriptRoot/../tools/settings.ps1" $downloadDir = "$PSScriptRoot/downloads" $propsDir = "$PSScriptRoot" $moduleDir = "$PSScriptRoot/../module" @@ -17,13 +15,17 @@ function CheckAssemblyVersion([string] $libFile, [string] $assemblyVersion) } } -function Download([string] $dependency, [string] $sourceTFM, [string] $targetTFM = $null) +function Download([string] $dependency, [string] $TFM, [string] $targetTFM = $null, [string] $assemblyVersion = $null) { - $targetTFM = "$targetTFM" -eq '' ? $sourceTFM : $targetTFM + $targetTFM = "$targetTFM" -eq '' ? $TFM : $targetTFM New-Item "$libDir/$targetTFM" -ItemType Directory -Force | Out-Null $props = (Get-Content "$propsDir/$dependency.properties" -Raw | ConvertFrom-StringData) - $assemblyVersion = $props.ContainsKey('assemblyVersion') ? $props.assemblyVersion : "$($props.version).0" + + if ("$assemblyVersion" -eq '') + { + $assemblyVersion = $props.ContainsKey('assemblyVersion') ? $props.assemblyVersion : "$($props.version).0" + } $targetLibFile = "$libDir/$targetTFM/$dependency.dll" $targetVersionFile = "$libDir/$targetTFM/$dependency.version" @@ -34,11 +36,12 @@ function Download([string] $dependency, [string] $sourceTFM, [string] $targetTFM try { CheckAssemblyVersion $targetLibFile $assemblyVersion + Write-Debug "Dependency $targetLibFile already exists and has the expected assembly version ($assemblyVersion), skipping." return } catch { - Write-Warning "$_, downloading again". + Write-Warning "$_, downloading again" } } @@ -86,7 +89,7 @@ function Download([string] $dependency, [string] $sourceTFM, [string] $targetTFM try { - extract "lib/$sourceTFM/$dependency.dll" $targetLibFile + extract "lib/$TFM/$dependency.dll" $targetLibFile if ($props.ContainsKey('licenseFile')) { extract $props.licenseFile $targetLicenseFile @@ -105,10 +108,15 @@ function Download([string] $dependency, [string] $sourceTFM, [string] $targetTFM $assemblyVersion | Out-File -NoNewline $targetVersionFile } -Download -Dependency 'Sentry' -SourceTFM 'net8.0' -Download -Dependency 'Sentry' -SourceTFM 'net6.0' -Download -Dependency 'Sentry' -SourceTFM 'netstandard2.0' -Download -Dependency 'Sentry' -SourceTFM 'net462' -Download -Dependency 'System.Text.Json' -SourceTFM 'net461' -TargetTFM 'net462' -Download -Dependency 'Microsoft.Bcl.AsyncInterfaces' -SourceTFM 'net461' -TargetTFM 'net462' -Download -Dependency 'System.Threading.Tasks.Extensions' -SourceTFM 'net461' -TargetTFM 'net462' +Download -Dependency 'Sentry' -TFM 'net8.0' +Download -Dependency 'Sentry' -TFM 'net6.0' +Download -Dependency 'Sentry' -TFM 'netstandard2.0' +Download -Dependency 'Sentry' -TFM 'net462' + +Download -Dependency 'System.Text.Json' -TFM 'net461' -TargetTFM 'net462' +Download -Dependency 'Microsoft.Bcl.AsyncInterfaces' -TFM 'net461' -TargetTFM 'net462' +Download -Dependency 'System.Threading.Tasks.Extensions' -TFM 'net461' -TargetTFM 'net462' + +Download -Dependency 'System.Text.Json' -TFM 'netstandard2.0' -assemblyVersion '6.0.0.0' +Download -Dependency 'Microsoft.Bcl.AsyncInterfaces' -TFM 'netstandard2.0' +Download -Dependency 'System.Threading.Tasks.Extensions' -TFM 'netstandard2.0' diff --git a/module/assemblies-loader.ps1 b/module/assemblies-loader.ps1 index 97b6963..05a6039 100644 --- a/module/assemblies-loader.ps1 +++ b/module/assemblies-loader.ps1 @@ -30,14 +30,13 @@ function GetTFM } $dir = Join-Path $dir (GetTFM) -$lib = Join-Path $dir 'Sentry.dll' # Check if the assembly is already loaded. $type = 'Sentry.SentrySdk' -as [type] if ($type) { $loadedAsssembly = $type.Assembly - $expectedAssembly = [Reflection.Assembly]::LoadFile($lib) + $expectedAssembly = [Reflection.Assembly]::LoadFile((Join-Path $dir 'Sentry.dll')) if ($loadedAsssembly.ToString() -ne $expectedAssembly.ToString()) { @@ -45,9 +44,16 @@ if ($type) Found: ($loadedAsssembly), location: $($loadedAsssembly.Location) Expected: ($expectedAssembly), location: $($expectedAssembly.Location)" } + else + { + Write-Debug "Sentry assembly is already loaded and at the expected version ($($expectedAssembly.GetName().Version)" + } } else { - Write-Debug "Loading Sentry assembly from $lib" - [Reflection.Assembly]::LoadFrom($lib) + Write-Debug "Loading assemblies from $($dir):" + Get-ChildItem -Path $dir -Filter '*.dll' | ForEach-Object { + Write-Debug "Loading assembly: $($_.Name)" + [Reflection.Assembly]::LoadFrom($_.FullName) | Write-Debug + } } diff --git a/tools/settings.ps1 b/tools/settings.ps1 new file mode 100644 index 0000000..be7d058 --- /dev/null +++ b/tools/settings.ps1 @@ -0,0 +1,10 @@ +# Common settings - use this in all scripts by sourcing: `. ./tools/settings.ps1` +Set-StrictMode -Version latest +$ErrorActionPreference = 'Stop' +$PSNativeCommandUseErrorActionPreference = $true + +# Enable debug logging in CI +if (Test-Path env:CI) +{ + $DebugPreference = 'Continue' +}