Skip to content

Commit 23b347f

Browse files
committed
Add pro benchmarks
1 parent d27ad02 commit 23b347f

File tree

3 files changed

+214
-36
lines changed

3 files changed

+214
-36
lines changed

.github/workflows/benchmark.yml

Lines changed: 177 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -29,33 +29,34 @@ on:
2929
default: '60s'
3030
type: string
3131
connections:
32-
description: 'Concurrent connections/virtual users'
32+
description: 'Concurrent connections/virtual users (also used as max)'
3333
required: false
3434
default: 10
3535
type: number
36-
max_connections:
37-
description: 'Maximum connections/virtual users'
38-
required: false
39-
type: number
4036
web_concurrency:
4137
description: 'Number of Puma worker processes'
4238
required: false
4339
default: 4
4440
type: number
45-
rails_max_threads:
46-
description: 'Maximum number of Puma threads'
41+
rails_threads:
42+
description: 'Number of Puma threads (min and max will be same)'
4743
required: false
4844
default: 3
4945
type: number
50-
rails_min_threads:
51-
description: 'Minimum number of Puma threads (same as maximum if not set)'
52-
required: false
53-
type: number
5446
tools:
5547
description: 'Comma-separated list of tools to run'
5648
required: false
5749
default: 'fortio,vegeta,k6'
5850
type: string
51+
app_version:
52+
description: 'Which app version to benchmark'
53+
required: false
54+
default: 'both'
55+
type: choice
56+
options:
57+
- 'both'
58+
- 'core_only'
59+
- 'pro_only'
5960
push:
6061
branches:
6162
- master
@@ -71,15 +72,17 @@ env:
7172
DURATION: ${{ github.event.inputs.duration || '30s' }}
7273
REQUEST_TIMEOUT: ${{ github.event.inputs.request_timeout || '60s' }}
7374
CONNECTIONS: ${{ github.event.inputs.connections || 10 }}
74-
MAX_CONNECTIONS: ${{ github.event.inputs.max_connections || github.event.inputs.connections || 10 }}
75+
MAX_CONNECTIONS: ${{ github.event.inputs.connections || 10 }}
7576
WEB_CONCURRENCY: ${{ github.event.inputs.web_concurrency || 4 }}
76-
RAILS_MAX_THREADS: ${{ github.event.inputs.rails_max_threads || 3 }}
77-
RAILS_MIN_THREADS: ${{ github.event.inputs.rails_min_threads || github.event.inputs.rails_max_threads || 3 }}
77+
RAILS_MAX_THREADS: ${{ github.event.inputs.rails_threads || 3 }}
78+
RAILS_MIN_THREADS: ${{ github.event.inputs.rails_threads || 3 }}
7879
TOOLS: ${{ github.event.inputs.tools || 'fortio,vegeta,k6' }}
7980

8081
jobs:
8182
benchmark:
8283
runs-on: ubuntu-latest
84+
env:
85+
REACT_ON_RAILS_PRO_LICENSE: ${{ secrets.REACT_ON_RAILS_PRO_LICENSE }}
8386

8487
steps:
8588
# ============================================
@@ -176,8 +179,8 @@ jobs:
176179
- name: Setup Ruby
177180
uses: ruby/setup-ruby@v1
178181
with:
179-
ruby-version: '3.4'
180-
bundler: 2.5.9
182+
ruby-version: '3.3.7'
183+
bundler: 2.5.4
181184

182185
- name: Fix dependency for libyaml-dev
183186
run: sudo apt install libyaml-dev -y
@@ -224,7 +227,7 @@ jobs:
224227
cd spec/dummy
225228
bundle lock --add-platform 'x86_64-linux'
226229
if ! bundle check --path=vendor/bundle; then
227-
bundle _2.5.9_ install --path=vendor/bundle --jobs=4 --retry=3
230+
bundle _2.5.4_ install --path=vendor/bundle --jobs=4 --retry=3
228231
fi
229232
230233
- name: generate file system-based packs
@@ -268,14 +271,15 @@ jobs:
268271
exit 1
269272
270273
# ============================================
271-
# STEP 5: RUN BENCHMARKS
274+
# STEP 5: RUN CORE BENCHMARKS
272275
# ============================================
273276

274-
- name: Execute benchmark suite
275-
timeout-minutes: 20
277+
- name: Execute Core benchmark suite
278+
if: github.event.inputs.app_version != 'pro_only'
279+
timeout-minutes: 120
276280
run: |
277281
set -e # Exit on any error
278-
echo "🏃 Running benchmark suite..."
282+
echo "🏃 Running Core benchmark suite..."
279283
280284
if ! ruby spec/performance/bench.rb; then
281285
echo "❌ ERROR: Benchmark execution failed"
@@ -284,7 +288,8 @@ jobs:
284288
285289
echo "✅ Benchmark suite completed successfully"
286290
287-
- name: Validate benchmark results
291+
- name: Validate Core benchmark results
292+
if: github.event.inputs.app_version != 'pro_only'
288293
run: |
289294
set -e # Exit on any error
290295
echo "🔍 Validating benchmark output files..."
@@ -322,39 +327,175 @@ jobs:
322327
echo "Continuing with available results..."
323328
fi
324329
325-
# ============================================
326-
# STEP 6: COLLECT BENCHMARK RESULTS
327-
# ============================================
328-
329-
- name: Upload benchmark results
330+
- name: Upload Core benchmark results
330331
uses: actions/upload-artifact@v4
331-
if: always() # Upload even if benchmark fails
332+
if: github.event.inputs.app_version != 'pro_only' && always()
332333
with:
333-
name: benchmark-results-${{ github.run_number }}
334+
name: benchmark-core-results-${{ github.run_number }}
334335
path: bench_results/
335336
retention-days: 30
336337
if-no-files-found: warn
337338

338-
- name: Verify artifact upload
339-
if: success()
339+
# ============================================
340+
# STEP 6: SETUP PRO APPLICATION SERVER
341+
# ============================================
342+
- name: Cache Pro package node modules
343+
if: github.event.inputs.app_version != 'core_only'
344+
uses: actions/cache@v4
345+
with:
346+
path: react_on_rails_pro/node_modules
347+
key: v4-pro-package-node-modules-cache-${{ hashFiles('react_on_rails_pro/yarn.lock') }}
348+
349+
- name: Cache Pro dummy app node modules
350+
if: github.event.inputs.app_version != 'core_only'
351+
uses: actions/cache@v4
352+
with:
353+
path: react_on_rails_pro/spec/dummy/node_modules
354+
key: v4-pro-dummy-app-node-modules-cache-${{ hashFiles('react_on_rails_pro/spec/dummy/yarn.lock') }}
355+
356+
- name: Cache Pro dummy app Ruby gems
357+
if: github.event.inputs.app_version != 'core_only'
358+
uses: actions/cache@v4
359+
with:
360+
path: react_on_rails_pro/spec/dummy/vendor/bundle
361+
key: v4-pro-dummy-app-gem-cache-${{ hashFiles('react_on_rails_pro/spec/dummy/Gemfile.lock') }}
362+
363+
- name: Install Node modules with Yarn for Pro package
364+
if: github.event.inputs.app_version != 'core_only'
365+
run: |
366+
cd react_on_rails_pro
367+
sudo yarn global add yalc
368+
yarn install --frozen-lockfile --no-progress --no-emoji
369+
370+
- name: Install Node modules with Yarn for Pro dummy app
371+
if: github.event.inputs.app_version != 'core_only'
372+
run: cd react_on_rails_pro/spec/dummy && yarn install --frozen-lockfile --no-progress --no-emoji
373+
374+
- name: Install Ruby Gems for Pro dummy app
375+
if: github.event.inputs.app_version != 'core_only'
376+
run: |
377+
cd react_on_rails_pro/spec/dummy
378+
bundle lock --add-platform 'x86_64-linux'
379+
bundle _2.5.4_ check || bundle _2.5.4_ install --jobs=4 --retry=3
380+
381+
- name: Generate file-system based entrypoints for Pro
382+
if: github.event.inputs.app_version != 'core_only'
383+
run: cd react_on_rails_pro/spec/dummy && bundle exec rake react_on_rails:generate_packs
384+
385+
- name: Prepare Pro production assets
386+
if: github.event.inputs.app_version != 'core_only'
340387
run: |
341-
echo "✅ Benchmark results uploaded as workflow artifacts"
342-
echo "📦 Artifact name: benchmark-results-${{ github.run_number }}"
343-
echo "🔗 Access artifacts from the Actions tab in GitHub"
388+
set -e
389+
echo "🔨 Building Pro production assets..."
390+
cd react_on_rails_pro/spec/dummy
391+
392+
if ! bin/prod-assets; then
393+
echo "❌ ERROR: Failed to build production assets"
394+
exit 1
395+
fi
396+
397+
echo "✅ Production assets built successfully"
398+
399+
- name: Start Pro production server
400+
if: github.event.inputs.app_version != 'core_only'
401+
run: |
402+
set -e
403+
echo "🚀 Starting Pro production server..."
404+
cd react_on_rails_pro/spec/dummy
405+
406+
# Start server in background
407+
bin/prod &
408+
echo "Server started in background"
409+
410+
# Wait for server to be ready (max 30 seconds)
411+
echo "⏳ Waiting for server to be ready..."
412+
for i in {1..30}; do
413+
if curl -fsS http://localhost:3001 > /dev/null; then
414+
echo "✅ Server is ready and responding"
415+
exit 0
416+
fi
417+
echo " Attempt $i/30: Server not ready yet..."
418+
sleep 1
419+
done
420+
421+
echo "❌ ERROR: Server failed to start within 30 seconds"
422+
exit 1
344423
345424
# ============================================
346-
# WORKFLOW COMPLETION
425+
# STEP 7: RUN PRO BENCHMARKS
347426
# ============================================
348427

428+
- name: Execute Pro benchmark suite
429+
if: github.event.inputs.app_version != 'core_only'
430+
timeout-minutes: 120
431+
run: |
432+
set -e
433+
echo "🏃 Running Pro benchmark suite..."
434+
435+
if ! PRO=true ruby spec/performance/bench.rb; then
436+
echo "❌ ERROR: Benchmark execution failed"
437+
exit 1
438+
fi
439+
440+
echo "✅ Benchmark suite completed successfully"
441+
442+
- name: Validate Pro benchmark results
443+
if: github.event.inputs.app_version != 'core_only'
444+
run: |
445+
set -e
446+
echo "🔍 Validating Pro benchmark output files..."
447+
448+
RESULTS_DIR="bench_results"
449+
REQUIRED_FILES=("summary.txt")
450+
MISSING_FILES=()
451+
452+
if [ ! -d "${RESULTS_DIR}" ]; then
453+
echo "❌ ERROR: Benchmark results directory '${RESULTS_DIR}' not found"
454+
exit 1
455+
fi
456+
457+
echo "Generated files:"
458+
ls -lh ${RESULTS_DIR}/ || true
459+
echo ""
460+
461+
for file in "${REQUIRED_FILES[@]}"; do
462+
if [ ! -f "${RESULTS_DIR}/${file}" ]; then
463+
MISSING_FILES+=("${file}")
464+
fi
465+
done
466+
467+
if [ ${#MISSING_FILES[@]} -eq 0 ]; then
468+
echo "✅ All required benchmark output files present"
469+
echo "📊 Summary preview:"
470+
head -20 ${RESULTS_DIR}/summary.txt || true
471+
else
472+
echo "⚠️ WARNING: Some required files are missing:"
473+
printf ' - %s\n' "${MISSING_FILES[@]}"
474+
echo "Continuing with available results..."
475+
fi
476+
477+
- name: Upload Pro benchmark results
478+
uses: actions/upload-artifact@v4
479+
if: github.event.inputs.app_version != 'core_only' && always()
480+
with:
481+
name: benchmark-pro-results-${{ github.run_number }}
482+
path: bench_results/
483+
retention-days: 30
484+
if-no-files-found: warn
485+
486+
# ============================================
487+
# STEP 8: WORKFLOW COMPLETION
488+
# ============================================
349489
- name: Workflow summary
350490
if: always()
351491
run: |
352492
echo "📋 Benchmark Workflow Summary"
353-
echo "=============================="
493+
echo "===================================="
354494
echo "Status: ${{ job.status }}"
355495
echo "Run number: ${{ github.run_number }}"
356496
echo "Triggered by: ${{ github.actor }}"
357497
echo "Branch: ${{ github.ref_name }}"
498+
echo "App version: ${{ github.event.inputs.app_version || 'both' }}"
358499
echo ""
359500
if [ "${{ job.status }}" == "success" ]; then
360501
echo "✅ All steps completed successfully"
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
#!/usr/bin/env bash
2+
3+
# Run only after ./prod-assets
4+
5+
# Check if assets are precompiled
6+
MANIFEST="public/webpack/production/manifest.json"
7+
8+
if [ ! -d "public/assets" ]; then
9+
echo "ERROR: public/assets not found. Run ./bin/prod-assets first"
10+
exit 1
11+
fi
12+
13+
if [ ! -f "$MANIFEST" ]; then
14+
echo "ERROR: $MANIFEST not found. Run ./bin/prod-assets first"
15+
exit 1
16+
fi
17+
18+
# Simple up-to-date check: warn if source files are newer than manifest.json
19+
if find client config -type f \( -name "*.[jt]s" -o -name "*.[jt]sx" \) -newer "$MANIFEST" 2>/dev/null | grep -q .; then
20+
echo "WARNING: client or config has changes newer than compiled assets"
21+
echo "Consider running ./bin/prod-assets to rebuild"
22+
fi
23+
24+
if [ -f "yarn.lock" ] && [ "yarn.lock" -nt "$MANIFEST" ]; then
25+
echo "WARNING: yarn.lock is newer than compiled assets"
26+
echo "Consider running ./bin/prod-assets to rebuild"
27+
fi
28+
29+
NODE_ENV=production RAILS_ENV=production bundle exec rails server -p 3001
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#!/usr/bin/env bash
2+
3+
export NODE_ENV=production
4+
export RAILS_ENV=production
5+
if [ "$CI" = "true" ]; then
6+
bundle exec bootsnap precompile --gemfile app/ lib/ config/
7+
fi
8+
bundle exec rails assets:precompile

0 commit comments

Comments
 (0)