feat: Implement async props with incremental rendering for React Server Components #443
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: 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 |