From 17e7e27155dca45dafc626bbb0ca8e8b3a67abf4 Mon Sep 17 00:00:00 2001 From: Josh Patra Date: Sun, 2 Aug 2026 16:33:15 -0400 Subject: [PATCH] perf(ci): report .NET lane timings --- .github/workflows/ci.yml | 38 ++++++++++++++++++++++++++++++------ tools/tests/timing_report.py | 7 +++++++ 2 files changed, 39 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5d1b7c14..c47d50e5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -69,16 +69,29 @@ jobs: pg_restore --version - name: Restore dependencies - run: dotnet restore -p:NuGetAudit=true + run: python3 tools/tests/timing_report.py --name dotnet-restore -- dotnet restore -p:NuGetAudit=true - name: Build - run: dotnet build --configuration Release --no-restore -p:TreatWarningsAsErrors=true + run: python3 tools/tests/timing_report.py --name dotnet-build -- dotnet build --configuration Release --no-restore -p:TreatWarningsAsErrors=true - name: Test run: >- + python3 tools/tests/timing_report.py + --name dotnet-test + --trx "${{ runner.temp }}/build-and-test.trx" + -- dotnet test --configuration Release --no-build --filter "FullyQualifiedName!~allstarr.Tests.DurableStateTransferServiceTests" --verbosity minimal + --logger "trx;LogFileName=${{ runner.temp }}/build-and-test.trx" + + - name: Upload .NET test results + if: always() + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 + with: + name: dotnet-test-results-build-and-test + path: ${{ runner.temp }}/build-and-test.trx + if-no-files-found: warn state-transfer-tests: runs-on: ubuntu-latest @@ -107,16 +120,29 @@ jobs: dotnet-version: ${{ env.DOTNET_VERSION }} - name: Restore dependencies - run: dotnet restore -p:NuGetAudit=true + run: python3 tools/tests/timing_report.py --name state-transfer-restore -- dotnet restore -p:NuGetAudit=true - name: Build - run: dotnet build --configuration Release --no-restore -p:TreatWarningsAsErrors=true + run: python3 tools/tests/timing_report.py --name state-transfer-build -- dotnet build --configuration Release --no-restore -p:TreatWarningsAsErrors=true - name: Test state transfer run: >- + python3 tools/tests/timing_report.py + --name state-transfer-test + --trx "${{ runner.temp }}/state-transfer-tests.trx" + -- dotnet test --configuration Release --no-build --filter "FullyQualifiedName~allstarr.Tests.DurableStateTransferServiceTests" --verbosity minimal + --logger "trx;LogFileName=${{ runner.temp }}/state-transfer-tests.trx" + + - name: Upload state-transfer test results + if: always() + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 + with: + name: dotnet-test-results-state-transfer + path: ${{ runner.temp }}/state-transfer-tests.trx + if-no-files-found: warn csharp-format: runs-on: ubuntu-latest @@ -130,10 +156,10 @@ jobs: dotnet-version: ${{ env.DOTNET_VERSION }} - name: Restore dependencies - run: dotnet restore -p:NuGetAudit=true + run: python3 tools/tests/timing_report.py --name csharp-restore -- dotnet restore -p:NuGetAudit=true - name: Verify C# formatting and analyzers - run: dotnet format allstarr.sln --no-restore --verify-no-changes --verbosity minimal + run: python3 tools/tests/timing_report.py --name csharp-format -- dotnet format allstarr.sln --no-restore --verify-no-changes --verbosity minimal webui: runs-on: ubuntu-latest diff --git a/tools/tests/timing_report.py b/tools/tests/timing_report.py index 191aa481..927319dc 100644 --- a/tools/tests/timing_report.py +++ b/tools/tests/timing_report.py @@ -162,6 +162,11 @@ def _duration(value: str) -> float | None: if seconds: hours, minutes, seconds_value = (float(item or 0) for item in seconds.groups()) return (hours * 3600 + minutes * 60 + seconds_value) * 1000 + timespan = re.fullmatch(r"(?:(\d+)\.)?(\d+):(\d{2}):(\d{2})(?:\.(\d+))?", value) + if timespan: + days, hours, minutes, seconds, fraction = timespan.groups() + whole_ms = ((int(days or 0) * 24 + int(hours)) * 60 + int(minutes)) * 60 + int(seconds) + return whole_ms * 1000 + (float(f"0.{fraction}") * 1000 if fraction else 0) return None @@ -291,6 +296,8 @@ def _self_test() -> None: assert _parse_retries("Retries: 2") == 2 assert _duration("PT1.25S") == 1250 assert _duration("12ms") == 12 + assert _duration("00:00:01.2500000") == 1250 + assert _duration("1.02:03:04.5") == 93784500 def main(argv: list[str] | None = None) -> int: