[Pro] Add RSC SSR synchrony regression tests: complete payload must render before setTimeout(0) #15178
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: Lint JS and Ruby | |
| permissions: | |
| contents: read | |
| on: | |
| push: | |
| branches: | |
| - 'main' | |
| - 'release/**' | |
| # Always trigger on main/release branches; docs-only detection handles skipping heavy jobs | |
| pull_request: | |
| types: [opened, synchronize, reopened, ready_for_review] | |
| merge_group: | |
| workflow_dispatch: | |
| inputs: | |
| force_full_hosted: | |
| description: 'Force full hosted CI (bypass optimized detect-changes)' | |
| required: false | |
| type: boolean | |
| default: false | |
| pull_request_base_ref: | |
| description: 'Pull request base branch for label/command dispatches' | |
| required: false | |
| type: string | |
| pull_request_base_sha: | |
| description: 'Pull request base SHA for label/command dispatches' | |
| required: false | |
| type: string | |
| jobs: | |
| detect-changes: | |
| # Branch deletion push events have no checkoutable release ref. | |
| if: github.event_name != 'push' || github.event.deleted != true | |
| permissions: | |
| contents: read | |
| actions: read | |
| issues: read | |
| runs-on: ubuntu-22.04 | |
| outputs: | |
| docs_only: ${{ steps.detect.outputs.docs_only }} | |
| non_runtime_only: ${{ steps.detect.outputs.non_runtime_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 }} | |
| should_run_hosted_ci: ${{ steps.hosted-ci.outputs.should_run_hosted_ci }} | |
| should_force_full_hosted_ci: ${{ steps.hosted-ci.outputs.should_force_full_hosted_ci }} | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| # Full history is only needed for workflow_dispatch base-SHA reruns. | |
| fetch-depth: ${{ github.event_name == 'workflow_dispatch' && '0' || '50' }} | |
| persist-credentials: false | |
| - name: Select hosted CI mode | |
| id: hosted-ci | |
| uses: ./.github/actions/hosted-ci-selectors | |
| with: | |
| force-full-hosted: ${{ inputs.force_full_hosted || false }} | |
| base-ref: ${{ inputs.pull_request_base_ref || '' }} | |
| - name: Detect relevant changes | |
| id: detect | |
| env: | |
| DISPATCH_BASE_REF: ${{ inputs.pull_request_base_ref || '' }} | |
| DISPATCH_BASE_SHA: ${{ inputs.pull_request_base_sha || '' }} | |
| run: | | |
| # Force-full hosted CI is the explicit escape hatch that bypasses | |
| # optimized change selection. Hosted readiness alone stays path-based. | |
| if [ "${{ steps.hosted-ci.outputs.should_force_full_hosted_ci }}" = "true" ]; then | |
| { | |
| echo "run_lint=true" | |
| echo "run_js_tests=true" | |
| echo "run_ruby_tests=true" | |
| echo "run_dummy_tests=true" | |
| echo "run_generators=true" | |
| echo "docs_only=false" | |
| echo "non_runtime_only=false" | |
| } >> "$GITHUB_OUTPUT" | |
| exit 0 | |
| fi | |
| if [ -n "$DISPATCH_BASE_SHA" ]; then | |
| export GITHUB_BASE_REF="$DISPATCH_BASE_REF" | |
| BASE_REF="$DISPATCH_BASE_SHA" | |
| else | |
| BASE_REF="${{ github.event.pull_request.base.sha || github.event.merge_group.base_sha || github.event.before || 'origin/main' }}" | |
| fi | |
| script/ci-changes-detector "$BASE_REF" | |
| shell: bash | |
| - name: Guard docs-only main pushes | |
| if: | | |
| (github.event_name == 'push' && github.ref == 'refs/heads/main') || | |
| (github.event_name == 'merge_group' && | |
| github.event.merge_group.base_ref == 'refs/heads/main') | |
| uses: ./.github/actions/ensure-main-docs-safety | |
| with: | |
| docs-only: ${{ steps.detect.outputs.docs_only }} | |
| previous-sha: ${{ github.event.before || github.event.merge_group.base_sha }} | |
| docs-format-check: | |
| needs: detect-changes | |
| if: | | |
| github.event_name == 'pull_request' && | |
| needs.detect-changes.outputs.docs_only == 'true' | |
| runs-on: ubuntu-22.04 | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| # No need for history in lint job | |
| fetch-depth: 1 | |
| persist-credentials: false | |
| - name: Setup Node | |
| uses: actions/setup-node@v4 | |
| with: | |
| # Latest Node comes from .tool-versions; pinned below the Node startup regression. | |
| # https://github.com/nodejs/node/issues/56010 | |
| node-version-file: .tool-versions | |
| - name: Setup pnpm | |
| uses: pnpm/action-setup@v4 | |
| - name: Install Node modules with pnpm | |
| run: pnpm install --frozen-lockfile --ignore-scripts --filter='{.}' | |
| - name: Check formatting | |
| run: pnpm start format.listDifferent | |
| build: | |
| needs: detect-changes | |
| # Run heavyweight lint only when hosted CI is allowed and the detector says | |
| # this PR actually needs lint. Docs-only PRs get the focused check above. | |
| if: | | |
| needs.detect-changes.outputs.should_run_hosted_ci == 'true' && | |
| needs.detect-changes.outputs.run_lint == 'true' | |
| runs-on: ubuntu-22.04 | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| # No need for history in lint job | |
| fetch-depth: 1 | |
| persist-credentials: false | |
| - name: Read runtime versions | |
| id: tool-versions | |
| uses: ./.github/actions/read-tool-versions | |
| - name: Setup Ruby | |
| uses: ./.github/actions/setup-ruby | |
| with: | |
| ruby-version: ${{ steps.tool-versions.outputs.ruby-minor-version }} | |
| - name: Setup Node | |
| uses: actions/setup-node@v4 | |
| with: | |
| # Latest Node comes from .tool-versions; pinned below the Node startup regression. | |
| # https://github.com/nodejs/node/issues/56010 | |
| node-version-file: .tool-versions | |
| - name: Setup pnpm | |
| uses: pnpm/action-setup@v4 | |
| - name: Get pnpm store directory | |
| shell: bash | |
| run: echo "STORE_PATH=$(pnpm store path --silent)" >> "$GITHUB_ENV" | |
| - name: Setup pnpm cache | |
| uses: actions/cache@v4 | |
| with: | |
| path: ${{ env.STORE_PATH }} | |
| key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} | |
| restore-keys: | | |
| ${{ runner.os }}-pnpm-store- | |
| - 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 "pnpm version: "; pnpm --version | |
| echo "Bundler version: "; bundle --version | |
| - name: Check Gemfile.lock platforms | |
| run: ruby script/check-gemfile-lock-platforms | |
| - name: Install Ruby Gems for root lint tools | |
| uses: ./.github/actions/setup-bundle | |
| with: | |
| working-directory: . | |
| ruby-version: ${{ steps.tool-versions.outputs.ruby-minor-version }} | |
| install-libyaml: 'false' | |
| - name: Install Ruby Gems for package | |
| uses: ./.github/actions/setup-bundle | |
| with: | |
| working-directory: react_on_rails | |
| ruby-version: ${{ steps.tool-versions.outputs.ruby-minor-version }} | |
| install-libyaml: 'false' | |
| - name: Install Node modules with pnpm | |
| run: pnpm install --frozen-lockfile | |
| # RuboCop is owned by the root Gemfile/Gemfile.lock so OSS and Pro use one | |
| # locked lint version. Keep package bundles for package-specific tasks. | |
| - name: Lint Ruby | |
| env: | |
| BUNDLE_GEMFILE: ${{ github.workspace }}/Gemfile | |
| run: cd react_on_rails && bundle exec rubocop | |
| # The benchmarks/ scripts live outside the gem, so the package rubocop run | |
| # above doesn't see them. Lint them from the repo root (root .rubocop.yml). | |
| - name: Lint benchmark scripts | |
| env: | |
| BUNDLE_GEMFILE: ${{ github.workspace }}/Gemfile | |
| run: bundle exec rubocop benchmarks | |
| - name: Validate RBS type signatures | |
| env: | |
| BUNDLE_GEMFILE: ${{ github.workspace }}/react_on_rails/Gemfile | |
| run: cd react_on_rails && bundle exec rake rbs:validate | |
| # TODO: Re-enable Steep once RBS signatures are complete for all checked files | |
| # Currently disabled because 374 type errors need to be fixed first | |
| # - name: Run Steep type checker | |
| # run: bundle exec rake rbs:steep | |
| - name: Install Ruby Gems for dummy app | |
| uses: ./.github/actions/setup-bundle | |
| with: | |
| working-directory: react_on_rails/spec/dummy | |
| ruby-version: ${{ steps.tool-versions.outputs.ruby-minor-version }} | |
| install-libyaml: 'false' | |
| - name: generate file system-based packs | |
| run: cd react_on_rails/spec/dummy && RAILS_ENV="test" bundle exec rake react_on_rails:generate_packs | |
| - name: Detect dead code | |
| run: | | |
| pnpm exec knip | |
| pnpm exec knip --production | |
| - name: Lint JS | |
| run: pnpm run eslint --report-unused-disable-directives | |
| - name: Test GitHub Action helpers | |
| run: node .github/actions/ensure-main-docs-safety/check-previous-main.test.cjs | |
| - name: Test custom ESLint rules | |
| run: pnpm run test:eslint-rules | |
| - name: Check formatting | |
| run: pnpm start format.listDifferent | |
| - name: Lint SCSS with stylelint | |
| run: pnpm run lint:scss | |
| - name: Type-check TypeScript | |
| run: pnpm run type-check | |
| - name: Pack for attw and publint | |
| run: cd packages/react-on-rails && pnpm pack | |
| - name: Lint package types | |
| # our package is ESM-only | |
| # Exclude internal exports used for react-on-rails-pro communication | |
| run: pnpm run attw packages/react-on-rails/react-on-rails-*.tgz --profile esm-only --exclude-entrypoints reactApis ReactDOMServer | |
| - name: Lint package publishing | |
| run: pnpm run publint --strict packages/react-on-rails/react-on-rails-*.tgz | |
| # We only download and run Actionlint if there is any difference in GitHub Action workflows | |
| # https://github.com/rhysd/actionlint/blob/main/docs/usage.md#on-github-actions |