legal: move COMMERCIAL_LICENSE.md to repo root, fix README link #7
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
| name: CI | |
| # Runs on every push to any branch and on every pull request. | |
| # Builds PowerMeter.exe (Release x64) and both ACSIL DLLs, then runs | |
| # smoke tests to verify the binaries are valid PE images and export | |
| # the expected entry points. | |
| on: | |
| push: | |
| branches: ["**"] | |
| tags-ignore: ["v*"] | |
| pull_request: | |
| branches: ["**"] | |
| concurrency: | |
| group: ci-${{ github.ref }} | |
| cancel-in-progress: true | |
| jobs: | |
| # --------------------------------------------------------------------------- | |
| build-overlay: | |
| name: Build PowerMeter.exe | |
| runs-on: windows-latest | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| - name: Add MSBuild to PATH | |
| uses: microsoft/setup-msbuild@v2 | |
| - name: Build PowerMeter.exe (Release x64) | |
| run: | | |
| msbuild PowerMeter.vcxproj ` | |
| /p:Configuration=Release ` | |
| /p:Platform=x64 ` | |
| /p:PlatformToolset=v143 ` | |
| /v:minimal ` | |
| /nologo | |
| - name: Locate PowerMeter.exe | |
| id: locate-exe | |
| shell: pwsh | |
| run: | | |
| $candidates = @( | |
| "x64\Release\PowerMeter.exe", | |
| "PowerMeter\x64\Release\PowerMeter.exe" | |
| ) | |
| $found = $candidates | Where-Object { Test-Path $_ } | Select-Object -First 1 | |
| if (-not $found) { Write-Error "PowerMeter.exe not found after build."; exit 1 } | |
| Write-Host "Found: $found" | |
| "exe_path=$found" | Out-File -FilePath $env:GITHUB_OUTPUT -Append | |
| - name: Smoke test - valid AMD64 PE image | |
| shell: pwsh | |
| run: | | |
| $exe = "${{ steps.locate-exe.outputs.exe_path }}" | |
| $bytes = [System.IO.File]::ReadAllBytes($exe) | |
| if ($bytes[0] -ne 0x4D -or $bytes[1] -ne 0x5A) { Write-Error "Missing MZ header"; exit 1 } | |
| $peOffset = [BitConverter]::ToInt32($bytes, 0x3C) | |
| $machine = [BitConverter]::ToUInt16($bytes, $peOffset + 4) | |
| if ($machine -ne 0x8664) { Write-Error ("Not AMD64: 0x{0:X4}" -f $machine); exit 1 } | |
| $size = (Get-Item $exe).Length | |
| if ($size -lt 50KB) { Write-Error "Binary too small: $size bytes"; exit 1 } | |
| Write-Host ("PASS: AMD64 PE, {0:N0} bytes" -f $size) | |
| - name: Upload overlay artifact | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: PowerMeter-exe | |
| path: ${{ steps.locate-exe.outputs.exe_path }} | |
| retention-days: 7 | |
| # --------------------------------------------------------------------------- | |
| build-acsil: | |
| name: Build ACSIL DLLs | |
| runs-on: windows-latest | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| - name: Add MSBuild to PATH | |
| uses: microsoft/setup-msbuild@v2 | |
| # SC headers are bundled in ACSIL/sc_stub/ACS_Source/ — no download needed. | |
| - name: Build PowerMeterFeed DLL (Debug x64) | |
| run: | | |
| msbuild PowerMeterFeed.vcxproj ` | |
| /p:Configuration=Debug ` | |
| /p:Platform=x64 ` | |
| /p:PlatformToolset=v143 ` | |
| /p:SierraChartRoot="${{ github.workspace }}\ACSIL\sc_stub" ` | |
| /v:minimal ` | |
| /nologo | |
| working-directory: ACSIL | |
| - name: Build PowerMeterFeedJS DLL (Debug x64) | |
| run: | | |
| msbuild PowerMeterFeedJS.vcxproj ` | |
| /p:Configuration=Debug ` | |
| /p:Platform=x64 ` | |
| /p:PlatformToolset=v143 ` | |
| /p:SierraChartRoot="${{ github.workspace }}\ACSIL\sc_stub" ` | |
| /v:minimal ` | |
| /nologo | |
| working-directory: ACSIL | |
| - name: Smoke test - DLLs are valid AMD64 PE images | |
| shell: pwsh | |
| run: | | |
| $dlls = @( | |
| "ACSIL\bin\x64\Debug\PowerMeterFeed_64_d.dll", | |
| "ACSIL\bin\x64\Debug\PowerMeterFeedJS_64_d.dll" | |
| ) | |
| foreach ($dll in $dlls) { | |
| if (-not (Test-Path $dll)) { Write-Error "Not found: $dll"; exit 1 } | |
| $bytes = [System.IO.File]::ReadAllBytes($dll) | |
| if ($bytes[0] -ne 0x4D -or $bytes[1] -ne 0x5A) { Write-Error "Bad MZ: $dll"; exit 1 } | |
| $peOffset = [BitConverter]::ToInt32($bytes, 0x3C) | |
| $machine = [BitConverter]::ToUInt16($bytes, $peOffset + 4) | |
| if ($machine -ne 0x8664) { Write-Error ("Not AMD64: $dll (0x{0:X4})" -f $machine); exit 1 } | |
| $size = (Get-Item $dll).Length | |
| if ($size -lt 10KB) { Write-Error "Too small: $size bytes ($dll)"; exit 1 } | |
| Write-Host ("PASS: $(Split-Path $dll -Leaf) ({0:N0} bytes, AMD64)" -f $size) | |
| } | |
| - name: Smoke test - DLL exports | |
| shell: pwsh | |
| run: | | |
| $vswhere = "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe" | |
| $vsPath = & $vswhere -latest -property installationPath | |
| $dumpbin = Get-ChildItem "$vsPath\VC\Tools\MSVC" -Recurse -Filter "dumpbin.exe" | | |
| Where-Object { $_.FullName -match "HostX64\\x64" } | | |
| Select-Object -First 1 | |
| if (-not $dumpbin) { Write-Error "dumpbin.exe not found via vswhere"; exit 1 } | |
| Write-Host "dumpbin: $($dumpbin.FullName)" | |
| $checks = @( | |
| @{ dll = "ACSIL\bin\x64\Debug\PowerMeterFeed_64_d.dll"; symbol = "scsf_PowerMeterFeed" }, | |
| @{ dll = "ACSIL\bin\x64\Debug\PowerMeterFeedJS_64_d.dll"; symbol = "scsf_PowerMeterFeedJS" } | |
| ) | |
| foreach ($check in $checks) { | |
| $dll = $check.dll | |
| $symbol = $check.symbol | |
| Write-Host "Checking exports of $dll for '$symbol'..." | |
| $exports = & $dumpbin.FullName /exports $dll 2>&1 | Out-String | |
| Write-Host $exports | |
| if ($exports -notmatch $symbol) { | |
| Write-Error "Export '$symbol' not found in $dll" | |
| exit 1 | |
| } | |
| Write-Host "PASS: $symbol exported from $(Split-Path $dll -Leaf)" | |
| } | |
| - name: Upload ACSIL artifacts | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: ACSIL-debug-dlls | |
| path: ACSIL/bin/x64/Debug/*.dll | |
| retention-days: 7 | |
| # --------------------------------------------------------------------------- | |
| ci-passed: | |
| name: CI passed | |
| needs: [build-overlay, build-acsil] | |
| runs-on: ubuntu-latest | |
| if: always() | |
| steps: | |
| - name: Check all jobs succeeded | |
| run: | | |
| if [[ "${{ needs.build-overlay.result }}" != "success" || \ | |
| "${{ needs.build-acsil.result }}" != "success" ]]; then | |
| echo "One or more CI jobs failed." | |
| exit 1 | |
| fi | |
| echo "All CI jobs passed." |