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
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
8081jobs :
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
@@ -208,29 +211,34 @@ jobs:
208211 run : cd packages/react-on-rails && yarn install --no-progress --no-emoji --frozen-lockfile && yalc publish
209212
210213 - name : yalc add react-on-rails
214+ if : github.event.inputs.app_version != 'pro_only'
211215 run : cd spec/dummy && yalc add react-on-rails
212216
213217 - name : Install Node modules with Yarn for dummy app
218+ if : github.event.inputs.app_version != 'pro_only'
214219 run : cd spec/dummy && yarn install --no-progress --no-emoji
215220
216221 - name : Save dummy app ruby gems to cache
222+ if : github.event.inputs.app_version != 'pro_only'
217223 uses : actions/cache@v4
218224 with :
219225 path : spec/dummy/vendor/bundle
220226 key : dummy-app-gem-cache-${{ hashFiles('spec/dummy/Gemfile.lock') }}
221227
222228 - name : Install Ruby Gems for dummy app
229+ if : github.event.inputs.app_version != 'pro_only'
223230 run : |
224231 cd spec/dummy
225232 bundle lock --add-platform 'x86_64-linux'
226233 if ! bundle check --path=vendor/bundle; then
227- bundle _2.5.9_ install --path=vendor/bundle --jobs=4 --retry=3
234+ bundle _2.5.4_ install --path=vendor/bundle --jobs=4 --retry=3
228235 fi
229236
230237 - name : generate file system-based packs
231238 run : cd spec/dummy && RAILS_ENV="production" bundle exec rake react_on_rails:generate_packs
232239
233240 - name : Prepare production assets
241+ if : github.event.inputs.app_version != 'pro_only'
234242 run : |
235243 set -e # Exit on any error
236244 echo "🔨 Building production assets..."
@@ -244,6 +252,7 @@ jobs:
244252 echo "✅ Production assets built successfully"
245253
246254 - name : Start production server
255+ if : github.event.inputs.app_version != 'pro_only'
247256 run : |
248257 set -e # Exit on any error
249258 echo "🚀 Starting production server..."
@@ -268,14 +277,15 @@ jobs:
268277 exit 1
269278
270279 # ============================================
271- # STEP 5: RUN BENCHMARKS
280+ # STEP 5: RUN CORE BENCHMARKS
272281 # ============================================
273282
274- - name : Execute benchmark suite
275- timeout-minutes : 20
283+ - name : Execute Core benchmark suite
284+ if : github.event.inputs.app_version != 'pro_only'
285+ timeout-minutes : 120
276286 run : |
277287 set -e # Exit on any error
278- echo "🏃 Running benchmark suite..."
288+ echo "🏃 Running Core benchmark suite..."
279289
280290 if ! ruby spec/performance/bench.rb; then
281291 echo "❌ ERROR: Benchmark execution failed"
@@ -284,7 +294,8 @@ jobs:
284294
285295 echo "✅ Benchmark suite completed successfully"
286296
287- - name : Validate benchmark results
297+ - name : Validate Core benchmark results
298+ if : github.event.inputs.app_version != 'pro_only'
288299 run : |
289300 set -e # Exit on any error
290301 echo "🔍 Validating benchmark output files..."
@@ -322,39 +333,175 @@ jobs:
322333 echo "Continuing with available results..."
323334 fi
324335
325- # ============================================
326- # STEP 6: COLLECT BENCHMARK RESULTS
327- # ============================================
328-
329- - name : Upload benchmark results
336+ - name : Upload Core benchmark results
330337 uses : actions/upload-artifact@v4
331- if : always() # Upload even if benchmark fails
338+ if : github.event.inputs.app_version != 'pro_only' && always()
332339 with :
333- name : benchmark-results-${{ github.run_number }}
340+ name : benchmark-core- results-${{ github.run_number }}
334341 path : bench_results/
335342 retention-days : 30
336343 if-no-files-found : warn
337344
338- - name : Verify artifact upload
339- if : success()
345+ # ============================================
346+ # STEP 6: SETUP PRO APPLICATION SERVER
347+ # ============================================
348+ - name : Cache Pro package node modules
349+ if : github.event.inputs.app_version != 'core_only'
350+ uses : actions/cache@v4
351+ with :
352+ path : react_on_rails_pro/node_modules
353+ key : v4-pro-package-node-modules-cache-${{ hashFiles('react_on_rails_pro/yarn.lock') }}
354+
355+ - name : Cache Pro dummy app node modules
356+ if : github.event.inputs.app_version != 'core_only'
357+ uses : actions/cache@v4
358+ with :
359+ path : react_on_rails_pro/spec/dummy/node_modules
360+ key : v4-pro-dummy-app-node-modules-cache-${{ hashFiles('react_on_rails_pro/spec/dummy/yarn.lock') }}
361+
362+ - name : Cache Pro dummy app Ruby gems
363+ if : github.event.inputs.app_version != 'core_only'
364+ uses : actions/cache@v4
365+ with :
366+ path : react_on_rails_pro/spec/dummy/vendor/bundle
367+ key : v4-pro-dummy-app-gem-cache-${{ hashFiles('react_on_rails_pro/spec/dummy/Gemfile.lock') }}
368+
369+ - name : Install Node modules with Yarn for Pro package
370+ if : github.event.inputs.app_version != 'core_only'
371+ run : |
372+ cd react_on_rails_pro
373+ sudo yarn global add yalc
374+ yarn install --frozen-lockfile --no-progress --no-emoji
375+
376+ - name : Install Node modules with Yarn for Pro dummy app
377+ if : github.event.inputs.app_version != 'core_only'
378+ run : cd react_on_rails_pro/spec/dummy && yarn install --frozen-lockfile --no-progress --no-emoji
379+
380+ - name : Install Ruby Gems for Pro dummy app
381+ if : github.event.inputs.app_version != 'core_only'
382+ run : |
383+ cd react_on_rails_pro/spec/dummy
384+ bundle lock --add-platform 'x86_64-linux'
385+ bundle _2.5.4_ check || bundle _2.5.4_ install --jobs=4 --retry=3
386+
387+ - name : Generate file-system based entrypoints for Pro
388+ if : github.event.inputs.app_version != 'core_only'
389+ run : cd react_on_rails_pro/spec/dummy && bundle exec rake react_on_rails:generate_packs
390+
391+ - name : Prepare Pro production assets
392+ if : github.event.inputs.app_version != 'core_only'
340393 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"
394+ set -e
395+ echo "🔨 Building Pro production assets..."
396+ cd react_on_rails_pro/spec/dummy
397+
398+ if ! bin/prod-assets; then
399+ echo "❌ ERROR: Failed to build production assets"
400+ exit 1
401+ fi
402+
403+ echo "✅ Production assets built successfully"
404+
405+ - name : Start Pro production server
406+ if : github.event.inputs.app_version != 'core_only'
407+ run : |
408+ set -e
409+ echo "🚀 Starting Pro production server..."
410+ cd react_on_rails_pro/spec/dummy
411+
412+ # Start server in background
413+ bin/prod &
414+ echo "Server started in background"
415+
416+ # Wait for server to be ready (max 30 seconds)
417+ echo "⏳ Waiting for server to be ready..."
418+ for i in {1..30}; do
419+ if curl -fsS http://localhost:3001 > /dev/null; then
420+ echo "✅ Server is ready and responding"
421+ exit 0
422+ fi
423+ echo " Attempt $i/30: Server not ready yet..."
424+ sleep 1
425+ done
426+
427+ echo "❌ ERROR: Server failed to start within 30 seconds"
428+ exit 1
344429
345430 # ============================================
346- # WORKFLOW COMPLETION
431+ # STEP 7: RUN PRO BENCHMARKS
347432 # ============================================
348433
434+ - name : Execute Pro benchmark suite
435+ if : github.event.inputs.app_version != 'core_only'
436+ timeout-minutes : 120
437+ run : |
438+ set -e
439+ echo "🏃 Running Pro benchmark suite..."
440+
441+ if ! PRO=true ruby spec/performance/bench.rb; then
442+ echo "❌ ERROR: Benchmark execution failed"
443+ exit 1
444+ fi
445+
446+ echo "✅ Benchmark suite completed successfully"
447+
448+ - name : Validate Pro benchmark results
449+ if : github.event.inputs.app_version != 'core_only'
450+ run : |
451+ set -e
452+ echo "🔍 Validating Pro benchmark output files..."
453+
454+ RESULTS_DIR="bench_results"
455+ REQUIRED_FILES=("summary.txt")
456+ MISSING_FILES=()
457+
458+ if [ ! -d "${RESULTS_DIR}" ]; then
459+ echo "❌ ERROR: Benchmark results directory '${RESULTS_DIR}' not found"
460+ exit 1
461+ fi
462+
463+ echo "Generated files:"
464+ ls -lh ${RESULTS_DIR}/ || true
465+ echo ""
466+
467+ for file in "${REQUIRED_FILES[@]}"; do
468+ if [ ! -f "${RESULTS_DIR}/${file}" ]; then
469+ MISSING_FILES+=("${file}")
470+ fi
471+ done
472+
473+ if [ ${#MISSING_FILES[@]} -eq 0 ]; then
474+ echo "✅ All required benchmark output files present"
475+ echo "📊 Summary preview:"
476+ head -20 ${RESULTS_DIR}/summary.txt || true
477+ else
478+ echo "⚠️ WARNING: Some required files are missing:"
479+ printf ' - %s\n' "${MISSING_FILES[@]}"
480+ echo "Continuing with available results..."
481+ fi
482+
483+ - name : Upload Pro benchmark results
484+ uses : actions/upload-artifact@v4
485+ if : github.event.inputs.app_version != 'core_only' && always()
486+ with :
487+ name : benchmark-pro-results-${{ github.run_number }}
488+ path : bench_results/
489+ retention-days : 30
490+ if-no-files-found : warn
491+
492+ # ============================================
493+ # STEP 8: WORKFLOW COMPLETION
494+ # ============================================
349495 - name : Workflow summary
350496 if : always()
351497 run : |
352498 echo "📋 Benchmark Workflow Summary"
353- echo "=============================="
499+ echo "==================================== "
354500 echo "Status: ${{ job.status }}"
355501 echo "Run number: ${{ github.run_number }}"
356502 echo "Triggered by: ${{ github.actor }}"
357503 echo "Branch: ${{ github.ref_name }}"
504+ echo "App version: ${{ github.event.inputs.app_version || 'both' }}"
358505 echo ""
359506 if [ "${{ job.status }}" == "success" ]; then
360507 echo "✅ All steps completed successfully"
0 commit comments