name: cross-platform-determinism on: workflow_dispatch: {} push: branches: [main] paths: - 'src/__Libraries/StellaOps.Canonical.Json/**' - 'src/__Libraries/StellaOps.Replay.Core/**' - 'src/__Tests/**Determinism**' - '.gitea/workflows/cross-platform-determinism.yml' pull_request: branches: [main] paths: - 'src/__Libraries/StellaOps.Canonical.Json/**' - 'src/__Libraries/StellaOps.Replay.Core/**' - 'src/__Tests/**Determinism**' jobs: # DET-GAP-11: Windows determinism test runner determinism-windows: runs-on: windows-latest steps: - name: Checkout uses: actions/checkout@v4 - name: Setup .NET uses: actions/setup-dotnet@v4 with: dotnet-version: "10.0.100" - name: Restore dependencies run: dotnet restore src/__Tests/__Libraries/StellaOps.Testing.Determinism.Properties/StellaOps.Testing.Determinism.Properties.csproj - name: Run determinism property tests run: | dotnet test src/__Tests/__Libraries/StellaOps.Testing.Determinism.Properties/StellaOps.Testing.Determinism.Properties.csproj ` --logger "trx;LogFileName=determinism-windows.trx" ` --results-directory ./test-results/windows - name: Generate hash report shell: pwsh run: | # Generate determinism baseline hashes $hashReport = @{ platform = "windows" timestamp = (Get-Date -Format "o") hashes = @{} } # Run hash generation script dotnet run --project tools/determinism-hash-generator -- ` --output ./test-results/windows/hashes.json # Upload for comparison Copy-Item ./test-results/windows/hashes.json ./test-results/windows-hashes.json - name: Upload Windows results uses: actions/upload-artifact@v4 with: name: determinism-windows path: | ./test-results/windows/ ./test-results/windows-hashes.json # DET-GAP-12: macOS determinism test runner determinism-macos: runs-on: macos-latest steps: - name: Checkout uses: actions/checkout@v4 - name: Setup .NET uses: actions/setup-dotnet@v4 with: dotnet-version: "10.0.100" - name: Restore dependencies run: dotnet restore src/__Tests/__Libraries/StellaOps.Testing.Determinism.Properties/StellaOps.Testing.Determinism.Properties.csproj - name: Run determinism property tests run: | dotnet test src/__Tests/__Libraries/StellaOps.Testing.Determinism.Properties/StellaOps.Testing.Determinism.Properties.csproj \ --logger "trx;LogFileName=determinism-macos.trx" \ --results-directory ./test-results/macos - name: Generate hash report run: | # Generate determinism baseline hashes dotnet run --project tools/determinism-hash-generator -- \ --output ./test-results/macos/hashes.json cp ./test-results/macos/hashes.json ./test-results/macos-hashes.json - name: Upload macOS results uses: actions/upload-artifact@v4 with: name: determinism-macos path: | ./test-results/macos/ ./test-results/macos-hashes.json # Linux runner (baseline) determinism-linux: runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v4 - name: Setup .NET uses: actions/setup-dotnet@v4 with: dotnet-version: "10.0.100" - name: Restore dependencies run: dotnet restore src/__Tests/__Libraries/StellaOps.Testing.Determinism.Properties/StellaOps.Testing.Determinism.Properties.csproj - name: Run determinism property tests run: | dotnet test src/__Tests/__Libraries/StellaOps.Testing.Determinism.Properties/StellaOps.Testing.Determinism.Properties.csproj \ --logger "trx;LogFileName=determinism-linux.trx" \ --results-directory ./test-results/linux - name: Generate hash report run: | # Generate determinism baseline hashes dotnet run --project tools/determinism-hash-generator -- \ --output ./test-results/linux/hashes.json cp ./test-results/linux/hashes.json ./test-results/linux-hashes.json - name: Upload Linux results uses: actions/upload-artifact@v4 with: name: determinism-linux path: | ./test-results/linux/ ./test-results/linux-hashes.json # DET-GAP-13: Cross-platform hash comparison report compare-hashes: runs-on: ubuntu-latest needs: [determinism-windows, determinism-macos, determinism-linux] steps: - name: Checkout uses: actions/checkout@v4 - name: Download all artifacts uses: actions/download-artifact@v4 with: path: ./artifacts - name: Setup Python uses: actions/setup-python@v5 with: python-version: '3.12' - name: Generate comparison report run: | python3 scripts/determinism/compare-platform-hashes.py \ --linux ./artifacts/determinism-linux/linux-hashes.json \ --windows ./artifacts/determinism-windows/windows-hashes.json \ --macos ./artifacts/determinism-macos/macos-hashes.json \ --output ./cross-platform-report.json \ --markdown ./cross-platform-report.md - name: Check for divergences run: | # Fail if any hashes differ across platforms python3 -c " import json import sys with open('./cross-platform-report.json') as f: report = json.load(f) divergences = report.get('divergences', []) if divergences: print(f'ERROR: {len(divergences)} hash divergence(s) detected!') for d in divergences: print(f' - {d[\"key\"]}: linux={d[\"linux\"]}, windows={d[\"windows\"]}, macos={d[\"macos\"]}') sys.exit(1) else: print('SUCCESS: All hashes match across platforms.') " - name: Upload comparison report uses: actions/upload-artifact@v4 with: name: cross-platform-comparison path: | ./cross-platform-report.json ./cross-platform-report.md - name: Comment on PR (if applicable) if: github.event_name == 'pull_request' uses: actions/github-script@v7 with: script: | const fs = require('fs'); const report = fs.readFileSync('./cross-platform-report.md', 'utf8'); github.rest.issues.createComment({ issue_number: context.issue.number, owner: context.repo.owner, repo: context.repo.repo, body: '## Cross-Platform Determinism Report\n\n' + report });