From d09dba24e8bdd66c4c221a08cf6346f2f74add55 Mon Sep 17 00:00:00 2001 From: Eduardo Ponz Date: Wed, 15 Mar 2023 12:04:16 +0100 Subject: [PATCH 01/16] Refs #17628: Add Windows CI workflow Signed-off-by: Eduardo Ponz --- .github/workflows/nightly-windows-ci.yml | 22 + .github/workflows/reusable-windows-ci.yml | 763 ++++++++++++++++++++++ .github/workflows/windows-ci.yml | 52 ++ README.md | 2 +- 4 files changed, 838 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/nightly-windows-ci.yml create mode 100644 .github/workflows/reusable-windows-ci.yml create mode 100644 .github/workflows/windows-ci.yml diff --git a/.github/workflows/nightly-windows-ci.yml b/.github/workflows/nightly-windows-ci.yml new file mode 100644 index 00000000000..f8569ee094f --- /dev/null +++ b/.github/workflows/nightly-windows-ci.yml @@ -0,0 +1,22 @@ +name: Fast-DDS Windows CI + +on: + schedule: + - cron: '0 1 * * *' + +jobs: + nightly-sec-windows-ci: + uses: ./.github/workflows/reusable-windows-ci.yml + with: + label: 'nightly-sec-windows-ci' + cmake-args: "-DSECURITY=ON" + ctest-args: "-LE xfail" + force-meta-branch: 'nightly' + + nightly-nosec-windows-ci: + uses: ./.github/workflows/reusable-windows-ci.yml + with: + label: 'nightly-sec-windows-ci' + cmake-args: "-DSECURITY=OFF" + ctest-args: "-LE xfail" + force-meta-branch: 'nightly' diff --git a/.github/workflows/reusable-windows-ci.yml b/.github/workflows/reusable-windows-ci.yml new file mode 100644 index 00000000000..32755a400a1 --- /dev/null +++ b/.github/workflows/reusable-windows-ci.yml @@ -0,0 +1,763 @@ +name: Fast-DDS Windows CI reusable workflow + +on: + workflow_call: + inputs: + label: + description: 'ID associated to the workflow. Must univocally identify artifacts.' + required: true + type: string + colcon-args: + description: 'Extra arguments for colcon cli' + required: false + type: string + cmake-args: + description: 'Extra arguments for cmake cli' + required: false + type: string + ctest-args: + description: 'Extra arguments for ctest cli' + required: false + type: string + force-meta-branch: + description: 'Branch to checkout in Fast-DDS-CI' + required: false + type: string + +defaults: + run: + shell: pwsh + +jobs: + reusable-windows-ci: + runs-on: windows-2019 + if: ${{ !contains(github.event.pull_request.labels.*.name, 'skip-ci') }} + strategy: + fail-fast: false + matrix: + cmake-config: + - 'RelWithDebInfo' + vs-toolset: + - 'v141' + - 'v142' + steps: + - name: Sync eProsima/Fast-DDS repository + uses: actions/checkout@v3 + with: + path: src/fastrtps + + - name: Get minimum supported version of CMake + uses: lukka/get-cmake@latest + with: + cmakeVersion: '3.16.3' + + - name: Patch SDK for source indexing + run: | + # This is a well known issue and the workarond is taken from there + # https://github.com/actions/runner-images/issues/4208 + $kitskey = gi "HKLM:SOFTWARE/Microsoft/Windows Kits/Installed Roots" + $kitspath = $kitskey.GetValue($kitskey.GetValueNames() -match "KitsRoot") + $pdbstr64 = Resolve-Path "$kitspath/*/x64/srcsrv/pdbstr.exe" + $pdbstr86 = Resolve-Path "$kitspath/*/x86/srcsrv/pdbstr.exe" + rm $pdbstr64 + New-Item -ItemType SymbolicLink -Target $pdbstr86 -Path $pdbstr64 + + - name: Setup environment + run: | + # Check the cmake version + if( (cmake --version) -join " " -notmatch + "${{ matrix.configs.cmake_minimum_requirement }}".replace(".","\.") ) + { + Write-Error "Using wrong cmake version" + } + + # Introduce EchoArgs to check colcon/cmake calls + $mdir = New-Item -Type Directory -Path (Join-Path ($Env:TMP ?? "/tmp") (New-GUID)) + Save-Module -Name Pscx -Path $mdir -Repository PSGallery + $echo = gci -Path $mdir -R -Filter EchoArgs* + "PATH=$Env:PATH" + [IO.Path]::PathSeparator + ($echo | Split-Path | gi) + | Out-File $Env:GITHUB_ENV -Append -Encoding OEM + + # Handle single target/multi target + $env_variables = @() + + [xml]$info = & "${Env:ProgramFiles(x86)}\Microsoft Visual Studio\installer\vswhere" ` + -latest -format xml + $pwshmodule = Join-Path $info.instances.instance.installationPath ` + "Common7\Tools\Microsoft.VisualStudio.DevShell.dll" | gi + + $env_variables += + 'CXXFLAGS=/MP', + 'CONFIG_TYPE=--config ${{ matrix.cmake-config }}', + 'BIN_ARCH=-A x64', + 'HOST_ARCH=-T ${{ matrix.vs-toolset }},host=x64', + ('VSPWSH=' + $pwshmodule) + + # download the pull request branches on fetch + git config --global remote.origin.fetch '+refs/pull/*:refs/remotes/origin/pull/*' + + $env_variables | Out-File $Env:GITHUB_ENV -Append -Encoding OEM + + - name: Enable WER + id: WERSetup + run: | + $wer = "HKLM:\SOFTWARE\Microsoft\Windows\Windows Error Reporting" + $ld = Join-Path $wer LocalDumps + $key = Get-Item $wer + + if("Disabled" -in $key.Property) { + Set-ItemProperty -Path $wer -Name "Disabled" -Value 0 + } else { + New-ItemProperty -Path $wer -Name "Disabled" -Value 0 -PropertyType DWord + } + + if(Test-Path $ld) { $key = Get-Item $ld } else { $key = New-Item -Path $wer -Name "LocalDumps" } + + #destination folder + $crashdir = New-Item -Path "CrashDumps" -Type Directory + if("DumpFolder" -in $key.Property) { + Set-ItemProperty -Path $ld -Name "DumpFolder" -Value $crashdir + } else { + New-ItemProperty -Path $ld -Name "DumpFolder" -Value $crashdir -PropertyType ExpandString + } + "DumpFolder=$crashdir" | Out-File $Env:GITHUB_OUTPUT -Append + + # up to DumpCount files in the folder + if("DumpCount" -in $key.Property) { + Set-ItemProperty -Path $ld -Name "DumpCount" -Value 100 + } else { + New-ItemProperty -Path $ld -Name "DumpCount" -Value 100 -PropertyType DWord + } + + # 2 -> full dump + if("DumpType" -in $key.Property) { + Set-ItemProperty -Path $ld -Name "DumpType" -Value 2 + } else { + New-ItemProperty -Path $ld -Name "DumpType" -Value 2 -PropertyType DWord + } + + # WER service is manual by default + Start-Service WerSvc + + - name: Install colcon + run: | + pip3 install -U colcon-common-extensions vcstool colcon-mixin + + # patch colcon issue with visual studio 2022 + $patch = gci -Include build.py -Recurse ` + -Path ((gcm colcon).source | Split-Path | Join-Path -ChildPath "..\Lib\site-packages\colcon_cmake\*") + if(!(sls -Path $patch -Pattern "'17.0': 'Visual Studio 17 2022'")) + { + echo "Patching colcon build to admit Visual Studio 17 2022" + $tmp = New-TemporaryFile + Get-Content $patch | % { + if($_ -match "Visual Studio 16 2019") { + " '17.0': 'Visual Studio 17 2022'," } + $_ + } | Out-File $tmp -Encoding OEM + Install-Module -Name Pscx -Force -AllowClobber + ConvertTo-UnixLineEnding -Destination $patch -Path $tmp.FullName + del $tmp + } + + # refresh mixins + colcon mixin add default 'https://raw.githubusercontent.com/colcon/colcon-mixin-repository/master/index.yaml' + colcon mixin update default + colcon mixin show + + - name: Install asio and tinyxml2 + run: | + $tmpdir = New-Item -Path "$Env:TMP\choco_aux" -Type Directory + iwr -Uri https://github.com/ros2/choco-packages/releases/download/2020-02-24/asio.1.12.1.nupkg -OutFile "$tmpdir\asio.1.12.1.nupkg" + iwr -Uri https://github.com/ros2/choco-packages/releases/download/2020-02-24/tinyxml2.6.0.0.nupkg -OutFile "$tmpdir\tinyxml2.6.0.0.nupkg" + choco install -y -s $tmpdir asio tinyxml2 + del $tmpdir -Recurse + + # Need to be very explicit in path location due to poor choice on ros2 choco-package composition + "CMAKE_PREFIX_PATH=$Env:ProgramData\chocolatey\lib\asio\share\cmake;" + + "$Env:ProgramData\chocolatey\lib\tinyxml2\share\cmake;$Env:CMAKE_PREFIX_PATH" | + Out-File $Env:GITHUB_ENV -Append -Encoding OEM + + - name: Install googletest + run: | + git clone --branch release-1.11.0 https://github.com/google/googletest.git + $crt = '-Dgtest_force_shared_crt=ON' + + # Show the args + EchoArgs -DBUILD_GMOCK=ON -DCMAKE_BUILD_TYPE=${{ matrix.cmake-config }} $crt -DCMAKE_VERBOSE_MAKEFILE=ON ` + -B ./build/googletest "$Env:BIN_ARCH".split(" ") "$Env:HOST_ARCH".split(" ") ./googletest + + # Generate + cmake -DBUILD_GMOCK=ON -DCMAKE_BUILD_TYPE=${{ matrix.cmake-config }} $crt -DCMAKE_VERBOSE_MAKEFILE=ON ` + -B ./build/googletest "$Env:BIN_ARCH".split(" ") "$Env:HOST_ARCH".split(" ") ./googletest + + # Build and install elevated if required + $build = { cmake --build ./build/googletest --target install "$Env:CONFIG_TYPE".split(" ") --verbose } + (& $build) | Tee-Object -FilePath gtest.log + + # Hint install dir + $pattern = "-- Installing:\s+(?.*)/GTestConfig.cmake" + $matches = sls -Path gtest.log -Pattern $pattern + $Env:GTest_DIR = ($matches.Matches.Groups | ? name -eq cmake_path).Value + ("GTest_DIR=" + $Env:GTest_DIR) | Out-File $Env:GITHUB_ENV -Append -Encoding OEM + + # clean up + 'build', 'googletest', 'gtest.log' | del -Recurse -Force + + - name: Install OpenSSL + run: | + # Windows host has only the binaries installed, we need the headers too + # download the last installer + $uri = 'https://slproweb.com' + + ((iwr 'https://slproweb.com/products/Win32OpenSSL.html').links | + sls 'href=\"(.*download/Win64OpenSSL-1_1_1.*\.exe)\"').matches.Groups.value[-1] + iwr -Uri $uri -OutFile "$Env:TMP\Win64OpenSSL.exe" + + # Do install + & "$Env:TMP\Win64OpenSSL.exe" /silent /verysilent /sp- /suppressmsgboxes; + + # Update the environment + "OPENSSL64_ROOT=$Env:ProgramFiles\OpenSSL-Win64" | Out-File $Env:GITHUB_ENV -Append -Encoding OEM + + # Wait for the installation to be fulfill + Get-Process Win??OpenSSL -ErrorAction SilentlyContinue | Wait-Process + del "$Env:TMP\Win64OpenSSL.exe" + + - name: Update known hosts file for DNS resolver testing + if: ${{ !contains(github.event.pull_request.labels.*.name, 'no-test') }} + run: | + $hostfile = "$Env:SystemRoot\system32\drivers" -replace "\\", "/" + $hostfile += "/etc/hosts" + + # DNS entries to add + $new_entries = @{ + "localhost.test" = "127.0.0.1", "::1" + "www.eprosima.com.test" = "154.56.134.194" + "www.acme.com.test" = "216.58.215.164", "2a00:1450:400e:803::2004" + "www.foo.com.test" = "140.82.121.4", "140.82.121.3" + "acme.org.test" = "ff1e::ffff:efff:1" + } + + # Modify the file + $mod = { Param([string]$FilePath, [Hashtable]$Entries ) + $entries.GetEnumerator() | + % { $hostname = $_.key; $_.value | + % { "{0,-25} {1}" -f $_, $hostname }} | + Out-File $filepath -Append + } + + & $mod -FilePath $hostfile -Entries $new_entries + + # Show the result + gc $hostfile + + - name: Set up libp11 and SoftHSM + timeout-minutes: 10 + continue-on-error: true + run: | + if(!(Test-Path -Path Env:OPENSSL64_ROOT)) + { + Write-Error -Message "OpenSSL is not set up properly. Check previous steps." + } + + # Install the HSM emulator (required for testing PKCS #11 support) + $urlHSM = "https://github.com/disig/SoftHSM2-for-Windows/releases/download/v2.5.0/SoftHSM2-2.5.0.msi" + $msiHSM = "$Env:tmp\SoftHSM2-2.5.0.msi" + + iwr $urlHSM -OutFile $msiHSM + msiexec /i $msiHSM /quiet TARGETDIR="""${Env:ProgramFiles(x86)}""" + $Env:SOFTHSM2_ROOT = Join-Path "${Env:ProgramFiles(x86)}" SoftHSM2 + 'SOFTHSM2_ROOT=' + $Env:SOFTHSM2_ROOT | Out-File $Env:GITHUB_ENV -Append -Encoding OEM + + # Build pkcs11 library + $deploy_dir = "$Env:ProgramFiles\libp11" + git clone https://github.com/OpenSC/libp11.git $deploy_dir + $deploy_dir = gi $deploy_dir + + $pwshmodule = gi $Env:VSPWSH + Import-Module $pwshmodule + Enter-VsDevShell -SetDefaultWindowTitle -VsInstallPath $pwshmodule.Directory.Parent.Parent ` + -StartInPath (pwd) -DevCmdArguments '/arch=x64 /host_arch=x64' + + cd $deploy_dir + + nmake .\Makefile.mak OPENSSL_DIR=$Env:OPENSSL64_ROOT BUILD_FOR=WIN64 + $config = ls -Path $Env:OPENSSL64_ROOT -Recurse -Include openssl.cnf; + $libp11_path = Join-Path $deploy_dir src + 'LibP11_ROOT_64=' + $libp11_path | Out-File $Env:GITHUB_ENV -Append -Encoding OEM + + # Wait until installation is completed + Wait-Process -Name msiexec -ErrorAction SilentlyContinue + del $msiHSM + + # Set up OpenSSL + $module_path = gci -Path $Env:SOFTHSM2_ROOT -Recurse -Include '*.dll' | ? FullName -match 64 + $contents = gc $config; + + $header = "# HSM test ancillary configuration", + "openssl_conf = openssl_init" + + $footer = "[openssl_init]", + "engines = engine_section", + "", + "[engine_section]", + "pkcs11 = pkcs11_section", + "", + "[pkcs11_section]", + "engine_id = pkcs11", + ("dynamic_path =" + ("$libp11_path/pkcs11.dll" -replace "\\","/")), + ("MODULE_PATH =" + ($module_path.FullName -replace "\\","/")), + "init = 0" + + $header_line = ($contents | sls '^HOME')[0].LineNumber; + ($contents[0..$header_line] + $header + $contents[$header_line..$contents.count] + $footer) | + % { $_.TrimStart() } | Out-File $config -Encoding OEM; + + # lead openssl to the right config file + $Env:OPENSSL_CONF=$config + + # introduce openssl binary in the path for the lower check + $Env:Path += ";$Env:OPENSSL64_ROOT\bin" + + # check if is working + openssl engine pkcs11 -t + + - name: Prepare colcon workspace + run: | + # Get some convenient tools + Install-Module -Name ConvertBase64Strings -Force -AllowClobber + Import-Module -name ConvertBase64Strings -Prefix CI + Install-Module powershell-yaml -Force + + # Check if git is behaving + $checker = @{ + Begin = {$errores = 0} + Process = {if($_ -is [Management.Automation.ErrorRecord] -and $_.Exception.Message -match "^(error|fatal):") {++$errores} } + End = { $errores -eq 0 } + } + $assert = {if($_ -is [Management.Automation.ErrorRecord] -and $_.Exception.Message -match "^(error|fatal):") + { Write-Error $_ } else { Write-Output $_ } } + + # Download Fast-DDS-CI repo and checkout current branch + git clone https://github.com/eProsima/Fast-DDS-CI.git Fast-DDS-CI 2>&1 | % $assert + pushd Fast-DDS-CI + # locally master is main + git symbolic-ref refs/heads/master refs/heads/main 2>&1 | % $assert + + # selecting specific metas & depends + $repo_branch = "${{ inputs.force-meta-branch }}" + + if($repo_branch) + { + # 1. Externally specified as nightlies + git checkout $repo_branch 2>&1 | % $assert + } + else + { + # 2. Use heuristics to choose + switch -regex ("${{ github.event_name }}") + { + "pull_request" + { + # try: source branch, destination branch + foreach($repo_branch in @("${{ github.head_ref }}", "${{ github.base_ref }}")) + { + if(git checkout $repo_branch 2>&1 | % @checker) + { + $choice = "taking metas & depends from branch $repo_branch" + break; + } + else + { + Write-Output "Fast-DDS-CI lacks branch $repo_branch" + } + } + } + "push|workflow" + { + # use the branch that was push or was selected for the workflow + $repo_branch = "${{ github.ref }}" + if(git checkout $repo_branch 2>&1 | % @checker) + { + $choice = "taking metas & depends from branch $repo_branch" + } + else + { + Write-Output "Fast-DDS-CI lacks branch $repo_branch" + } + } + } + + # On failure fallback to master + if(!$choice) + { + git checkout master 2>&1 | % $assert + $choice = "fallback: taking metas & depends from master" + } + Write-Output $choice + } + + popd + + # Get action credentials for github REST API + $secret = ConvertTo-SecureString -String "${{ secrets.GITHUB_TOKEN }}" -AsPlainText + + # Check available queries according with github policy + "::group::Rate Limits with github action token" + ((Invoke-WebRequest -Authentication OAuth -Token $secret ` + -Uri https://api.github.com/users/octocat).Headers.GetEnumerator() | + ? Key -like "X-RateLimit*") | Out-Host + "::endgroup::" + + # download the repos file + $repos = ((Invoke-WebRequest -Authentication OAuth -Token $secret ` + -Uri "${{ github.api_url }}/repos/eProsima/Fast-DDS/contents/fastrtps.repos?ref=${{ github.ref }}" ` + -Headers @{"method"="GET";"Accept"="application/vnd.github.v3+json"}).content | + ConvertFrom-Json).content | ConvertFrom-CIBase64 | ConvertFrom-Yaml + + # merge with the provided Fast-DDS-CLI depends.repos + $depends_path = ".\Fast-DDS-CI\depends.repos" + if(Test-Path $depends_path) + { + $depends = Get-Content $depends_path | ConvertFrom-Yaml + + # Replace fastrtps.repos entires with depends.repos ones + $depends.repositories.GetEnumerator() | + % { $repos.repositories[$_.Name] = $_.Value} + } + else + { + Write-Output "depends.repos not available in Fast-DDS-CI" + } + + # cmake --find-package has issues on unix base system + # let's use a dummy project + $find_gtest = { + $tmpdir = $IsWindows ? "$Env:TMP\" : "/tmp/" + pushd (New-Item -Type Directory -Path "$tmpdir$(New-Guid)") + $cr = "`n" + 'cmake_minimum_required(VERSION 3.5)' + $cr + + 'project(dummy VERSION 1.0.0 LANGUAGES CXX)' + $cr + + 'find_package(GTest CONFIG REQUIRED)' + $cr + + 'message(STATUS "GTest_FOUND=>>>>${GTest_FOUND}<<<<<")' | + Out-File CMakeLists.txt + (cmake .) *>&1 | % { + if($_ -Match "GTest_FOUND=>>>>(?.*)<<<<<") { $Matches.res -eq 1 } + }; popd } + + # If there is a framework version of googletest use it + if($repos.repositories.Contains("googletest-distribution") -and (& $find_gtest)) + { + $repos.repositories.Remove("googletest-distribution") + Write-Output "Using framework version of googletest-distribution" + } + + "::group::merged vcstool repos file" + $repos | ConvertTo-Yaml | Tee-Object -FilePath fastrtps.repos + "::endgroup::" + + # create source dir and download the sources + mkdir src + vcs import src --input fastrtps.repos --skip-existing + + - name: Retrieve colcon.meta file + run: | + # Try retrieve it from the Fast-DDS-CI + $meta_path = ".\Fast-DDS-CI\colcon.meta" + if(Test-Path $meta_path) + { + $meta = Get-Content $meta_path | ConvertFrom-Yaml + } + else + { + Write-Output "depends.repos not available in Fast-DDS-CI" + + # generate dynamically one + $meta = [PSCustomObject]@{names=@{fastrtps=@{"cmake-args"=$Null}}} + + $meta.names.fastrtps."cmake-args" = "-DEPROSIMA_BUILD=ON", + "-DINTERNAL_DEBUG=ON", + "-DGTEST_INDIVIDUAL=ON", + "-DFASTRTPS_API_TESTS=OFF", + "-DFASTDDS_PIM_API_TESTS=ON", + "-DPERFORMANCE_TESTS=ON", + "-DNO_TLS=ON", + "-DENABLE_WER=ON", + "-DWER_TIMEOUT_TIME=240" + } + + # Generate the meta file + "::group::deployed colcon.meta file" + $meta | ConvertTo-Json -Depth 3 | Tee-Object -FilePath ci.meta -Encoding OEM + "::endgroup::" + + - name: Build + id: build + run: | + # build type mixin names doesn't match cmake ones + $translate = @{ + "Debug"="debug" + "Release"="release" + "RelWithDebInfo"="rel-with-deb-info" + "MinSizeRel"="min-size-rel" + } + # For convenience use an array to pass the arguments + $buildargs = "--merge-install", + "--symlink-install", + "--event-handlers=console_direct+", + "--packages-up-to", "fastrtps", + "--mixin", $translate["${{ matrix.cmake-config }}"] + + $cmakeargs = '--cmake-args ${{ inputs.cmake-args }} ' + + # On Windows we must load the developer environment and chose a config + $pwshmodule = gi $Env:VSPWSH + Import-Module $pwshmodule + Enter-VsDevShell -SetDefaultWindowTitle -VsInstallPath $pwshmodule.Directory.Parent.Parent ` + -StartInPath (pwd) -DevCmdArguments '/arch=x64 /host_arch=x64' + + $cmakeargs += "$Env:BIN_ARCH $Env:HOST_ARCH" + + # Show the args + EchoArgs $buildargs --metas ci.meta --executor sequential ${{ inputs.colcon-args }} $cmakeargs.split(" ") + + "::group::cmake summary" + colcon build $buildargs --metas ci.meta --executor sequential ${{ inputs.colcon-args }} $cmakeargs.split(" ") + "::endgroup::" + + $output_buffer = "" + $warning_sb = {Write-Warning $args[0]; $global:output_buffer += $args[0]} + $error_sb = {Write-Error $args[0]; $global:output_buffer += $args[0]} + + switch($LASTEXITCODE) + { + 0 { $report_kind = "generation or build warnings"; $wm = $warning_sb } + 1 { $report_kind = "CMake errors"; $wm = $error_sb } + 2 { $report_kind = "build errors"; $wm = $error_sb } + } + + # Show only warnings or error reports but do not fail + $LASTEXITCODE=0 + $WarningPreference = $ErrorActionPreference = 'Continue' + $reports = gci -Path ./log/build_* -R -Filter stderr.log | ? { sls -Path $_ -Pattern "error|warning" } + + $reports.FullName + + if($reports) + { + $logFolder = New-Item -Type Directory -Path build_logs + $msg = "There were $report_kind in some packages:" + & $wm $msg + (($reports.FullName | sls "log.build_[\d-_]*.(?[^/]*).stderr.log").Matches.Groups | + ? name -eq "package").value | % { + $msg += " $_" + & $wm $_ + $file = Resolve-Path "./log/*/$_/stderr.log" + $dest_file = Join-Path -Path $logFolder -ChildPath "$_-stderr.log" + Copy-Item -Path $file -Destination $dest_file + Get-Content $file + } + + "BuildWarningsErrors=" + $output_buffer | Out-File $Env:GITHUB_OUTPUT + "BuildLogFolder=" + $logFolder.FullName | Out-File $Env:GITHUB_OUTPUT -Append + } + + - name: Test + if: ${{ !contains(github.event.pull_request.labels.*.name, 'no-test') && + ((steps.test.outcome == 'success') && + (steps.build.outputs.BuildWarningsErrors == 0 || + contains(steps.build.outputs.BuildWarningsErrors, 'warning'))) }} + id: test + run: | + # Create a junit file for test results + $junit = New-Item -Path ./junit.xml -ItemType File + 'JUNIT_LOG=' + $junit.FullName | Out-File $Env:GITHUB_ENV -Append -Encoding OEM + + # add ctest args + $ctestargs = '${{ inputs.ctest-args }}'.split(" ") + + # Show the arguments + EchoArgs --packages-select fastrtps --event-handlers=console_direct+ ` + --executor sequential --ctest-args $ctestargs --timeout 300 --output-junit $junit + + # Run the testing + "::group::ctest summary" + colcon test --packages-select fastrtps --event-handlers=console_direct+ ` + --executor sequential --ctest-args $ctestargs --timeout 300 --output-junit $junit + "::endgroup::" + + - name: Create test Summary + id: summary + if: ${{ steps.test.outcome == 'success' }} + run: | + $ErrorActionPreference = 'Continue' + $failed = 0 + + # If the CMake version (3.21 et seq.) supports junit use it + if((Test-Path $Env:JUNIT_LOG) -and (gi $Env:JUNIT_LOG).Length ) + { + # ancillary for markdown summary + $modules = Get-Module -ListAvailable | Select ModuleType, Version, Name + if(!($modules | ? Name -eq "MarkdownPS")) + { + Install-Module -Name MarkdownPS -Force + } + + [xml]$res = gc $Env:JUNIT_LOG + [long]$failed = $res.testsuite.failures + + # Summary + $res.testsuite | select name, tests, failures, disabled, hostname, time, timestamp | + New-MDTable | Tee-Object -FilePath $Env:GITHUB_STEP_SUMMARY -Append + + if($failed) + { + # list the failures if any + "::group::Failures Summary" + $failures = $res.testsuite.testcase | ? status -eq fail + $failures | select name, time | format-list + "::endgroup::" + + # list faulty tests output + "::group::Failed tests output" + $failures + "::endgroup::" + + # populate a log folder with the failures + $logFolder = New-Item -Type Directory -Path test_logs + pushd $logFolder + $failures | % { $_.'system-out' | Set-Content -Path ($_.name + ".txt") } + popd + + "TestLogFolder=" + $logFolder.FullName | Out-File $Env:GITHUB_OUTPUT -Append + } + + } + else + { + # Let's create a summary table + $table = @{} + + # fallback to parse the ordinary output file + # check total and passed + $pattern = '(?:(?[\d-:T]+)\.\S+ |^)(?:.\[0;32m)?(\d+)% tests passed(?:.\[0;0m)?,' + + ' (?:.\[0;31m)?(?\d+) tests failed(?:.\[0;0m)? out of (?\d+)$' + $logfile = gi ./log/latest_test/fastrtps/stdout.log + $summary = (gc $logfile).where({ $_ -match $pattern }, 'SkipUntil') + $table.failures = [long]$failed = $matches.failed + $table.tests = $matches.total + $table.hostname = hostname + if($matches.timestamp) { $table.timestamp = $matches.timestamp } + else { $table.timestamp = $logfile.LastWriteTime | Get-Date -Format "yyyy-MM-ddThh:mm:ss" } + # check time + $pattern = "Total Test time \(real\) = (?