You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@logging.apache.org by fr...@apache.org on 2026/09/25 11:41:19 UTC
(logging-log4net) branch Feature/327-release-script-tests created (now 54435a71)
This is an automated email from the ASF dual-hosted git repository.
FreeAndNil pushed a change to branch Feature/327-release-script-tests
in repository https://gitbox.apache.org/repos/asf/logging-log4net.git
at 54435a71 Pester tests for build-release and build-preview #327
This branch includes the following new commits:
new 54435a71 Pester tests for build-release and build-preview #327
The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
(logging-log4net) 01/01: Pester tests for build-release and build-preview #327
Posted by fr...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
FreeAndNil pushed a commit to branch Feature/327-release-script-tests
in repository https://gitbox.apache.org/repos/asf/logging-log4net.git
commit 54435a7159653279ce2af0308f7962df7c89be1e
Author: Jan Friedrich <fr...@apache.org>
AuthorDate: Fri Sep 25 13:40:52 2026 +0200
Pester tests for build-release and build-preview #327
- a failing native command stops both scripts before signing or
tagging, and nothing is tagged without confirmation
- build-release shipped verify-release.Tests.ps1 without hash or
signature
- CI runs mvnw from pwsh, where mvnw.cmd 3.2.0 failed its checksum
---
.github/workflows/build.yaml | 15 ++++---
scripts/FakeCommands.TestHelper.ps1 | 88 +++++++++++++++++++++++++++++++++++++
scripts/build-preview.Tests.ps1 | 48 ++++++++++++++++++++
scripts/build-release.Tests.ps1 | 65 +++++++++++++++++++++++++++
scripts/build-release.ps1 | 2 +-
src/changelog/3.5.0/.release.xml | 2 +-
6 files changed, 211 insertions(+), 9 deletions(-)
diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml
index 10155a10..dbf19026 100644
--- a/.github/workflows/build.yaml
+++ b/.github/workflows/build.yaml
@@ -62,9 +62,14 @@ jobs:
- name: Release script tests
shell: pwsh
run: |
- $result = Invoke-Pester ./scripts/verify-release.Tests.ps1 -Output Detailed -PassThru
+ $result = Invoke-Pester ./scripts -Output Detailed -PassThru
if ($result.FailedCount -ne 0) { exit 1 }
+ # From pwsh, as build-release.ps1 calls it: mvnw.cmd 3.2.0 failed its checksum there on Windows.
+ - name: Maven wrapper
+ shell: pwsh
+ run: ./mvnw -v
+
# Runs the same probes twice, JIT compiled and published with Native AOT, so that a
# difference between the two is caused by AOT rather than by the platform. The project
# knows which probes are expected to fail in each mode and exits non-zero when reality
@@ -74,12 +79,10 @@ jobs:
env:
"log4net.AotEnvironmentProbe": from-environment
run: |
+ $PSNativeCommandUseErrorActionPreference = $true
dotnet run --project ./src/log4net.Tests.Aot/log4net.Tests.Aot.csproj -c Release
- if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
dotnet publish ./src/log4net.Tests.Aot/log4net.Tests.Aot.csproj -c Release -o ./aot-probes
- if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
& "./aot-probes/log4net.Tests.Aot$($IsWindows ? '.exe' : '')"
- if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
# A process that hosts the runtime natively has no entry assembly, so the configuration
# system cannot work out where the config file is (issue #162). The check owns the process
@@ -93,6 +96,4 @@ jobs:
# makes it a green that cannot fail for the reason the check exists.
- name: AOT probes, no entry assembly
shell: pwsh
- run: |
- dotnet run --project ./src/log4net.Tests.Aot/log4net.Tests.Aot.csproj -c Release -- --no-entry-assembly
- if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
\ No newline at end of file
+ run: dotnet run --project ./src/log4net.Tests.Aot/log4net.Tests.Aot.csproj -c Release -- --no-entry-assembly
\ No newline at end of file
diff --git a/scripts/FakeCommands.TestHelper.ps1 b/scripts/FakeCommands.TestHelper.ps1
new file mode 100644
index 00000000..280ea4cd
--- /dev/null
+++ b/scripts/FakeCommands.TestHelper.ps1
@@ -0,0 +1,88 @@
+#Requires -Version 7.4
+
+<#
+.SYNOPSIS
+ Runs a build script in a scratch tree against fake native commands, for the Pester tests.
+
+.DESCRIPTION
+ The fakes log every call and create the files the scripts go on to read, so a test sees which
+ commands ran without building, signing, tagging or pushing anything.
+#>
+
+# Logs its call, fails when named in FAKE_FAIL, and otherwise writes the files the real command
+# would, where it is told to, so a wrong output path fails as it would for real.
+$script:FakeCommand = @'
+param([string]$Name)
+Add-Content -Path $env:FAKE_LOG -Value "$Name $($args -join ' ')"
+if ($env:FAKE_FAIL -eq $Name) { exit 1 }
+$outputs = switch ($Name)
+{
+ 'dotnet'
+ {
+ $version = ($args -join ' ') -replace '.*PackageVersion=(\S+).*', '$1'
+ $build = "$(Split-Path $PSScriptRoot)/build"
+ "$build/artifacts/log4net.$version.nupkg", "$build/artifacts/log4net.Ext.Mail.$version.nupkg", "$build/Release/net462/log4net.dll"
+ }
+ 'git' { if ($args[0] -eq 'archive') { $args[$args.IndexOf('--output') + 1] } }
+ 'zip' { $args[1] }
+}
+$outputs | ForEach-Object { New-Item -ItemType File -Force -Path $_ | Out-Null }
+'@
+
+function New-ScratchTree
+{
+ param ([Parameter(Mandatory)][string]$Script)
+
+ $root = New-Item -ItemType Directory -Path (Join-Path ([System.IO.Path]::GetTempPath()) ([guid]::NewGuid()))
+ $scripts = New-Item -ItemType Directory -Path (Join-Path $root 'scripts')
+ $bin = New-Item -ItemType Directory -Path (Join-Path $root 'fakebin')
+ Copy-Item (Join-Path $PSScriptRoot $Script) $scripts
+ Copy-Item (Join-Path $PSScriptRoot 'verify-release.*') $scripts
+ 'license' | Set-Content (Join-Path $root 'LICENSE')
+ 'notice' | Set-Content (Join-Path $root 'NOTICE')
+ Set-Content -Path (Join-Path $bin 'fake.ps1') -Value $script:FakeCommand
+ foreach ($name in 'dotnet', 'git', 'gpg', 'zip', 'mvnw')
+ {
+ # mvnw is called by path from the root, the others through PATH.
+ $directory = $name -eq 'mvnw' ? $root : $bin
+ if ($IsWindows)
+ {
+ Set-Content -Path (Join-Path $directory "$name.cmd") -Value "@pwsh -NoProfile -File `"$bin\fake.ps1`" $name %*`r`n@exit /b %ERRORLEVEL%"
+ }
+ else
+ {
+ $path = Join-Path $directory $name
+ Set-Content -Path $path -Value "#!/bin/sh`nexec pwsh -NoProfile -File '$bin/fake.ps1' $name `"`$@`""
+ chmod +x $path
+ }
+ }
+ return $root.FullName
+}
+
+function Invoke-InScratchTree
+{
+ param ([Parameter(Mandatory)][string]$Root, [Parameter(Mandatory)][string]$Script, [string]$Fail)
+
+ $log = Join-Path $Root 'calls.log'
+ New-Item -ItemType File -Path $log -Force | Out-Null
+ $path = $env:PATH
+ try
+ {
+ $env:PATH = (Join-Path $Root 'fakebin') + [System.IO.Path]::PathSeparator + $path
+ $env:FAKE_LOG = $log
+ $env:FAKE_FAIL = $Fail
+ # NonInteractive makes the confirmation pause throw, standing in for a release manager who says no.
+ $output = pwsh -NoProfile -NonInteractive -File (Join-Path $Root 'scripts' $Script) 2>&1
+ $exitCode = $LASTEXITCODE
+ }
+ finally
+ {
+ $env:PATH = $path
+ Remove-Item Env:FAKE_LOG, Env:FAKE_FAIL -ErrorAction SilentlyContinue
+ }
+ return [pscustomobject]@{
+ ExitCode = $exitCode
+ Calls = @(Get-Content $log | ForEach-Object { ($_ -split ' ')[0..1] -join ' ' })
+ Output = $output -join [Environment]::NewLine
+ }
+}
diff --git a/scripts/build-preview.Tests.ps1 b/scripts/build-preview.Tests.ps1
new file mode 100644
index 00000000..55617312
--- /dev/null
+++ b/scripts/build-preview.Tests.ps1
@@ -0,0 +1,48 @@
+#Requires -Version 7.4
+#Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0' }
+
+<#
+.SYNOPSIS
+ Checks that build-preview.ps1 stops at the first failure and tags nothing unconfirmed.
+
+.DESCRIPTION
+ Runs the script against fake native commands, so nothing is built, signed, tagged or pushed.
+
+ Run with: Invoke-Pester ./scripts/build-preview.Tests.ps1
+#>
+
+BeforeAll {
+ . (Join-Path $PSScriptRoot 'FakeCommands.TestHelper.ps1')
+}
+
+Describe 'build-preview.ps1' {
+ BeforeEach {
+ $script:Root = New-ScratchTree -Script 'build-preview.ps1'
+ }
+
+ AfterEach {
+ Remove-Item $script:Root -Recurse -Force -ErrorAction SilentlyContinue
+ }
+
+ It 'signs nothing when the build fails' {
+ $result = Invoke-InScratchTree -Root $script:Root -Script 'build-preview.ps1' -Fail 'dotnet'
+
+ $result.ExitCode | Should -Not -Be 0
+ $result.Calls | Should -Be @('dotnet build')
+ }
+
+ It 'tags nothing when signing fails' {
+ $result = Invoke-InScratchTree -Root $script:Root -Script 'build-preview.ps1' -Fail 'gpg'
+
+ $result.ExitCode | Should -Not -Be 0
+ $result.Calls | Should -Be @('dotnet build', 'gpg --armor')
+ }
+
+ It 'signs both packages and tags nothing without confirmation' {
+ $result = Invoke-InScratchTree -Root $script:Root -Script 'build-preview.ps1'
+
+ $result.ExitCode | Should -Not -Be 0
+ $result.Output | Should -BeLike '*NonInteractive*'
+ $result.Calls | Should -Be @('dotnet build', 'gpg --armor', 'gpg --armor')
+ }
+}
diff --git a/scripts/build-release.Tests.ps1 b/scripts/build-release.Tests.ps1
new file mode 100644
index 00000000..12563471
--- /dev/null
+++ b/scripts/build-release.Tests.ps1
@@ -0,0 +1,65 @@
+#Requires -Version 7.4
+#Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0' }
+
+<#
+.SYNOPSIS
+ Checks that build-release.ps1 stops at the first failure and tags nothing unconfirmed.
+
+.DESCRIPTION
+ Runs the script against fake native commands, so nothing is built, signed, tagged or pushed.
+
+ Run with: Invoke-Pester ./scripts/build-release.Tests.ps1
+#>
+
+BeforeAll {
+ . (Join-Path $PSScriptRoot 'FakeCommands.TestHelper.ps1')
+}
+
+Describe 'build-release.ps1' {
+ BeforeEach {
+ $script:Root = New-ScratchTree -Script 'build-release.ps1'
+ }
+
+ AfterEach {
+ Remove-Item $script:Root -Recurse -Force -ErrorAction SilentlyContinue
+ }
+
+ It 'signs nothing when the build fails' {
+ $result = Invoke-InScratchTree -Root $script:Root -Script 'build-release.ps1' -Fail 'dotnet'
+
+ $result.ExitCode | Should -Not -Be 0
+ $result.Calls | Should -Be @('dotnet test')
+ }
+
+ It 'builds no site when signing fails' {
+ $result = Invoke-InScratchTree -Root $script:Root -Script 'build-release.ps1' -Fail 'gpg'
+
+ $result.ExitCode | Should -Not -Be 0
+ $result.Calls | Should -Be @('dotnet test', 'git archive', 'zip -r', 'gpg --armor')
+ }
+
+ It 'asks for no tag when the site build fails' {
+ $result = Invoke-InScratchTree -Root $script:Root -Script 'build-release.ps1' -Fail 'mvnw'
+
+ $result.ExitCode | Should -Not -Be 0
+ $result.Output | Should -Not -BeLike '*NonInteractive*'
+ $result.Calls[-1] | Should -Be 'mvnw site'
+ }
+
+ It 'signs all six artifacts and tags nothing without confirmation' {
+ $result = Invoke-InScratchTree -Root $script:Root -Script 'build-release.ps1'
+
+ $result.ExitCode | Should -Not -Be 0
+ $result.Output | Should -BeLike '*NonInteractive*'
+ $result.Calls | Should -Be @('dotnet test', 'git archive', 'zip -r',
+ 'gpg --armor', 'gpg --armor', 'gpg --armor', 'gpg --armor', 'gpg --armor', 'gpg --armor', 'mvnw site')
+ }
+
+ It 'ships no artifact without a hash' {
+ Invoke-InScratchTree -Root $script:Root -Script 'build-release.ps1' | Out-Null
+
+ $artifacts = Get-ChildItem (Join-Path $script:Root 'build' 'artifacts') -Exclude '*.sha512', '*.asc'
+ $artifacts.Name | Should -HaveCount 6
+ $artifacts | Where-Object { !(Test-Path "$($_.FullName).sha512") } | Should -BeNullOrEmpty
+ }
+}
diff --git a/scripts/build-release.ps1 b/scripts/build-release.ps1
index de2f0c1e..82e4cef0 100644
--- a/scripts/build-release.ps1
+++ b/scripts/build-release.ps1
@@ -34,7 +34,7 @@ pushd $PSScriptRoot/..
git archive --format=zip --output $PSScriptRoot/../build/artifacts/apache-log4net-source-$Version.zip master
popd
'compressing binaries ...'
-Copy-Item $PSScriptRoot/verify-release.* $PSScriptRoot/../build/artifacts/
+Copy-Item $PSScriptRoot/verify-release.ps1, $PSScriptRoot/verify-release.sh $PSScriptRoot/../build/artifacts/
Copy-Item $PSScriptRoot/../LICENSE $PSScriptRoot/../build/Release/
Copy-Item $PSScriptRoot/../NOTICE $PSScriptRoot/../build/Release/
pushd $PSScriptRoot/../build/Release
diff --git a/src/changelog/3.5.0/.release.xml b/src/changelog/3.5.0/.release.xml
index 4bba497b..39dda551 100644
--- a/src/changelog/3.5.0/.release.xml
+++ b/src/changelog/3.5.0/.release.xml
@@ -2,5 +2,5 @@
<release xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="https://logging.apache.org/xml/ns"
xsi:schemaLocation="https://logging.apache.org/xml/ns https://logging.apache.org/xml/ns/log4j-changelog-0.xsd"
- date="2026-11-01"
+ date="2026-09-28"
version="3.5.0"/>
\ No newline at end of file