Skip to content

feat: compliance module, contract modularization, unified token adapt… #202

feat: compliance module, contract modularization, unified token adapt…

feat: compliance module, contract modularization, unified token adapt… #202

name: Gas Benchmark Suite
on:
push:
branches: ["main", "dev"]
paths:
- "stellar-lend/contracts/**"
- "stellar-lend/benchmarks/**"
- ".github/workflows/gas-benchmarks.yml"
pull_request:
branches: ["main", "dev"]
paths:
- "stellar-lend/contracts/**"
- "stellar-lend/benchmarks/**"
- ".github/workflows/gas-benchmarks.yml"
# Allow manual trigger for on-demand profiling
workflow_dispatch:
inputs:
compare_baseline:
description: "Compare against baseline (true/false)"
required: false
default: "true"
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
# ─────────────────────────────────────────────────────────────────────────────
# Gas Benchmark Job
# ─────────────────────────────────────────────────────────────────────────────
gas-benchmarks:
name: Gas Benchmarks — All Contracts
runs-on: ubuntu-latest
env:
CARGO_TERM_COLOR: always
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
with:
toolchain: stable
- name: Cache cargo registry & build
uses: actions/cache@v4
with:
path: |
~/.cargo/registry
~/.cargo/git
stellar-lend/target
key: ${{ runner.os }}-cargo-bench-${{ hashFiles('stellar-lend/Cargo.lock') }}
restore-keys: |
${{ runner.os }}-cargo-bench-
${{ runner.os }}-cargo-
- name: Build benchmark suite
run: |
cd stellar-lend
cargo build --bin run_benchmarks --release 2>&1 | tee benchmark-build.log
echo "Build exit code: $?"
- name: Run gas benchmarks
id: run_benchmarks
run: |
cd stellar-lend
cargo run --bin run_benchmarks -- \
--output benchmark-results.json \
2>&1 | tee benchmark-output.log
echo "Benchmark exit code: $?"
- name: Run benchmarks with baseline comparison
id: baseline_check
if: ${{ github.event.inputs.compare_baseline != 'false' }}
run: |
cd stellar-lend
# Use baseline from repo if it exists and has results
BASELINE="benchmarks/baseline.json"
RESULTS=$(python3 -c "import json; d=json.load(open('$BASELINE')); print(len(d.get('results', [])))" 2>/dev/null || echo "0")
if [ "$RESULTS" -gt "0" ]; then
echo "Comparing against baseline ($RESULTS recorded operations)..."
cargo run --bin run_benchmarks -- \
--compare "$BASELINE" \
--output benchmark-results.json \
2>&1 | tee benchmark-comparison.log
EXIT_CODE=$?
if [ $EXIT_CODE -ne 0 ]; then
echo "::error::Gas regression detected! See benchmark-comparison.log for details."
exit $EXIT_CODE
fi
echo "All operations within gas budgets."
else
echo "No baseline results found — skipping regression check."
echo "Run benchmarks locally and commit baseline.json to enable regression detection."
fi
- name: Generate benchmark summary
if: always()
run: |
cd stellar-lend
if [ -f benchmark-results.json ]; then
echo "## Gas Benchmark Results" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "| Contract | Operations | Max Instructions | Avg Instructions | Over Budget |" >> $GITHUB_STEP_SUMMARY
echo "|----------|-----------|-----------------|-----------------|-------------|" >> $GITHUB_STEP_SUMMARY
python3 - <<'EOF'
import json, os
with open("benchmark-results.json") as f:
report = json.load(f)
summary = report.get("summary_by_contract", {})
with open(os.environ["GITHUB_STEP_SUMMARY"], "a") as out:
for contract, s in sorted(summary.items()):
over = s.get("over_budget_count", 0)
status = "✗" if over > 0 else "✓"
out.write(
f"| {contract} | {s['total_operations']} | "
f"{s['max_instructions']:,} | {s['avg_instructions']:,} | "
f"{status} {over} |\n"
)
total = report["total_benchmarks"]
passed = report["passed"]
failed = report["failed"]
out.write(f"\n**Total:** {total} | **Passed:** {passed} | **Failed:** {failed}\n")
EOF
# Also append markdown report to summary if available
if [ -f benchmark-results.md ]; then
echo "" >> $GITHUB_STEP_SUMMARY
echo "---" >> $GITHUB_STEP_SUMMARY
cat benchmark-results.md >> $GITHUB_STEP_SUMMARY
fi
fi
- name: Upload benchmark results
if: always()
uses: actions/upload-artifact@v4
with:
name: gas-benchmark-results-${{ github.sha }}
path: |
stellar-lend/benchmark-results.json
stellar-lend/benchmark-results.md
stellar-lend/benchmarks/history.json
stellar-lend/benchmark-output.log
stellar-lend/benchmark-comparison.log
retention-days: 90
- name: Upload build log
if: failure()
uses: actions/upload-artifact@v4
with:
name: benchmark-build-log
path: stellar-lend/benchmark-build.log
# ── Budget Alert Gate ──────────────────────────────────────────────────
- name: Enforce gas budget gate
if: always()
run: |
cd stellar-lend
if [ ! -f benchmark-results.json ]; then
echo "::error::benchmark-results.json not found — benchmarks may have failed to run."
exit 1
fi
FAILED=$(python3 -c "
import json
with open('benchmark-results.json') as f:
r = json.load(f)
over = [x for x in r['results'] if not x['within_budget'] and x['budget'] > 0]
for o in over:
print(f\" {o['operation']}: {o['instructions']:,} instructions (budget: {o['budget']:,})\")
print(len(over))
" | tail -1)
if [ "$FAILED" -gt "0" ]; then
echo "::error::$FAILED operation(s) exceeded gas budget. See benchmark-results.json for details."
exit 1
fi
echo "All operations within gas budgets."