Benchmark Run 209 #209
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: Benchmark | |
| run-name: Benchmark Run ${{ github.run_number }} | |
| on: | |
| schedule: | |
| # Daily at 21:00 UTC | |
| - cron: '0 21 * * *' | |
| workflow_dispatch: | |
| inputs: | |
| gateway: | |
| description: 'Gateway to benchmark' | |
| required: false | |
| default: 'all' | |
| type: choice | |
| options: | |
| - all | |
| - apollo-gateway | |
| - apollo-router | |
| - cosmo | |
| - grafbase | |
| - hive-gateway | |
| - hive-gateway-router-runtime | |
| - hive-router | |
| - hotchocolate | |
| benchmark: | |
| description: 'Benchmark mode' | |
| required: false | |
| default: 'all' | |
| type: choice | |
| options: | |
| - all | |
| - constant | |
| - latency | |
| - burst | |
| runs: | |
| description: 'Number of benchmark runs per gateway' | |
| required: false | |
| default: '9' | |
| duration: | |
| description: 'Duration per run in seconds' | |
| required: false | |
| default: '120' | |
| diagnostic_run: | |
| description: 'Diagnostic run (collect diagnostics artifacts, skip result documents)' | |
| required: false | |
| default: false | |
| type: boolean | |
| concurrency: | |
| group: gateway-benchmarks | |
| cancel-in-progress: false | |
| permissions: | |
| actions: read | |
| contents: write | |
| jobs: | |
| prepare-matrix: | |
| runs-on: ubuntu-latest | |
| outputs: | |
| gateways: ${{ steps.build.outputs.gateways }} | |
| gateways_net: ${{ steps.build.outputs.gateways_net }} | |
| gateway_builds: ${{ steps.build.outputs.gateway_builds }} | |
| subgraph_builds: ${{ steps.build.outputs.subgraph_builds }} | |
| is_diagnostic: ${{ steps.flags.outputs.is_diagnostic }} | |
| should_publish: ${{ steps.flags.outputs.should_publish }} | |
| run_constant: ${{ steps.flags.outputs.run_constant }} | |
| run_burst: ${{ steps.flags.outputs.run_burst }} | |
| run_latency: ${{ steps.flags.outputs.run_latency }} | |
| steps: | |
| - name: Compute run flags | |
| id: flags | |
| run: | | |
| BENCHMARK="${{ inputs.benchmark || 'all' }}" | |
| GATEWAY="${{ inputs.gateway || 'all' }}" | |
| DIAGNOSTIC="${{ inputs.diagnostic_run }}" | |
| IS_DIAGNOSTIC="false" | |
| if [[ "$DIAGNOSTIC" == "true" ]]; then | |
| IS_DIAGNOSTIC="true" | |
| fi | |
| SHOULD_PUBLISH="false" | |
| if [[ "$GATEWAY" == "all" && "$BENCHMARK" == "all" && "$IS_DIAGNOSTIC" == "false" ]]; then | |
| SHOULD_PUBLISH="true" | |
| fi | |
| RUN_CONSTANT="false" | |
| if [[ "$BENCHMARK" == "all" || "$BENCHMARK" == "constant" ]]; then | |
| RUN_CONSTANT="true" | |
| fi | |
| RUN_BURST="false" | |
| if [[ "$BENCHMARK" == "all" || "$BENCHMARK" == "burst" ]]; then | |
| RUN_BURST="true" | |
| fi | |
| RUN_LATENCY="false" | |
| if [[ "$BENCHMARK" == "all" || "$BENCHMARK" == "latency" ]]; then | |
| RUN_LATENCY="true" | |
| fi | |
| { | |
| echo "is_diagnostic=$IS_DIAGNOSTIC" | |
| echo "should_publish=$SHOULD_PUBLISH" | |
| echo "run_constant=$RUN_CONSTANT" | |
| echo "run_burst=$RUN_BURST" | |
| echo "run_latency=$RUN_LATENCY" | |
| } >> "$GITHUB_OUTPUT" | |
| - name: Build gateway matrix | |
| id: build | |
| env: | |
| SELECTED_GATEWAY: ${{ inputs.gateway || 'all' }} | |
| run: | | |
| python3 - <<'PY' | |
| import json | |
| import os | |
| import sys | |
| selected = os.environ.get("SELECTED_GATEWAY", "all") | |
| aliases = { | |
| "hc": "hotchocolate", | |
| "hc-rust": "hotchocolate-rust", | |
| "hc-net": "hotchocolate-net", | |
| } | |
| selected = aliases.get(selected, selected) | |
| selected_gateway = selected | |
| selected_subgraph_tech = None | |
| if selected.endswith("-rust"): | |
| selected_gateway = selected[:-5] | |
| selected_subgraph_tech = "rust" | |
| elif selected.endswith("-net"): | |
| selected_gateway = selected[:-4] | |
| selected_subgraph_tech = ".net" | |
| base_gateways = [ | |
| { | |
| "path": "apollo-federation/gateways/apollo-gateway", | |
| "name": "apollo-gateway", | |
| "gateway_artifact": "prebuilt-gateway-apollo-gateway", | |
| }, | |
| { | |
| "path": "apollo-federation/gateways/apollo-router", | |
| "name": "apollo-router", | |
| "gateway_artifact": "prebuilt-gateway-apollo-router", | |
| }, | |
| { | |
| "path": "apollo-federation/gateways/cosmo", | |
| "name": "cosmo", | |
| "gateway_artifact": "prebuilt-gateway-cosmo", | |
| }, | |
| { | |
| "path": "apollo-federation/gateways/grafbase", | |
| "name": "grafbase", | |
| "gateway_artifact": "prebuilt-gateway-grafbase", | |
| }, | |
| { | |
| "path": "apollo-federation/gateways/hive-gateway", | |
| "name": "hive-gateway", | |
| "gateway_artifact": "prebuilt-gateway-hive-gateway", | |
| }, | |
| { | |
| "path": "apollo-federation/gateways/hive-gateway-router-runtime", | |
| "name": "hive-gateway-router-runtime", | |
| "gateway_artifact": "prebuilt-gateway-hive-gateway-router-runtime", | |
| }, | |
| { | |
| "path": "apollo-federation/gateways/hive-router", | |
| "name": "hive-router", | |
| "gateway_artifact": "prebuilt-gateway-hive-router", | |
| }, | |
| { | |
| "path": "composite-schema/gateways/hotchocolate", | |
| "name": "hotchocolate", | |
| "gateway_artifact": "prebuilt-gateway-hotchocolate", | |
| }, | |
| ] | |
| subgraph_variants_by_category = { | |
| "apollo-federation": [ | |
| { | |
| "dir": "subgraphs-rust", | |
| "tech": "rust", | |
| "artifact": "prebuilt-apollo-federation-subgraphs-rust", | |
| "suffix": "rust", | |
| }, | |
| { | |
| "dir": "subgraphs-net", | |
| "tech": ".net", | |
| "artifact": "prebuilt-apollo-federation-subgraphs-net", | |
| "suffix": "net", | |
| }, | |
| ], | |
| "composite-schema": [ | |
| { | |
| "dir": "subgraphs-rust", | |
| "tech": "rust", | |
| "artifact": "prebuilt-composite-schema-subgraphs-rust", | |
| "suffix": "rust", | |
| }, | |
| { | |
| "dir": "subgraphs-net", | |
| "tech": ".net", | |
| "artifact": "prebuilt-composite-schema-subgraphs-net", | |
| "suffix": "net", | |
| }, | |
| ], | |
| } | |
| gateways = [] | |
| for gateway in base_gateways: | |
| category = gateway["path"].split("/", 1)[0] | |
| variants = subgraph_variants_by_category.get(category, []) | |
| for variant in variants: | |
| gateways.append({ | |
| "path": gateway["path"], | |
| "name": f"{gateway['name']}-{variant['suffix']}", | |
| "base_name": gateway["name"], | |
| "subgraphs": variant["dir"], | |
| "subgraph_tech": variant["tech"], | |
| "display_name": f"{gateway['name']} ({variant['tech']} subgraphs)", | |
| "subgraphs_artifact": variant["artifact"], | |
| "gateway_artifact": gateway["gateway_artifact"], | |
| }) | |
| if selected == "all": | |
| chosen = gateways | |
| else: | |
| chosen = [entry for entry in gateways if entry["base_name"] == selected_gateway] | |
| if selected_subgraph_tech: | |
| chosen = [entry for entry in chosen if entry["subgraph_tech"] == selected_subgraph_tech] | |
| if not chosen: | |
| print(f"Error: no gateway entries match selection {selected!r}", file=sys.stderr) | |
| sys.exit(1) | |
| matrix_json = json.dumps(chosen, separators=(",", ":")) | |
| chosen_net = [e for e in chosen if e["subgraph_tech"] == ".net"] | |
| matrix_net_json = json.dumps(chosen_net, separators=(",", ":")) | |
| builds_by_artifact = {} | |
| for entry in chosen: | |
| artifact = entry["gateway_artifact"] | |
| if artifact in builds_by_artifact: | |
| continue | |
| builds_by_artifact[artifact] = { | |
| "path": entry["path"], | |
| "artifact": artifact, | |
| } | |
| build_matrix_json = json.dumps(list(builds_by_artifact.values()), separators=(",", ":")) | |
| subgraphs_by_artifact = {} | |
| for entry in chosen: | |
| artifact = entry["subgraphs_artifact"] | |
| if artifact in subgraphs_by_artifact: | |
| continue | |
| category = entry["path"].split("/", 1)[0] | |
| subgraphs_by_artifact[artifact] = { | |
| "path": f"{category}/{entry['subgraphs']}", | |
| "artifact": artifact, | |
| } | |
| subgraph_matrix_json = json.dumps(list(subgraphs_by_artifact.values()), separators=(",", ":")) | |
| with open(os.environ["GITHUB_OUTPUT"], "a", encoding="utf-8") as fh: | |
| fh.write(f"gateways={matrix_json}\n") | |
| fh.write(f"gateways_net={matrix_net_json}\n") | |
| fh.write(f"gateway_builds={build_matrix_json}\n") | |
| fh.write(f"subgraph_builds={subgraph_matrix_json}\n") | |
| print("Selected gateway entries:") | |
| for entry in chosen: | |
| print(f" - {entry['base_name']} [{entry['subgraph_tech']}]") | |
| print("Subgraph builds:") | |
| for sub in subgraphs_by_artifact.values(): | |
| print(f" - {sub['path']} ({sub['artifact']})") | |
| PY | |
| build-subgraphs: | |
| needs: prepare-matrix | |
| runs-on: ubuntu-latest | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| subgraphs: ${{ fromJson(needs.prepare-matrix.outputs.subgraph_builds) }} | |
| name: build-${{ matrix.subgraphs.path }} | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - name: Setup .NET SDK | |
| uses: actions/setup-dotnet@v5 | |
| with: | |
| global-json-file: global.json | |
| - name: Build subgraphs | |
| run: | | |
| chmod +x "${{ matrix.subgraphs.path }}/build.sh" | |
| (cd "${{ matrix.subgraphs.path }}" && bash build.sh) | |
| - name: Pack prebuilt subgraphs | |
| run: | | |
| tar -czf "prebuilt-subgraphs-${{ matrix.subgraphs.artifact }}.tar.gz" "${{ matrix.subgraphs.path }}" | |
| - name: Upload prebuilt subgraphs | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: ${{ matrix.subgraphs.artifact }} | |
| path: prebuilt-subgraphs-${{ matrix.subgraphs.artifact }}.tar.gz | |
| build-gateways: | |
| needs: prepare-matrix | |
| runs-on: ubuntu-latest | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| gateway: ${{ fromJson(needs.prepare-matrix.outputs.gateway_builds) }} | |
| name: build-${{ matrix.gateway.artifact }} | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - name: Setup .NET SDK | |
| uses: actions/setup-dotnet@v5 | |
| with: | |
| global-json-file: global.json | |
| - name: Build gateway | |
| run: | | |
| chmod +x "${{ matrix.gateway.path }}/install.sh" | |
| (cd "${{ matrix.gateway.path }}" && bash install.sh) | |
| touch "${{ matrix.gateway.path }}/.prebuilt-gateway-ready" | |
| - name: Pack prebuilt gateway | |
| run: | | |
| tar -czf "prebuilt-gateway-${{ matrix.gateway.artifact }}.tar.gz" "${{ matrix.gateway.path }}" | |
| - name: Upload prebuilt gateway | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: ${{ matrix.gateway.artifact }} | |
| path: prebuilt-gateway-${{ matrix.gateway.artifact }}.tar.gz | |
| benchmark-constant: | |
| needs: | |
| - prepare-matrix | |
| - build-subgraphs | |
| - build-gateways | |
| - benchmark-constant-latency | |
| if: ${{ always() && !cancelled() && needs.prepare-matrix.outputs.run_constant == 'true' }} | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| gateway: ${{ fromJson(needs.prepare-matrix.outputs.gateways) }} | |
| runs-on: | |
| group: benchmarking-1 | |
| name: ${{ matrix.gateway.name }} (constant) | |
| env: | |
| BENCH_RUNS: ${{ inputs.runs || '9' }} | |
| MEASURE_SECONDS: ${{ inputs.duration || '120' }} | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - name: Download prebuilt gateway | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: ${{ matrix.gateway.gateway_artifact }} | |
| path: prebuilt-gateway/ | |
| - name: Restore prebuilt gateway | |
| run: | | |
| GATEWAY_ARCHIVE="$(find prebuilt-gateway -type f -name '*.tar.gz' | head -n1)" | |
| if [[ -z "$GATEWAY_ARCHIVE" ]]; then | |
| echo "Error: prebuilt gateway archive not found" | |
| find prebuilt-gateway -maxdepth 3 -print | |
| exit 1 | |
| fi | |
| tar -xzf "$GATEWAY_ARCHIVE" -C . | |
| if [[ -f apollo-federation/gateways/apollo-router/router ]]; then | |
| chmod +x apollo-federation/gateways/apollo-router/router | |
| fi | |
| if [[ -f apollo-federation/gateways/cosmo/cosmo ]]; then | |
| chmod +x apollo-federation/gateways/cosmo/cosmo | |
| fi | |
| if [[ -f apollo-federation/gateways/grafbase/grafbase-gateway ]]; then | |
| chmod +x apollo-federation/gateways/grafbase/grafbase-gateway | |
| fi | |
| if [[ -f apollo-federation/gateways/hive-router/hive_router ]]; then | |
| chmod +x apollo-federation/gateways/hive-router/hive_router | |
| fi | |
| - name: Download prebuilt subgraphs | |
| continue-on-error: true | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: ${{ matrix.gateway.subgraphs_artifact }} | |
| path: prebuilt-subgraphs/ | |
| - name: Restore prebuilt subgraphs | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| GATEWAY_PATH: ${{ matrix.gateway.path }} | |
| SUBGRAPHS_DIR: ${{ matrix.gateway.subgraphs }} | |
| SUBGRAPHS_ARTIFACT: ${{ matrix.gateway.subgraphs_artifact }} | |
| run: | | |
| set -euo pipefail | |
| find_subgraphs_archive() { | |
| find prebuilt-subgraphs -type f -name '*.tar.gz' | head -n1 | |
| } | |
| redownload_subgraphs_artifact() { | |
| rm -rf prebuilt-subgraphs | |
| mkdir -p prebuilt-subgraphs | |
| gh run download "$GITHUB_RUN_ID" --repo "$GITHUB_REPOSITORY" --name "$SUBGRAPHS_ARTIFACT" --dir prebuilt-subgraphs | |
| } | |
| ATTEMPTS=3 | |
| for attempt in $(seq 1 "$ATTEMPTS"); do | |
| SUBGRAPHS_ARCHIVE="$(find_subgraphs_archive)" | |
| if [[ -z "$SUBGRAPHS_ARCHIVE" ]]; then | |
| echo "Subgraphs archive not found (attempt $attempt/$ATTEMPTS)" | |
| elif tar -tzf "$SUBGRAPHS_ARCHIVE" >/dev/null 2>&1; then | |
| tar -xzf "$SUBGRAPHS_ARCHIVE" -C . | |
| if [[ -f apollo-federation/subgraphs-rust/target/release/subgraphs ]]; then | |
| chmod +x apollo-federation/subgraphs-rust/target/release/subgraphs | |
| fi | |
| if [[ -f composite-schema/subgraphs-rust/target/release/subgraphs ]]; then | |
| chmod +x composite-schema/subgraphs-rust/target/release/subgraphs | |
| fi | |
| exit 0 | |
| else | |
| echo "Subgraphs archive integrity check failed (attempt $attempt/$ATTEMPTS): $SUBGRAPHS_ARCHIVE" | |
| ls -lh "$SUBGRAPHS_ARCHIVE" || true | |
| fi | |
| if [[ "$attempt" -lt "$ATTEMPTS" ]]; then | |
| echo "Re-downloading artifact '$SUBGRAPHS_ARTIFACT' for retry..." | |
| if ! redownload_subgraphs_artifact; then | |
| echo "Artifact re-download failed (attempt $((attempt + 1))/$ATTEMPTS)." | |
| fi | |
| sleep $((attempt * 5)) | |
| fi | |
| done | |
| find prebuilt-subgraphs -maxdepth 3 -print || true | |
| SUBGRAPHS_ROOT="${GATEWAY_PATH%%/*}" | |
| SUBGRAPHS_PATH="${SUBGRAPHS_ROOT}/${SUBGRAPHS_DIR}" | |
| echo "Archive restore failed after $ATTEMPTS attempts; falling back to local rebuild: $SUBGRAPHS_PATH" | |
| if [[ ! -f "$SUBGRAPHS_PATH/build.sh" ]]; then | |
| echo "Error: fallback build script not found: $SUBGRAPHS_PATH/build.sh" | |
| exit 1 | |
| fi | |
| chmod +x "$SUBGRAPHS_PATH/build.sh" | |
| (cd "$SUBGRAPHS_PATH" && bash build.sh) | |
| if [[ -f apollo-federation/subgraphs-rust/target/release/subgraphs ]]; then | |
| chmod +x apollo-federation/subgraphs-rust/target/release/subgraphs | |
| fi | |
| if [[ -f composite-schema/subgraphs-rust/target/release/subgraphs ]]; then | |
| chmod +x composite-schema/subgraphs-rust/target/release/subgraphs | |
| fi | |
| - name: Kill stale perfrunner processes | |
| run: | | |
| sudo pkill -u perfrunner || true | |
| sleep 1 | |
| sudo pkill -9 -u perfrunner || true | |
| - name: Prepare workspace for perfrunner | |
| run: | | |
| # Both users need write access during a run: | |
| # - perfrunner writes dependency artifacts (node_modules, target, etc.) | |
| # - github-runner writes benchmark outputs (results/, summaries) | |
| sudo chmod -R a+rX,g+rwX . | |
| sudo chown -R perfrunner:github-runner . | |
| # Preserve github-runner as group owner for newly created files/dirs. | |
| sudo find . -type d -exec chmod g+s {} + | |
| - name: Prepare diagnostics directory | |
| if: ${{ needs.prepare-matrix.outputs.is_diagnostic == 'true' }} | |
| run: | | |
| mkdir -p "${{ matrix.gateway.path }}/diagnostics" | |
| { | |
| echo "diagnostic_run=true" | |
| echo "mode=constant" | |
| echo "gateway=${{ matrix.gateway.name }}" | |
| echo "started_utc=${{ github.run_started_at || 'n/a' }}" | |
| echo "run_id=${{ github.run_id }}" | |
| } > "${{ matrix.gateway.path }}/diagnostics/run-info.txt" | |
| sudo chown -R perfrunner:github-runner "${{ matrix.gateway.path }}/diagnostics" | |
| sudo chmod -R u+rwX,g+rwX "${{ matrix.gateway.path }}/diagnostics" | |
| - name: Run benchmark | |
| run: ./k6/benchmark.sh ${{ matrix.gateway.path }} ${{ matrix.gateway.subgraphs }} constant | |
| env: | |
| BENCH_DISPLAY_NAME: ${{ matrix.gateway.display_name || '' }} | |
| BENCH_SUBGRAPH_TECH: ${{ matrix.gateway.subgraph_tech || '' }} | |
| BENCH_DIAGNOSTIC_RUN: ${{ needs.prepare-matrix.outputs.is_diagnostic == 'true' && '1' || '0' }} | |
| BENCH_DIAGNOSTICS_DIR: ${{ github.workspace }}/${{ matrix.gateway.path }}/diagnostics | |
| USE_PREBUILT_SUBGRAPHS: "1" | |
| USE_PREBUILT_GATEWAY: "1" | |
| - name: Kill all perfrunner processes | |
| if: always() | |
| run: | | |
| echo "Killing all perfrunner processes..." | |
| sudo pkill -u perfrunner || true | |
| sleep 2 | |
| sudo pkill -9 -u perfrunner || true | |
| echo "Done." | |
| - name: Reclaim workspace ownership | |
| if: always() | |
| run: sudo chown -R $(id -u):$(id -g) . | |
| - name: Upload results | |
| if: always() | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: results-${{ matrix.gateway.name }}-constant | |
| path: ${{ matrix.gateway.path }}/results/ | |
| - name: Inspect diagnostics directory | |
| if: ${{ always() && needs.prepare-matrix.outputs.is_diagnostic == 'true' }} | |
| run: | | |
| echo "Diagnostics directory: ${{ matrix.gateway.path }}/diagnostics" | |
| ls -la "${{ matrix.gateway.path }}/diagnostics" || true | |
| find "${{ matrix.gateway.path }}/diagnostics" -maxdepth 2 -type f -print | sort || true | |
| - name: Upload diagnostics | |
| if: ${{ always() && needs.prepare-matrix.outputs.is_diagnostic == 'true' }} | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: diagnostics-${{ matrix.gateway.name }}-constant | |
| path: ${{ matrix.gateway.path }}/diagnostics/ | |
| if-no-files-found: ignore | |
| benchmark-burst: | |
| needs: | |
| - prepare-matrix | |
| - build-subgraphs | |
| - build-gateways | |
| - benchmark-constant | |
| if: ${{ always() && !cancelled() && needs.prepare-matrix.outputs.run_burst == 'true' }} | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| gateway: ${{ fromJson(needs.prepare-matrix.outputs.gateways) }} | |
| runs-on: | |
| group: benchmarking-1 | |
| name: ${{ matrix.gateway.name }} (burst) | |
| env: | |
| BENCH_RUNS: ${{ inputs.runs || '9' }} | |
| MEASURE_SECONDS: ${{ inputs.duration || '120' }} | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - name: Download prebuilt gateway | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: ${{ matrix.gateway.gateway_artifact }} | |
| path: prebuilt-gateway/ | |
| - name: Restore prebuilt gateway | |
| run: | | |
| GATEWAY_ARCHIVE="$(find prebuilt-gateway -type f -name '*.tar.gz' | head -n1)" | |
| if [[ -z "$GATEWAY_ARCHIVE" ]]; then | |
| echo "Error: prebuilt gateway archive not found" | |
| find prebuilt-gateway -maxdepth 3 -print | |
| exit 1 | |
| fi | |
| tar -xzf "$GATEWAY_ARCHIVE" -C . | |
| if [[ -f apollo-federation/gateways/apollo-router/router ]]; then | |
| chmod +x apollo-federation/gateways/apollo-router/router | |
| fi | |
| if [[ -f apollo-federation/gateways/cosmo/cosmo ]]; then | |
| chmod +x apollo-federation/gateways/cosmo/cosmo | |
| fi | |
| if [[ -f apollo-federation/gateways/grafbase/grafbase-gateway ]]; then | |
| chmod +x apollo-federation/gateways/grafbase/grafbase-gateway | |
| fi | |
| if [[ -f apollo-federation/gateways/hive-router/hive_router ]]; then | |
| chmod +x apollo-federation/gateways/hive-router/hive_router | |
| fi | |
| - name: Download prebuilt subgraphs | |
| continue-on-error: true | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: ${{ matrix.gateway.subgraphs_artifact }} | |
| path: prebuilt-subgraphs/ | |
| - name: Restore prebuilt subgraphs | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| GATEWAY_PATH: ${{ matrix.gateway.path }} | |
| SUBGRAPHS_DIR: ${{ matrix.gateway.subgraphs }} | |
| SUBGRAPHS_ARTIFACT: ${{ matrix.gateway.subgraphs_artifact }} | |
| run: | | |
| set -euo pipefail | |
| find_subgraphs_archive() { | |
| find prebuilt-subgraphs -type f -name '*.tar.gz' | head -n1 | |
| } | |
| redownload_subgraphs_artifact() { | |
| rm -rf prebuilt-subgraphs | |
| mkdir -p prebuilt-subgraphs | |
| gh run download "$GITHUB_RUN_ID" --repo "$GITHUB_REPOSITORY" --name "$SUBGRAPHS_ARTIFACT" --dir prebuilt-subgraphs | |
| } | |
| ATTEMPTS=3 | |
| for attempt in $(seq 1 "$ATTEMPTS"); do | |
| SUBGRAPHS_ARCHIVE="$(find_subgraphs_archive)" | |
| if [[ -z "$SUBGRAPHS_ARCHIVE" ]]; then | |
| echo "Subgraphs archive not found (attempt $attempt/$ATTEMPTS)" | |
| elif tar -tzf "$SUBGRAPHS_ARCHIVE" >/dev/null 2>&1; then | |
| tar -xzf "$SUBGRAPHS_ARCHIVE" -C . | |
| if [[ -f apollo-federation/subgraphs-rust/target/release/subgraphs ]]; then | |
| chmod +x apollo-federation/subgraphs-rust/target/release/subgraphs | |
| fi | |
| if [[ -f composite-schema/subgraphs-rust/target/release/subgraphs ]]; then | |
| chmod +x composite-schema/subgraphs-rust/target/release/subgraphs | |
| fi | |
| exit 0 | |
| else | |
| echo "Subgraphs archive integrity check failed (attempt $attempt/$ATTEMPTS): $SUBGRAPHS_ARCHIVE" | |
| ls -lh "$SUBGRAPHS_ARCHIVE" || true | |
| fi | |
| if [[ "$attempt" -lt "$ATTEMPTS" ]]; then | |
| echo "Re-downloading artifact '$SUBGRAPHS_ARTIFACT' for retry..." | |
| if ! redownload_subgraphs_artifact; then | |
| echo "Artifact re-download failed (attempt $((attempt + 1))/$ATTEMPTS)." | |
| fi | |
| sleep $((attempt * 5)) | |
| fi | |
| done | |
| find prebuilt-subgraphs -maxdepth 3 -print || true | |
| SUBGRAPHS_ROOT="${GATEWAY_PATH%%/*}" | |
| SUBGRAPHS_PATH="${SUBGRAPHS_ROOT}/${SUBGRAPHS_DIR}" | |
| echo "Archive restore failed after $ATTEMPTS attempts; falling back to local rebuild: $SUBGRAPHS_PATH" | |
| if [[ ! -f "$SUBGRAPHS_PATH/build.sh" ]]; then | |
| echo "Error: fallback build script not found: $SUBGRAPHS_PATH/build.sh" | |
| exit 1 | |
| fi | |
| chmod +x "$SUBGRAPHS_PATH/build.sh" | |
| (cd "$SUBGRAPHS_PATH" && bash build.sh) | |
| if [[ -f apollo-federation/subgraphs-rust/target/release/subgraphs ]]; then | |
| chmod +x apollo-federation/subgraphs-rust/target/release/subgraphs | |
| fi | |
| if [[ -f composite-schema/subgraphs-rust/target/release/subgraphs ]]; then | |
| chmod +x composite-schema/subgraphs-rust/target/release/subgraphs | |
| fi | |
| - name: Kill stale perfrunner processes | |
| run: | | |
| sudo pkill -u perfrunner || true | |
| sleep 1 | |
| sudo pkill -9 -u perfrunner || true | |
| - name: Prepare workspace for perfrunner | |
| run: | | |
| # Both users need write access during a run: | |
| # - perfrunner writes dependency artifacts (node_modules, target, etc.) | |
| # - github-runner writes benchmark outputs (results/, summaries) | |
| sudo chmod -R a+rX,g+rwX . | |
| sudo chown -R perfrunner:github-runner . | |
| # Preserve github-runner as group owner for newly created files/dirs. | |
| sudo find . -type d -exec chmod g+s {} + | |
| - name: Prepare diagnostics directory | |
| if: ${{ needs.prepare-matrix.outputs.is_diagnostic == 'true' }} | |
| run: | | |
| mkdir -p "${{ matrix.gateway.path }}/diagnostics" | |
| { | |
| echo "diagnostic_run=true" | |
| echo "mode=burst" | |
| echo "gateway=${{ matrix.gateway.name }}" | |
| echo "started_utc=${{ github.run_started_at || 'n/a' }}" | |
| echo "run_id=${{ github.run_id }}" | |
| } > "${{ matrix.gateway.path }}/diagnostics/run-info.txt" | |
| sudo chown -R perfrunner:github-runner "${{ matrix.gateway.path }}/diagnostics" | |
| sudo chmod -R u+rwX,g+rwX "${{ matrix.gateway.path }}/diagnostics" | |
| - name: Run benchmark | |
| run: ./k6/benchmark.sh ${{ matrix.gateway.path }} ${{ matrix.gateway.subgraphs }} burst | |
| env: | |
| BENCH_DISPLAY_NAME: ${{ matrix.gateway.display_name || '' }} | |
| BENCH_SUBGRAPH_TECH: ${{ matrix.gateway.subgraph_tech || '' }} | |
| BENCH_DIAGNOSTIC_RUN: ${{ needs.prepare-matrix.outputs.is_diagnostic == 'true' && '1' || '0' }} | |
| BENCH_DIAGNOSTICS_DIR: ${{ github.workspace }}/${{ matrix.gateway.path }}/diagnostics | |
| USE_PREBUILT_SUBGRAPHS: "1" | |
| USE_PREBUILT_GATEWAY: "1" | |
| - name: Kill all perfrunner processes | |
| if: always() | |
| run: | | |
| echo "Killing all perfrunner processes..." | |
| sudo pkill -u perfrunner || true | |
| sleep 2 | |
| sudo pkill -9 -u perfrunner || true | |
| echo "Done." | |
| - name: Reclaim workspace ownership | |
| if: always() | |
| run: sudo chown -R $(id -u):$(id -g) . | |
| - name: Upload results | |
| if: always() | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: results-${{ matrix.gateway.name }}-burst | |
| path: ${{ matrix.gateway.path }}/results/ | |
| - name: Inspect diagnostics directory | |
| if: ${{ always() && needs.prepare-matrix.outputs.is_diagnostic == 'true' }} | |
| run: | | |
| echo "Diagnostics directory: ${{ matrix.gateway.path }}/diagnostics" | |
| ls -la "${{ matrix.gateway.path }}/diagnostics" || true | |
| find "${{ matrix.gateway.path }}/diagnostics" -maxdepth 2 -type f -print | sort || true | |
| - name: Upload diagnostics | |
| if: ${{ always() && needs.prepare-matrix.outputs.is_diagnostic == 'true' }} | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: diagnostics-${{ matrix.gateway.name }}-burst | |
| path: ${{ matrix.gateway.path }}/diagnostics/ | |
| if-no-files-found: ignore | |
| benchmark-constant-latency: | |
| needs: | |
| - prepare-matrix | |
| - build-subgraphs | |
| - build-gateways | |
| if: ${{ always() && !cancelled() && needs.prepare-matrix.outputs.run_latency == 'true' }} | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| gateway: ${{ fromJson(needs.prepare-matrix.outputs.gateways_net) }} | |
| runs-on: | |
| group: benchmarking-1 | |
| name: ${{ matrix.gateway.name }} (constant-latency) | |
| env: | |
| BENCH_RUNS: ${{ inputs.runs || '9' }} | |
| MEASURE_SECONDS: ${{ inputs.duration || '120' }} | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - name: Download prebuilt gateway | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: ${{ matrix.gateway.gateway_artifact }} | |
| path: prebuilt-gateway/ | |
| - name: Restore prebuilt gateway | |
| run: | | |
| GATEWAY_ARCHIVE="$(find prebuilt-gateway -type f -name '*.tar.gz' | head -n1)" | |
| if [[ -z "$GATEWAY_ARCHIVE" ]]; then | |
| echo "Error: prebuilt gateway archive not found" | |
| find prebuilt-gateway -maxdepth 3 -print | |
| exit 1 | |
| fi | |
| tar -xzf "$GATEWAY_ARCHIVE" -C . | |
| if [[ -f apollo-federation/gateways/apollo-router/router ]]; then | |
| chmod +x apollo-federation/gateways/apollo-router/router | |
| fi | |
| if [[ -f apollo-federation/gateways/cosmo/cosmo ]]; then | |
| chmod +x apollo-federation/gateways/cosmo/cosmo | |
| fi | |
| if [[ -f apollo-federation/gateways/grafbase/grafbase-gateway ]]; then | |
| chmod +x apollo-federation/gateways/grafbase/grafbase-gateway | |
| fi | |
| if [[ -f apollo-federation/gateways/hive-router/hive_router ]]; then | |
| chmod +x apollo-federation/gateways/hive-router/hive_router | |
| fi | |
| - name: Download prebuilt subgraphs | |
| continue-on-error: true | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: ${{ matrix.gateway.subgraphs_artifact }} | |
| path: prebuilt-subgraphs/ | |
| - name: Restore prebuilt subgraphs | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| GATEWAY_PATH: ${{ matrix.gateway.path }} | |
| SUBGRAPHS_DIR: ${{ matrix.gateway.subgraphs }} | |
| SUBGRAPHS_ARTIFACT: ${{ matrix.gateway.subgraphs_artifact }} | |
| run: | | |
| set -euo pipefail | |
| find_subgraphs_archive() { | |
| find prebuilt-subgraphs -type f -name '*.tar.gz' | head -n1 | |
| } | |
| redownload_subgraphs_artifact() { | |
| rm -rf prebuilt-subgraphs | |
| mkdir -p prebuilt-subgraphs | |
| gh run download "$GITHUB_RUN_ID" --repo "$GITHUB_REPOSITORY" --name "$SUBGRAPHS_ARTIFACT" --dir prebuilt-subgraphs | |
| } | |
| ATTEMPTS=3 | |
| for attempt in $(seq 1 "$ATTEMPTS"); do | |
| SUBGRAPHS_ARCHIVE="$(find_subgraphs_archive)" | |
| if [[ -z "$SUBGRAPHS_ARCHIVE" ]]; then | |
| echo "Subgraphs archive not found (attempt $attempt/$ATTEMPTS)" | |
| elif tar -tzf "$SUBGRAPHS_ARCHIVE" >/dev/null 2>&1; then | |
| tar -xzf "$SUBGRAPHS_ARCHIVE" -C . | |
| if [[ -f apollo-federation/subgraphs-rust/target/release/subgraphs ]]; then | |
| chmod +x apollo-federation/subgraphs-rust/target/release/subgraphs | |
| fi | |
| if [[ -f composite-schema/subgraphs-rust/target/release/subgraphs ]]; then | |
| chmod +x composite-schema/subgraphs-rust/target/release/subgraphs | |
| fi | |
| exit 0 | |
| else | |
| echo "Subgraphs archive integrity check failed (attempt $attempt/$ATTEMPTS): $SUBGRAPHS_ARCHIVE" | |
| ls -lh "$SUBGRAPHS_ARCHIVE" || true | |
| fi | |
| if [[ "$attempt" -lt "$ATTEMPTS" ]]; then | |
| echo "Re-downloading artifact '$SUBGRAPHS_ARTIFACT' for retry..." | |
| if ! redownload_subgraphs_artifact; then | |
| echo "Artifact re-download failed (attempt $((attempt + 1))/$ATTEMPTS)." | |
| fi | |
| sleep $((attempt * 5)) | |
| fi | |
| done | |
| find prebuilt-subgraphs -maxdepth 3 -print || true | |
| SUBGRAPHS_ROOT="${GATEWAY_PATH%%/*}" | |
| SUBGRAPHS_PATH="${SUBGRAPHS_ROOT}/${SUBGRAPHS_DIR}" | |
| echo "Archive restore failed after $ATTEMPTS attempts; falling back to local rebuild: $SUBGRAPHS_PATH" | |
| if [[ ! -f "$SUBGRAPHS_PATH/build.sh" ]]; then | |
| echo "Error: fallback build script not found: $SUBGRAPHS_PATH/build.sh" | |
| exit 1 | |
| fi | |
| chmod +x "$SUBGRAPHS_PATH/build.sh" | |
| (cd "$SUBGRAPHS_PATH" && bash build.sh) | |
| if [[ -f apollo-federation/subgraphs-rust/target/release/subgraphs ]]; then | |
| chmod +x apollo-federation/subgraphs-rust/target/release/subgraphs | |
| fi | |
| if [[ -f composite-schema/subgraphs-rust/target/release/subgraphs ]]; then | |
| chmod +x composite-schema/subgraphs-rust/target/release/subgraphs | |
| fi | |
| - name: Kill stale perfrunner processes | |
| run: | | |
| sudo pkill -u perfrunner || true | |
| sleep 1 | |
| sudo pkill -9 -u perfrunner || true | |
| - name: Prepare workspace for perfrunner | |
| run: | | |
| sudo chmod -R a+rX,g+rwX . | |
| sudo chown -R perfrunner:github-runner . | |
| sudo find . -type d -exec chmod g+s {} + | |
| - name: Prepare diagnostics directory | |
| if: ${{ needs.prepare-matrix.outputs.is_diagnostic == 'true' }} | |
| run: | | |
| mkdir -p "${{ matrix.gateway.path }}/diagnostics" | |
| { | |
| echo "diagnostic_run=true" | |
| echo "mode=constant-latency" | |
| echo "gateway=${{ matrix.gateway.name }}" | |
| echo "started_utc=${{ github.run_started_at || 'n/a' }}" | |
| echo "run_id=${{ github.run_id }}" | |
| } > "${{ matrix.gateway.path }}/diagnostics/run-info.txt" | |
| sudo chown -R perfrunner:github-runner "${{ matrix.gateway.path }}/diagnostics" | |
| sudo chmod -R u+rwX,g+rwX "${{ matrix.gateway.path }}/diagnostics" | |
| - name: Run benchmark | |
| run: ./k6/benchmark.sh ${{ matrix.gateway.path }} ${{ matrix.gateway.subgraphs }} constant-latency | |
| env: | |
| BENCH_DISPLAY_NAME: ${{ matrix.gateway.display_name || '' }} | |
| BENCH_SUBGRAPH_TECH: ${{ matrix.gateway.subgraph_tech || '' }} | |
| BENCH_DIAGNOSTIC_RUN: ${{ needs.prepare-matrix.outputs.is_diagnostic == 'true' && '1' || '0' }} | |
| BENCH_DIAGNOSTICS_DIR: ${{ github.workspace }}/${{ matrix.gateway.path }}/diagnostics | |
| USE_PREBUILT_SUBGRAPHS: "1" | |
| USE_PREBUILT_GATEWAY: "1" | |
| - name: Kill all perfrunner processes | |
| if: always() | |
| run: | | |
| echo "Killing all perfrunner processes..." | |
| sudo pkill -u perfrunner || true | |
| sleep 2 | |
| sudo pkill -9 -u perfrunner || true | |
| echo "Done." | |
| - name: Reclaim workspace ownership | |
| if: always() | |
| run: sudo chown -R $(id -u):$(id -g) . | |
| - name: Upload results | |
| if: always() | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: results-${{ matrix.gateway.name }}-constant-latency | |
| path: ${{ matrix.gateway.path }}/results/ | |
| - name: Inspect diagnostics directory | |
| if: ${{ always() && needs.prepare-matrix.outputs.is_diagnostic == 'true' }} | |
| run: | | |
| echo "Diagnostics directory: ${{ matrix.gateway.path }}/diagnostics" | |
| ls -la "${{ matrix.gateway.path }}/diagnostics" || true | |
| find "${{ matrix.gateway.path }}/diagnostics" -maxdepth 2 -type f -print | sort || true | |
| - name: Upload diagnostics | |
| if: ${{ always() && needs.prepare-matrix.outputs.is_diagnostic == 'true' }} | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: diagnostics-${{ matrix.gateway.name }}-constant-latency | |
| path: ${{ matrix.gateway.path }}/diagnostics/ | |
| if-no-files-found: ignore | |
| generate-results-constant: | |
| needs: | |
| - prepare-matrix | |
| - benchmark-constant | |
| - generate-results-constant-latency | |
| if: ${{ always() && !cancelled() && needs.prepare-matrix.outputs.should_publish == 'true' }} | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v6 | |
| with: | |
| ref: ${{ github.ref_name }} | |
| - uses: actions/download-artifact@v8 | |
| with: | |
| pattern: results-*-constant | |
| path: artifacts/ | |
| - name: Generate constant result document | |
| env: | |
| EXPECTED_GATEWAYS_JSON: ${{ needs.prepare-matrix.outputs.gateways }} | |
| EXPECTED_GATEWAYS_NET_JSON: ${{ needs.prepare-matrix.outputs.gateways_net }} | |
| RESULT_MODES: constant | |
| run: python3 k6/generate-results.py artifacts/ benchmark-runs/${{ github.run_number }} | |
| - name: Write constant summary | |
| run: | | |
| RUN_RESULTS_DIR="benchmark-runs/${{ github.run_number }}" | |
| CONSTANT_RESULTS_FILE="$RUN_RESULTS_DIR/RESULTS_CONSTANT.md" | |
| echo "# Benchmark Results (Constant)" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| if [[ -f "$CONSTANT_RESULTS_FILE" ]]; then | |
| cat "$CONSTANT_RESULTS_FILE" >> $GITHUB_STEP_SUMMARY | |
| else | |
| echo "No constant results were generated." >> $GITHUB_STEP_SUMMARY | |
| fi | |
| - name: Commit constant results | |
| run: | | |
| RUN_RESULTS_DIR="benchmark-runs/${{ github.run_number }}" | |
| CONSTANT_RESULTS_FILE="$RUN_RESULTS_DIR/RESULTS_CONSTANT.md" | |
| git config user.name "github-actions[bot]" | |
| git config user.email "github-actions[bot]@users.noreply.github.com" | |
| if [[ -f "$CONSTANT_RESULTS_FILE" ]]; then | |
| git add "$CONSTANT_RESULTS_FILE" | |
| fi | |
| git diff --cached --quiet || git commit -m "Add constant benchmark results for run #${{ github.run_number }}" | |
| git push | |
| - name: Upload combined constant results | |
| if: always() | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: all-results-constant | |
| path: artifacts/ | |
| generate-results-burst: | |
| needs: | |
| - prepare-matrix | |
| - benchmark-burst | |
| - generate-results-constant | |
| if: ${{ !cancelled() && needs.prepare-matrix.outputs.should_publish == 'true' }} | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v6 | |
| with: | |
| ref: ${{ github.ref_name }} | |
| - uses: actions/download-artifact@v8 | |
| with: | |
| pattern: results-*-burst | |
| path: artifacts/ | |
| - name: Generate burst result document | |
| env: | |
| EXPECTED_GATEWAYS_JSON: ${{ needs.prepare-matrix.outputs.gateways }} | |
| EXPECTED_GATEWAYS_NET_JSON: ${{ needs.prepare-matrix.outputs.gateways_net }} | |
| RESULT_MODES: burst | |
| run: python3 k6/generate-results.py artifacts/ benchmark-runs/${{ github.run_number }} | |
| - name: Write burst summary | |
| run: | | |
| RUN_RESULTS_DIR="benchmark-runs/${{ github.run_number }}" | |
| BURST_RESULTS_FILE="$RUN_RESULTS_DIR/RESULTS_BURST.md" | |
| echo "# Benchmark Results (Burst)" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| if [[ -f "$BURST_RESULTS_FILE" ]]; then | |
| cat "$BURST_RESULTS_FILE" >> $GITHUB_STEP_SUMMARY | |
| else | |
| echo "No burst results were generated." >> $GITHUB_STEP_SUMMARY | |
| fi | |
| - name: Commit burst results | |
| run: | | |
| RUN_RESULTS_DIR="benchmark-runs/${{ github.run_number }}" | |
| BURST_RESULTS_FILE="$RUN_RESULTS_DIR/RESULTS_BURST.md" | |
| git config user.name "github-actions[bot]" | |
| git config user.email "github-actions[bot]@users.noreply.github.com" | |
| if [[ -f "$BURST_RESULTS_FILE" ]]; then | |
| git add "$BURST_RESULTS_FILE" | |
| fi | |
| git diff --cached --quiet || git commit -m "Add burst benchmark results for run #${{ github.run_number }}" | |
| git push | |
| - name: Upload combined burst results | |
| if: always() | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: all-results-burst | |
| path: artifacts/ | |
| generate-results-constant-latency: | |
| needs: | |
| - prepare-matrix | |
| - benchmark-constant-latency | |
| if: ${{ !cancelled() && needs.prepare-matrix.outputs.should_publish == 'true' }} | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v6 | |
| with: | |
| ref: ${{ github.ref_name }} | |
| - uses: actions/download-artifact@v8 | |
| with: | |
| pattern: results-*-constant-latency | |
| path: artifacts/ | |
| - name: Generate constant-latency result document | |
| env: | |
| EXPECTED_GATEWAYS_JSON: ${{ needs.prepare-matrix.outputs.gateways }} | |
| EXPECTED_GATEWAYS_NET_JSON: ${{ needs.prepare-matrix.outputs.gateways_net }} | |
| RESULT_MODES: constant-latency | |
| run: python3 k6/generate-results.py artifacts/ benchmark-runs/${{ github.run_number }} | |
| - name: Write constant-latency summary | |
| run: | | |
| RUN_RESULTS_DIR="benchmark-runs/${{ github.run_number }}" | |
| CONSTANT_LATENCY_RESULTS_FILE="$RUN_RESULTS_DIR/RESULTS_CONSTANT_LATENCY.md" | |
| echo "# Benchmark Results (Constant Latency)" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| if [[ -f "$CONSTANT_LATENCY_RESULTS_FILE" ]]; then | |
| cat "$CONSTANT_LATENCY_RESULTS_FILE" >> $GITHUB_STEP_SUMMARY | |
| else | |
| echo "No constant-latency results were generated." >> $GITHUB_STEP_SUMMARY | |
| fi | |
| - name: Commit constant-latency results | |
| run: | | |
| RUN_RESULTS_DIR="benchmark-runs/${{ github.run_number }}" | |
| CONSTANT_LATENCY_RESULTS_FILE="$RUN_RESULTS_DIR/RESULTS_CONSTANT_LATENCY.md" | |
| git config user.name "github-actions[bot]" | |
| git config user.email "github-actions[bot]@users.noreply.github.com" | |
| if [[ -f "$CONSTANT_LATENCY_RESULTS_FILE" ]]; then | |
| git add "$CONSTANT_LATENCY_RESULTS_FILE" | |
| fi | |
| git diff --cached --quiet || git commit -m "Add constant-latency benchmark results for run #${{ github.run_number }}" | |
| git push | |
| - name: Upload combined constant-latency results | |
| if: always() | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: all-results-constant-latency | |
| path: artifacts/ | |
| benchmark-summary: | |
| needs: | |
| - benchmark-constant | |
| - benchmark-burst | |
| - benchmark-constant-latency | |
| - generate-results-constant | |
| - generate-results-burst | |
| - generate-results-constant-latency | |
| if: ${{ !cancelled() && needs.prepare-matrix.outputs.should_publish == 'true' }} | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v6 | |
| with: | |
| ref: ${{ github.ref_name }} | |
| - name: Write final benchmark summary | |
| run: | | |
| RUN_RESULTS_DIR="benchmark-runs/${{ github.run_number }}" | |
| CONSTANT_RESULTS_FILE="$RUN_RESULTS_DIR/RESULTS_CONSTANT.md" | |
| BURST_RESULTS_FILE="$RUN_RESULTS_DIR/RESULTS_BURST.md" | |
| CONSTANT_LATENCY_RESULTS_FILE="$RUN_RESULTS_DIR/RESULTS_CONSTANT_LATENCY.md" | |
| echo "# Benchmark Results" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "- Run: **Benchmark #${{ github.run_number }}**" >> $GITHUB_STEP_SUMMARY | |
| echo "- Started (UTC): **${{ github.run_started_at || 'start-time-unavailable' }}**" >> $GITHUB_STEP_SUMMARY | |
| echo "- Gateway selection: \`${{ inputs.gateway || 'all' }}\`" >> $GITHUB_STEP_SUMMARY | |
| echo "- Benchmark selection: \`${{ inputs.benchmark || 'all' }}\`" >> $GITHUB_STEP_SUMMARY | |
| echo "- Diagnostic run: \`${{ inputs.diagnostic_run || 'false' }}\`" >> $GITHUB_STEP_SUMMARY | |
| echo "- Runs per gateway: \`${{ inputs.runs || '9' }}\`" >> $GITHUB_STEP_SUMMARY | |
| echo "- Duration per run: \`${{ inputs.duration || '120' }}s\`" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| if [[ -f "$CONSTANT_RESULTS_FILE" ]]; then | |
| cat "$CONSTANT_RESULTS_FILE" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| else | |
| echo "No constant results were generated." >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| fi | |
| if [[ -f "$BURST_RESULTS_FILE" ]]; then | |
| cat "$BURST_RESULTS_FILE" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| else | |
| echo "No burst results were generated." >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| fi | |
| if [[ -f "$CONSTANT_LATENCY_RESULTS_FILE" ]]; then | |
| cat "$CONSTANT_LATENCY_RESULTS_FILE" >> $GITHUB_STEP_SUMMARY | |
| else | |
| echo "No constant-latency results were generated." >> $GITHUB_STEP_SUMMARY | |
| fi | |
| - name: Publish latest root results | |
| if: ${{ needs.benchmark-constant.result == 'success' && needs.benchmark-burst.result == 'success' && needs.benchmark-constant-latency.result == 'success' && needs.generate-results-constant.result == 'success' && needs.generate-results-burst.result == 'success' && needs.generate-results-constant-latency.result == 'success' }} | |
| run: | | |
| RUN_RESULTS_DIR="benchmark-runs/${{ github.run_number }}" | |
| CONSTANT_RESULTS_FILE="$RUN_RESULTS_DIR/RESULTS_CONSTANT.md" | |
| BURST_RESULTS_FILE="$RUN_RESULTS_DIR/RESULTS_BURST.md" | |
| CONSTANT_LATENCY_RESULTS_FILE="$RUN_RESULTS_DIR/RESULTS_CONSTANT_LATENCY.md" | |
| for file in "$CONSTANT_RESULTS_FILE" "$BURST_RESULTS_FILE" "$CONSTANT_LATENCY_RESULTS_FILE"; do | |
| if [[ ! -f "$file" ]]; then | |
| echo "Error: expected run result file is missing: $file" | |
| exit 1 | |
| fi | |
| done | |
| cp "$CONSTANT_RESULTS_FILE" RESULTS_CONSTANT.md | |
| cp "$BURST_RESULTS_FILE" RESULTS_BURST.md | |
| cp "$CONSTANT_LATENCY_RESULTS_FILE" RESULTS_CONSTANT_LATENCY.md | |
| git config user.name "github-actions[bot]" | |
| git config user.email "github-actions[bot]@users.noreply.github.com" | |
| git add RESULTS_CONSTANT.md RESULTS_BURST.md RESULTS_CONSTANT_LATENCY.md | |
| git diff --cached --quiet || git commit -m "Update latest benchmark results from run #${{ github.run_number }}" | |
| git push | |
| - name: Skip latest root publish (errors detected) | |
| if: ${{ needs.benchmark-constant.result != 'success' || needs.benchmark-burst.result != 'success' || needs.benchmark-constant-latency.result != 'success' || needs.generate-results-constant.result != 'success' || needs.generate-results-burst.result != 'success' || needs.generate-results-constant-latency.result != 'success' }} | |
| run: | | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "- Latest root files were not updated because one or more benchmark jobs failed." >> $GITHUB_STEP_SUMMARY |