Skip to content

feat: Implement async props with incremental rendering for React Server Components #443

feat: Implement async props with incremental rendering for React Server Components

feat: Implement async props with incremental rendering for React Server Components #443

name: Integration Tests
on:
push:
branches:
- 'master'
# Always trigger on master; docs-only detection handles skipping heavy jobs
pull_request:
paths-ignore:
- '**.md'
- 'docs/**'
- 'react_on_rails_pro/**'
workflow_dispatch:
inputs:
force_run:
description: 'Force run all jobs (bypass detect-changes)'
required: false
type: boolean
default: false
jobs:
detect-changes:
permissions:
contents: read
actions: read
runs-on: ubuntu-22.04
outputs:
docs_only: ${{ steps.detect.outputs.docs_only }}
run_lint: ${{ steps.detect.outputs.run_lint }}
run_js_tests: ${{ steps.detect.outputs.run_js_tests }}
run_ruby_tests: ${{ steps.detect.outputs.run_ruby_tests }}
run_dummy_tests: ${{ steps.detect.outputs.run_dummy_tests }}
run_generators: ${{ steps.detect.outputs.run_generators }}
has_full_ci_label: ${{ steps.check-label.outputs.result }}
steps:
- uses: actions/checkout@v4
with:
# Fetch enough history for change detection (50 commits is usually sufficient for PRs)
fetch-depth: 50
persist-credentials: false
- name: Check for full-ci label
id: check-label
uses: ./.github/actions/check-full-ci-label
- name: Detect relevant changes
id: detect
run: |
# If force_run is true OR full-ci label is present, run everything
if [ "${{ inputs.force_run }}" = "true" ] || [ "${{ steps.check-label.outputs.result }}" = "true" ]; then
echo "run_lint=true" >> "$GITHUB_OUTPUT"
echo "run_js_tests=true" >> "$GITHUB_OUTPUT"
echo "run_ruby_tests=true" >> "$GITHUB_OUTPUT"
echo "run_dummy_tests=true" >> "$GITHUB_OUTPUT"
echo "run_generators=true" >> "$GITHUB_OUTPUT"
echo "docs_only=false" >> "$GITHUB_OUTPUT"
else
BASE_REF="${{ github.event.pull_request.base.sha || github.event.before || 'origin/master' }}"
script/ci-changes-detector "$BASE_REF"
fi
shell: bash
- name: Guard docs-only master pushes
if: github.event_name == 'push' && github.ref == 'refs/heads/master'
uses: ./.github/actions/ensure-master-docs-safety
with:
docs-only: ${{ steps.detect.outputs.docs_only }}
previous-sha: ${{ github.event.before }}
setup-integration-matrix:
needs: detect-changes
runs-on: ubuntu-22.04
outputs:
matrix: ${{ steps.set-matrix.outputs.matrix }}
steps:
- id: set-matrix
run: |
# Determine if we should run full matrix (master, workflow_dispatch, force_run, or full-ci label)
if [[ "${{ github.ref }}" == "refs/heads/master" ]] || \
[[ "${{ github.event_name }}" == "workflow_dispatch" ]] || \
[[ "${{ inputs.force_run }}" == "true" ]] || \
[[ "${{ needs.detect-changes.outputs.has_full_ci_label }}" == "true" ]]; then
# Full matrix: test both latest and minimum supported versions
echo 'matrix={"include":[{"ruby-version":"3.4","node-version":"22","dependency-level":"latest"},{"ruby-version":"3.2","node-version":"20","dependency-level":"minimum"}]}' >> $GITHUB_OUTPUT
else
# PR matrix: test only latest versions for fast feedback
echo 'matrix={"include":[{"ruby-version":"3.4","node-version":"22","dependency-level":"latest"}]}' >> $GITHUB_OUTPUT
fi
build-dummy-app-webpack-test-bundles:
needs: [detect-changes, setup-integration-matrix]
# Skip only if: master push AND docs-only changes
# Otherwise run if: on master OR workflow_dispatch OR dummy tests needed
# This allows docs-only commits to skip heavy jobs while ensuring full CI on master for code changes
if: |
!(
github.event_name == 'push' &&
github.ref == 'refs/heads/master' &&
needs.detect-changes.outputs.docs_only == 'true'
) && (
github.ref == 'refs/heads/master' ||
github.event_name == 'workflow_dispatch' ||
needs.detect-changes.outputs.run_dummy_tests == 'true'
)
strategy:
matrix: ${{ fromJson(needs.setup-integration-matrix.outputs.matrix) }}
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
with:
persist-credentials: false
- name: Setup Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: ${{ matrix.ruby-version }}
bundler: 2.5.9
# libyaml-dev is needed for psych v5
# this gem depends on sdoc which depends on rdoc which depends on psych
- name: Fix dependency for libyaml-dev
run: sudo apt install libyaml-dev
- name: Setup Node
uses: ./.github/actions/setup-node-with-retry
with:
node-version: ${{ matrix.node-version }}
# Retry logic now handles V8 crashes automatically
# https://github.com/nodejs/node/issues/56010
cache: yarn
cache-dependency-path: '**/yarn.lock'
- name: Print system information
run: |
echo "Linux release: "; cat /etc/issue
echo "Current user: "; whoami
echo "Current directory: "; pwd
echo "Ruby version: "; ruby -v
echo "Node version: "; node -v
echo "Yarn version: "; yarn --version
echo "Bundler version: "; bundle --version
- name: run conversion script to support shakapacker v6
if: matrix.dependency-level == 'minimum'
run: script/convert
- name: Install Node modules with Yarn for renderer package
run: |
yarn install --no-progress --no-emoji ${{ matrix.dependency-level == 'latest' && '--frozen-lockfile' || '' }}
sudo yarn global add yalc
- name: yalc publish for react-on-rails
run: cd packages/react-on-rails && yalc publish
- name: yalc add react-on-rails
run: cd spec/dummy && yalc add react-on-rails
- name: Install Node modules with Yarn for dummy app
run: cd spec/dummy && yarn install --no-progress --no-emoji ${{ matrix.dependency-level == 'latest' && '--frozen-lockfile' || '' }}
- name: Save dummy app ruby gems to cache
uses: actions/cache@v4
with:
path: spec/dummy/vendor/bundle
key: dummy-app-gem-cache-${{ hashFiles('spec/dummy/Gemfile.lock') }}-ruby${{ matrix.ruby-version }}-${{ matrix.dependency-level }}
- name: Install Ruby Gems for dummy app
run: |
cd spec/dummy
bundle lock --add-platform 'x86_64-linux'
if ! bundle check --path=vendor/bundle; then
bundle _2.5.9_ install --path=vendor/bundle --jobs=4 --retry=3
fi
- name: generate file system-based packs
run: cd spec/dummy && RAILS_ENV="test" bundle exec rake react_on_rails:generate_packs
- name: Build test bundles for dummy app
run: cd spec/dummy && rm -rf public/webpack/test && yarn run build:rescript && RAILS_ENV="test" NODE_ENV="test" bin/shakapacker
- id: get-sha
run: echo "sha=\"$(git rev-parse HEAD)\"" >> "$GITHUB_OUTPUT"
- name: Save test Webpack bundles to cache (for build number checksum used by RSpec job)
uses: actions/cache/save@v4
with:
path: spec/dummy/public/webpack
key: dummy-app-webpack-bundle-${{ steps.get-sha.outputs.sha }}-ruby${{ matrix.ruby-version }}-${{ matrix.dependency-level }}
dummy-app-integration-tests:
needs: [detect-changes, setup-integration-matrix, build-dummy-app-webpack-test-bundles]
# Run on master, workflow_dispatch, OR when tests needed on PR
if: |
!(
github.event_name == 'push' &&
github.ref == 'refs/heads/master' &&
needs.detect-changes.outputs.docs_only == 'true'
) && (
github.ref == 'refs/heads/master' ||
github.event_name == 'workflow_dispatch' ||
needs.detect-changes.outputs.run_dummy_tests == 'true'
)
strategy:
matrix: ${{ fromJson(needs.setup-integration-matrix.outputs.matrix) }}
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
with:
persist-credentials: false
- name: Setup Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: ${{ matrix.ruby-version }}
bundler: 2.5.9
- name: Setup Node
uses: ./.github/actions/setup-node-with-retry
with:
node-version: ${{ matrix.node-version }}
# Retry logic now handles V8 crashes automatically
# https://github.com/nodejs/node/issues/56010
cache: yarn
cache-dependency-path: '**/yarn.lock'
- name: Print system information
run: |
echo "Linux release: "; cat /etc/issue
echo "Current user: "; whoami
echo "Current directory: "; pwd
echo "Ruby version: "; ruby -v
echo "Node version: "; node -v
echo "Yarn version: "; yarn --version
echo "Bundler version: "; bundle --version
- name: run conversion script to support shakapacker v6
if: matrix.dependency-level == 'minimum'
run: script/convert
- name: Save root ruby gems to cache
uses: actions/cache@v4
with:
path: vendor/bundle
key: package-app-gem-cache-${{ hashFiles('Gemfile.lock') }}-ruby${{ matrix.ruby-version }}-${{ matrix.dependency-level }}
- name: Save dummy app ruby gems to cache
uses: actions/cache@v4
with:
path: spec/dummy/vendor/bundle
key: dummy-app-gem-cache-${{ hashFiles('spec/dummy/Gemfile.lock') }}-ruby${{ matrix.ruby-version }}-${{ matrix.dependency-level }}
- id: get-sha
run: echo "sha=\"$(git rev-parse HEAD)\"" >> "$GITHUB_OUTPUT"
- name: Save test Webpack bundles to cache (for build number checksum used by RSpec job)
uses: actions/cache@v4
with:
path: spec/dummy/public/webpack
key: dummy-app-webpack-bundle-${{ steps.get-sha.outputs.sha }}-ruby${{ matrix.ruby-version }}-${{ matrix.dependency-level }}
- name: Install Node modules with Yarn
run: |
yarn install --no-progress --no-emoji ${{ matrix.dependency-level == 'latest' && '--frozen-lockfile' || '' }}
sudo yarn global add yalc
- name: yalc publish for react-on-rails
run: cd packages/react-on-rails && yalc publish
- name: yalc add react-on-rails
run: cd spec/dummy && yalc add react-on-rails
- name: Install Node modules with Yarn for dummy app
run: cd spec/dummy && yarn install --no-progress --no-emoji ${{ matrix.dependency-level == 'latest' && '--frozen-lockfile' || '' }}
- name: Dummy JS tests
run: |
cd spec/dummy
yarn run test:js
- name: Install Ruby Gems for package
run: |
bundle lock --add-platform 'x86_64-linux'
if ! bundle check --path=vendor/bundle; then
bundle _2.5.9_ install --path=vendor/bundle --jobs=4 --retry=3
fi
- name: Install Ruby Gems for dummy app
run: |
cd spec/dummy
bundle lock --add-platform 'x86_64-linux'
if ! bundle check --path=vendor/bundle; then
bundle _2.5.9_ install --path=vendor/bundle --jobs=4 --retry=3
fi
- name: Ensure minimum required Chrome version
run: |
echo -e "Already installed $(google-chrome --version)\n"
MINIMUM_REQUIRED_CHROME_VERSION=75
INSTALLED_CHROME_MAJOR_VERSION="$(google-chrome --version | tr ' .' '\t' | cut -f3)"
if [[ $INSTALLED_CHROME_MAJOR_VERSION -lt $MINIMUM_REQUIRED_CHROME_VERSION ]]; then
wget -q -O - https://dl.google.com/linux/linux_signing_key.pub | sudo apt-key add -
sudo sh -c 'echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google.list'
sudo apt-get update
sudo apt-get install google-chrome-stable
echo -e "\nInstalled $(google-chrome --version)"
fi
- name: Increase the amount of inotify watchers
run: echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf && sudo sysctl -p
- name: generate file system-based packs
run: cd spec/dummy && RAILS_ENV="test" bundle exec rake react_on_rails:generate_packs
- name: Git Stuff
if: matrix.dependency-level == 'minimum'
run: |
git config user.email "[email protected]"
git config user.name "Your Name"
git commit -am "stop generators from complaining about uncommitted code"
- run: cd spec/dummy && bundle info shakapacker
- name: Set packer version environment variable
run: |
echo "CI_DEPENDENCY_LEVEL=ruby${{ matrix.ruby-version }}-${{ matrix.dependency-level }}" >> $GITHUB_ENV
- name: Main CI
run: bundle exec rake run_rspec:all_dummy
- name: Store test results
uses: actions/upload-artifact@v4
with:
name: main-rspec-${{ github.run_id }}-${{ github.job }}-ruby${{ matrix.ruby-version }}-${{ matrix.dependency-level }}
path: ~/rspec
- name: Store artifacts
uses: actions/upload-artifact@v4
with:
name: dummy-app-capybara-${{ github.run_id }}-${{ github.job }}-ruby${{ matrix.ruby-version }}-${{ matrix.dependency-level }}
path: spec/dummy/tmp/capybara
- name: Store artifacts
uses: actions/upload-artifact@v4
with:
name: dummy-app-test-log-${{ github.run_id }}-${{ github.job }}-ruby${{ matrix.ruby-version }}-${{ matrix.dependency-level }}
path: spec/dummy/log/test.log
- name: Store artifacts
uses: actions/upload-artifact@v4
with:
name: dummy-app-yarn-log-${{ github.run_id }}-${{ github.job }}-ruby${{ matrix.ruby-version }}-${{ matrix.dependency-level }}
path: spec/dummy/yarn-error.log