Fix WFO1000 errors and exclude Eigen from Jekyll #10
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # (260405Ch) Build ReciProSetup on v* tag push and publish a GitHub Release using the latest Version.cs history line | |
| name: Build And Release Installer | |
| on: | |
| push: | |
| tags: | |
| - "v*" | |
| permissions: | |
| contents: write | |
| jobs: | |
| release: | |
| runs-on: windows-2025-vs2026 # (260405Ch) net10.0-windows + WinForms setup build needs Visual Studio 18 on GitHub-hosted runners. | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v5 | |
| - name: Setup .NET 10 | |
| uses: actions/setup-dotnet@v5 | |
| with: | |
| dotnet-version: "10.0.x" | |
| - name: Restore managed dependencies | |
| shell: pwsh | |
| run: dotnet restore ReciPro\ReciPro.csproj | |
| - name: Confirm installer project sources | |
| shell: pwsh | |
| run: | | |
| # (260405Ch) Fail early with a clear message if installer project sources were not committed to GitHub. | |
| $requiredSources = @( | |
| "ReciProSetup\ReciProSetup.vdproj", | |
| "ReciProSetup\EnableLaunchApplication.js", | |
| "LICENSE.rtf", | |
| "REQUIREMENT.rtf" | |
| ) | |
| $missingSources = $requiredSources | Where-Object { -not (Test-Path $_) } | |
| if ($missingSources.Count -gt 0) { | |
| throw "Installer source files are missing from the checkout: $($missingSources -join ', ')" | |
| } | |
| - name: Read release info from Version.cs | |
| id: version_info | |
| shell: pwsh | |
| run: | | |
| $versionFile = "ReciPro\Version.cs" | |
| $content = Get-Content $versionFile -Raw | |
| $historyRegex = [regex]::Matches($content, 'ver[^\r\n"]+') | |
| if ($historyRegex.Count -eq 0) { | |
| throw "Could not find a release history line in $versionFile." | |
| } | |
| $latestHistory = $historyRegex[0].Value.Trim() | |
| if ($latestHistory -notmatch '^ver(?<Version>[0-9][0-9A-Za-z\.\-_]*)') { | |
| throw "Could not parse version number from history line: $latestHistory" | |
| } | |
| $historyTag = "v$($Matches.Version)" | |
| $tagName = "${{ github.ref_name }}" | |
| if ($historyTag -ne $tagName) { | |
| throw "Tag '$tagName' does not match Version.cs latest history '$historyTag'." | |
| } | |
| $releaseTitle = "ReciPro $tagName" | |
| $notesPath = Join-Path $env:RUNNER_TEMP "release-notes.txt" | |
| @( | |
| $latestHistory | |
| "" | |
| "Built automatically from tag $tagName." | |
| ) | Set-Content -Path $notesPath -Encoding UTF8 | |
| "latest_history=$latestHistory" >> $env:GITHUB_OUTPUT | |
| "release_title=$releaseTitle" >> $env:GITHUB_OUTPUT | |
| "notes_path=$notesPath" >> $env:GITHUB_OUTPUT | |
| - name: Disable out-of-proc setup project build | |
| shell: pwsh | |
| run: | | |
| # (260405Ch) Force installer builds to run in-proc so devenv does not return before MSI generation completes. | |
| $visualStudioRoot = "HKCU:\Software\Microsoft\VisualStudio" | |
| $configKeys = Get-ChildItem $visualStudioRoot -ErrorAction SilentlyContinue | | |
| Where-Object { $_.PSChildName -like '17.0*_Config' -or $_.PSChildName -like '18.0*_Config' } | |
| if ($configKeys.Count -eq 0) { | |
| Write-Warning "No Visual Studio *_Config registry keys were found under $visualStudioRoot." | |
| } | |
| foreach ($configKey in $configKeys) { | |
| $msbuildKey = Join-Path $configKey.PSPath "MSBuild" | |
| if (-not (Test-Path $msbuildKey)) { | |
| New-Item -Path $msbuildKey -Force | Out-Null | |
| } | |
| New-ItemProperty -Path $msbuildKey -Name DisableOutOfProcBuild -PropertyType DWord -Value 1 -Force | Out-Null | |
| Write-Host "Set DisableOutOfProcBuild=1 at $msbuildKey" | |
| } | |
| - name: Build native runtime binaries | |
| shell: pwsh | |
| run: | | |
| # (260405Ch) Build Crystallography.Native separately because the main solution build does not include it in Release|x64. | |
| $devenvExe = (& "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe" -latest -products * -property productPath).Trim() | |
| if (-not $devenvExe) { | |
| throw "Visual Studio was not found." | |
| } | |
| $devenvCli = [System.IO.Path]::ChangeExtension($devenvExe, ".com") | |
| if (-not (Test-Path $devenvCli)) { | |
| throw "devenv.com was not found next to $devenvExe." | |
| } | |
| $buildLogPath = Join-Path $env:RUNNER_TEMP "devenv-native-build.log" | |
| & $devenvCli "ReciPro.sln" /Build "Release|x64" /Project "Crystallography.Native" /Out $buildLogPath | |
| $buildExitCode = $LASTEXITCODE | |
| if (Test-Path $buildLogPath) { | |
| Get-Content $buildLogPath | |
| } | |
| if ($buildExitCode -ne 0) { | |
| throw "Crystallography.Native build failed with exit code $buildExitCode." | |
| } | |
| - name: Build managed application | |
| shell: pwsh | |
| run: | | |
| # (260405Ch) Build managed projects with dotnet to avoid devenv-triggered file locking inside obj during CI. | |
| dotnet build ReciPro\ReciPro.csproj -c Release -p:Platform=x64 --no-restore | |
| - name: Confirm packaging inputs | |
| shell: pwsh | |
| run: | | |
| # (260405Ch) Validate that setup packaging prerequisites exist before running the setup project. | |
| $requiredOutputs = @( | |
| "ReciPro\bin\Release\ReciPro.exe", | |
| "ReciPro\bin\Release\Crystallography.Native.dll", | |
| "ReciPro\bin\Release\Crystallography.Native.avx2.dll", | |
| "ReciPro\bin\Release\Crystallography.Native.avx512.dll" | |
| ) | |
| $missingOutputs = $requiredOutputs | Where-Object { -not (Test-Path $_) } | |
| if ($missingOutputs.Count -gt 0) { | |
| throw "Setup packaging inputs are missing: $($missingOutputs -join ', ')" | |
| } | |
| - name: Create installer-only solution | |
| id: pack_solution | |
| shell: pwsh | |
| run: | | |
| # (260405Ch) Generate a temporary solution that keeps project output metadata for vdproj while skipping managed rebuilds. | |
| $solutionPath = Join-Path (Get-Location) "ReciProSetup.CI.sln" | |
| @' | |
| Microsoft Visual Studio Solution File, Format Version 12.00 | |
| # Visual Studio Version 18 | |
| VisualStudioVersion = 18.0.11205.157 | |
| MinimumVisualStudioVersion = 10.0.40219.1 | |
| Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ReciPro", "ReciPro\ReciPro.csproj", "{D01883A1-458D-4127-8E9B-EEC176201483}" | |
| EndProject | |
| Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Crystallography", "Crystallography\Crystallography.csproj", "{3AABEFB0-E84E-4AF6-8496-4D1F33C8F517}" | |
| EndProject | |
| Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Crystallography.Controls", "Crystallography.Controls\Crystallography.Controls.csproj", "{FD96FE43-6DEE-4520-BB26-CFF7976DE27D}" | |
| EndProject | |
| Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Crystallography.OpenGL", "Crystallography.OpenGL\Crystallography.OpenGL.csproj", "{BE7CC301-70E0-4BAA-9349-FDA49B38CC93}" | |
| EndProject | |
| Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Crystallography.Native", "Crystallography.Native\Crystallography.Native.vcxproj", "{0A6070E5-8843-4C4B-A4ED-4ABC55BFDBDD}" | |
| EndProject | |
| Project("{54435603-DBB4-11D2-8724-00A0C9A8B90C}") = "ReciProSetup", "ReciProSetup\ReciProSetup.vdproj", "{8083E96B-786B-4351-87EF-8546C9C8B297}" | |
| EndProject | |
| Global | |
| GlobalSection(SolutionConfigurationPlatforms) = preSolution | |
| Debug|x64 = Debug|x64 | |
| Release|x64 = Release|x64 | |
| EndGlobalSection | |
| GlobalSection(ProjectConfigurationPlatforms) = postSolution | |
| {D01883A1-458D-4127-8E9B-EEC176201483}.Debug|x64.ActiveCfg = Debug|x64 | |
| {D01883A1-458D-4127-8E9B-EEC176201483}.Release|x64.ActiveCfg = Release|x64 | |
| {3AABEFB0-E84E-4AF6-8496-4D1F33C8F517}.Debug|x64.ActiveCfg = Debug|x64 | |
| {3AABEFB0-E84E-4AF6-8496-4D1F33C8F517}.Release|x64.ActiveCfg = Release|x64 | |
| {FD96FE43-6DEE-4520-BB26-CFF7976DE27D}.Debug|x64.ActiveCfg = Debug|x64 | |
| {FD96FE43-6DEE-4520-BB26-CFF7976DE27D}.Release|x64.ActiveCfg = Release|x64 | |
| {BE7CC301-70E0-4BAA-9349-FDA49B38CC93}.Debug|x64.ActiveCfg = Debug|x64 | |
| {BE7CC301-70E0-4BAA-9349-FDA49B38CC93}.Release|x64.ActiveCfg = Release|x64 | |
| {0A6070E5-8843-4C4B-A4ED-4ABC55BFDBDD}.Debug|x64.ActiveCfg = Debug|x64 | |
| {0A6070E5-8843-4C4B-A4ED-4ABC55BFDBDD}.Release|x64.ActiveCfg = Release|x64 | |
| {8083E96B-786B-4351-87EF-8546C9C8B297}.Debug|x64.ActiveCfg = Debug | |
| {8083E96B-786B-4351-87EF-8546C9C8B297}.Debug|x64.Build.0 = Debug | |
| {8083E96B-786B-4351-87EF-8546C9C8B297}.Release|x64.ActiveCfg = Release | |
| {8083E96B-786B-4351-87EF-8546C9C8B297}.Release|x64.Build.0 = Release | |
| EndGlobalSection | |
| GlobalSection(SolutionProperties) = preSolution | |
| HideSolutionNode = FALSE | |
| EndGlobalSection | |
| EndGlobal | |
| '@ | Set-Content -Path $solutionPath -Encoding ASCII | |
| "solution_path=$solutionPath" >> $env:GITHUB_OUTPUT | |
| - name: Build installer with Visual Studio | |
| id: build_installer | |
| shell: pwsh | |
| run: | | |
| # (260405Ch) Build vdproj from a packaging-only solution so setup can resolve project outputs without rebuilding managed projects. | |
| $devenvExe = (& "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe" -latest -products * -property productPath).Trim() | |
| if (-not $devenvExe) { | |
| throw "Visual Studio was not found." | |
| } | |
| $devenvCli = [System.IO.Path]::ChangeExtension($devenvExe, ".com") | |
| if (-not (Test-Path $devenvCli)) { | |
| throw "devenv.com was not found next to $devenvExe." | |
| } | |
| $buildLogPath = Join-Path $env:RUNNER_TEMP "devenv-build.log" | |
| & $devenvCli "${{ steps.pack_solution.outputs.solution_path }}" /Build "Release|x64" /Project "ReciProSetup" /Out $buildLogPath | |
| $buildExitCode = $LASTEXITCODE | |
| Write-Host "devenv exit code: $buildExitCode" | |
| if (Test-Path $buildLogPath) { | |
| Get-Content $buildLogPath | |
| } | |
| "build_exit_code=$buildExitCode" >> $env:GITHUB_OUTPUT | |
| "build_log_path=$buildLogPath" >> $env:GITHUB_OUTPUT | |
| - name: Confirm installer outputs | |
| id: installer_outputs | |
| shell: pwsh | |
| run: | | |
| # (260405Ch) Some environments materialize setup project outputs slightly after devenv returns, so wait and locate them dynamically. | |
| $requiredNames = @("ReciProSetup.msi") | |
| $foundFiles = @{} | |
| $deadline = (Get-Date).AddMinutes(2) | |
| do { | |
| Get-ChildItem -Path . -Recurse -File -ErrorAction SilentlyContinue | | |
| Where-Object { $requiredNames -contains $_.Name } | | |
| ForEach-Object { $foundFiles[$_.Name] = $_.FullName } | |
| $missingFiles = $requiredNames | Where-Object { -not $foundFiles.ContainsKey($_) } | |
| if ($missingFiles.Count -eq 0) { | |
| break | |
| } | |
| Start-Sleep -Seconds 2 | |
| } while ((Get-Date) -lt $deadline) | |
| $missingFiles = $requiredNames | Where-Object { -not $foundFiles.ContainsKey($_) } | |
| if ($missingFiles.Count -gt 0) { | |
| Write-Host "Located installer-like files:" | |
| Get-ChildItem -Path . -Recurse -File -ErrorAction SilentlyContinue | | |
| Where-Object { $_.Extension -eq ".msi" -or $_.Name -eq "setup.exe" } | | |
| Select-Object FullName, Length, LastWriteTime | |
| if (Test-Path "${{ steps.build_installer.outputs.build_log_path }}") { | |
| Write-Host "devenv build log:" | |
| Get-Content "${{ steps.build_installer.outputs.build_log_path }}" | |
| } | |
| throw "Required output was not found: $($missingFiles -join ', ')" | |
| } | |
| if ("${{ steps.build_installer.outputs.build_exit_code }}" -ne "0") { | |
| Write-Warning "devenv returned exit code ${{ steps.build_installer.outputs.build_exit_code }}, but the MSI output was found. Continuing with the generated file." | |
| } | |
| "msi_path=$($foundFiles['ReciProSetup.msi'])" >> $env:GITHUB_OUTPUT | |
| - name: Upload workflow artifacts | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: ReciPro-installer-${{ github.ref_name }} | |
| path: | | |
| ${{ steps.installer_outputs.outputs.msi_path }} | |
| - name: Create GitHub Release | |
| shell: pwsh | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| gh release create "${{ github.ref_name }}" ` | |
| "${{ steps.installer_outputs.outputs.msi_path }}" ` | |
| --verify-tag ` | |
| --title "${{ steps.version_info.outputs.release_title }}" ` | |
| --notes-file "${{ steps.version_info.outputs.notes_path }}" |