diff --git a/.github/workflows/deduplicate-lock-file.yml b/.github/workflows/deduplicate-lock-file.yml index f36f572900..e9d12ee300 100644 --- a/.github/workflows/deduplicate-lock-file.yml +++ b/.github/workflows/deduplicate-lock-file.yml @@ -1,4 +1,4 @@ -name: โš™๏ธ Deduplicate lock file +name: Deduplicate lock file on: push: @@ -17,24 +17,24 @@ jobs: runs-on: ubuntu-latest steps: - - name: โฌ‡๏ธ Checkout repo + - name: Checkout repo uses: actions/checkout@v6 with: token: ${{ secrets.FORMAT_PAT }} - - name: ๐Ÿ“ฆ Setup pnpm + - name: Setup pnpm uses: pnpm/action-setup@v6 - - name: โŽ” Setup node + - name: Setup node uses: actions/setup-node@v6 with: node-version-file: ".nvmrc" cache: "pnpm" - - name: โš™๏ธ Dedupe lock file + - name: Dedupe lock file run: pnpm dedupe && rm -rf ./node_modules && pnpm install - - name: ๐Ÿ’ช Commit + - name: Commit run: | git config --local user.email "hello@remix.run" git config --local user.name "Remix Run Bot" diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 6438bee719..f4b2139b6c 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -1,4 +1,4 @@ -name: ๐Ÿ“š Docs +name: Docs on: push: @@ -24,34 +24,34 @@ jobs: runs-on: ubuntu-latest steps: - - name: โฌ‡๏ธ Checkout repo + - name: Checkout repo uses: actions/checkout@v6 with: token: ${{ secrets.FORMAT_PAT }} ref: ${{ github.event.inputs.branch }} - - name: ๐Ÿ“ฆ Setup pnpm + - name: Setup pnpm uses: pnpm/action-setup@v6 - - name: โŽ” Setup node + - name: Setup node uses: actions/setup-node@v6 with: node-version-file: ".nvmrc" cache: pnpm - - name: ๐Ÿ“ฅ Install deps + - name: Install deps run: pnpm install --frozen-lockfile - - name: ๐Ÿ— Build + - name: Build run: pnpm build - - name: ๐Ÿ“š Generate Typedoc Docs + - name: Generate Typedoc Docs run: pnpm run docs:typedoc - - name: ๐Ÿ“š Generate Markdown Docs + - name: Generate Markdown Docs run: pnpm run docs:jsdoc --write - - name: ๐Ÿ’ช Commit + - name: Commit run: | git config --local user.email "hello@remix.run" git config --local user.name "Remix Run Bot" diff --git a/.github/workflows/format.yml b/.github/workflows/format.yml index 25870a55dd..ec27ef8c01 100644 --- a/.github/workflows/format.yml +++ b/.github/workflows/format.yml @@ -1,4 +1,4 @@ -name: ๐Ÿ‘” Format +name: Format on: push: @@ -16,30 +16,30 @@ jobs: runs-on: ubuntu-latest steps: - - name: โฌ‡๏ธ Checkout repo + - name: Checkout repo uses: actions/checkout@v6 with: token: ${{ secrets.FORMAT_PAT }} - - name: ๐Ÿ“ฆ Setup pnpm + - name: Setup pnpm uses: pnpm/action-setup@v6 - - name: โŽ” Setup node + - name: Setup node uses: actions/setup-node@v6 with: node-version-file: ".nvmrc" cache: pnpm - - name: ๐Ÿ“ฅ Install deps + - name: Install deps run: pnpm install --frozen-lockfile - - name: ๐Ÿ”ƒ Sort contributors.yml + - name: Sort contributors.yml run: sort --ignore-case --output contributors.yml contributors.yml - - name: ๐Ÿ‘” Format + - name: Format run: pnpm format - - name: ๐Ÿ’ช Commit + - name: Commit run: | git config --local user.email "hello@remix.run" git config --local user.name "Remix Run Bot" diff --git a/.github/workflows/integration-full.yml b/.github/workflows/integration-full.yml deleted file mode 100644 index d34ce8ad3d..0000000000 --- a/.github/workflows/integration-full.yml +++ /dev/null @@ -1,53 +0,0 @@ -name: Branch - -# The main branch gets the full run across -# all OS/browsers for multiple node versions - -on: - push: - branches: - - main - paths-ignore: - - "packages/*/.changes/**" - - "decisions/**" - - "docs/**" - - "examples/**" - - "jest/**" - - "scripts/**" - - "tutorial/**" - - "contributors.yml" - - "**/*.md" - -jobs: - build: - name: "โš™๏ธ Build" - if: github.repository == 'remix-run/react-router' - uses: ./.github/workflows/shared-build.yml - - integration-ubuntu: - name: "๐Ÿ‘€ Integration Test" - if: github.repository == 'remix-run/react-router' - uses: ./.github/workflows/shared-integration.yml - with: - os: "ubuntu-latest" - node_version: "[20.19, 22]" - browser: '["chromium", "firefox"]' - - integration-windows: - name: "๐Ÿ‘€ Integration Test" - if: github.repository == 'remix-run/react-router' - uses: ./.github/workflows/shared-integration.yml - with: - os: "windows-latest" - node_version: "[22]" - browser: '["msedge"]' - timeout: 90 - - integration-macos: - name: "๐Ÿ‘€ Integration Test" - if: github.repository == 'remix-run/react-router' - uses: ./.github/workflows/shared-integration.yml - with: - os: "macos-latest" - node_version: "[20.19, 22]" - browser: '["webkit"]' diff --git a/.github/workflows/integration-pr-ubuntu.yml b/.github/workflows/integration-pr-ubuntu.yml deleted file mode 100644 index 98724ba356..0000000000 --- a/.github/workflows/integration-pr-ubuntu.yml +++ /dev/null @@ -1,35 +0,0 @@ -name: PR (Base) - -# All PRs touching code will run tests on ubuntu/node/chromium - -on: - pull_request: - paths-ignore: - - "packages/*/.changes/**" - - "decisions/**" - - "docs/**" - - "examples/**" - - "jest/**" - - "scripts/**" - - "tutorial/**" - - "contributors.yml" - - "**/*.md" - -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true - -jobs: - build: - name: "โš™๏ธ Build" - if: github.repository == 'remix-run/react-router' - uses: ./.github/workflows/shared-build.yml - - integration-chromium: - name: "๐Ÿ‘€ Integration Test" - if: github.repository == 'remix-run/react-router' - uses: ./.github/workflows/shared-integration.yml - with: - os: "ubuntu-latest" - node_version: "[22]" - browser: '["chromium"]' diff --git a/.github/workflows/integration-pr-windows-macos.yml b/.github/workflows/integration-pr-windows-macos.yml deleted file mode 100644 index 9f2a67d441..0000000000 --- a/.github/workflows/integration-pr-windows-macos.yml +++ /dev/null @@ -1,54 +0,0 @@ -name: PR (Full) - -# PRs touching @react-router/dev will also run on Ubuntu/Firefox, Windows/Edge and -# OSX/WebKit as well as an Ubuntu/Chromium run on Node 20.19. - -on: - pull_request: - paths: - - "pnpm-lock.yaml" - - "integration/**" - - "packages/react-router-dev/**" - - "!**/*.md" - -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true - -jobs: - integration-chromium: - name: "๐Ÿ‘€ Integration Test" - if: github.repository == 'remix-run/react-router' - uses: ./.github/workflows/shared-integration.yml - with: - os: "ubuntu-latest" - node_version: "[20.19]" - browser: '["chromium"]' - - integration-firefox: - name: "๐Ÿ‘€ Integration Test" - if: github.repository == 'remix-run/react-router' - uses: ./.github/workflows/shared-integration.yml - with: - os: "ubuntu-latest" - node_version: "[22]" - browser: '["firefox"]' - - integration-msedge: - name: "๐Ÿ‘€ Integration Test" - if: github.repository == 'remix-run/react-router' - uses: ./.github/workflows/shared-integration.yml - with: - os: "windows-latest" - node_version: "[22]" - browser: '["msedge"]' - timeout: 90 - - integration-webkit: - name: "๐Ÿ‘€ Integration Test" - if: github.repository == 'remix-run/react-router' - uses: ./.github/workflows/shared-integration.yml - with: - os: "macos-latest" - node_version: "[22]" - browser: '["webkit"]' diff --git a/.github/workflows/no-response.yml b/.github/workflows/no-response.yml index 5fed41a852..0684e13b00 100644 --- a/.github/workflows/no-response.yml +++ b/.github/workflows/no-response.yml @@ -1,4 +1,4 @@ -name: ๐Ÿฅบ No Response +name: No Response on: schedule: @@ -14,7 +14,7 @@ jobs: if: github.repository == 'remix-run/react-router' runs-on: ubuntu-latest steps: - - name: ๐Ÿฅบ Handle Ghosting + - name: Handle Ghosting uses: actions/stale@v10 with: days-before-close: 10 diff --git a/.github/workflows/pr-actions.yml b/.github/workflows/pr-actions.yml index 724fe3dd8c..1232a1a4b4 100644 --- a/.github/workflows/pr-actions.yml +++ b/.github/workflows/pr-actions.yml @@ -1,4 +1,4 @@ -name: PR (Actions) +name: PR Actions # Triggered when "PR (Check)" completes. Downloads the artifact produced by # the upstream workflow and applies the recorded actions (sticky comments, @@ -7,12 +7,12 @@ name: PR (Actions) on: workflow_run: - workflows: ["PR (Check)"] + workflows: ["PR Checks"] types: [completed] jobs: actions: - name: PR (Actions) + name: Actions if: > github.event.workflow_run.conclusion == 'success' && github.repository == 'remix-run/react-router' @@ -24,29 +24,29 @@ jobs: steps: # Check's out the base (main) branch - not the PR branch - - name: โฌ‡๏ธ Checkout repo + - name: Checkout repo uses: actions/checkout@v6 - - name: ๐Ÿ“ฆ Setup pnpm + - name: Setup pnpm uses: pnpm/action-setup@v6 - - name: โŽ” Setup node + - name: Setup node uses: actions/setup-node@v6 with: node-version-file: ".nvmrc" cache: pnpm - - name: ๐Ÿ“ฅ Install deps + - name: Install deps run: pnpm install --frozen-lockfile - - name: ๐Ÿ“ฅ Download result from upstream workflow + - name: Download result from upstream workflow uses: actions/download-artifact@v8 with: name: pr-checks-result github-token: ${{ github.token }} run-id: ${{ github.event.workflow_run.id }} - - name: ๐Ÿ’ฌ Apply actions + - name: Apply actions env: GITHUB_TOKEN: ${{ github.token }} run: node scripts/pr.ts actions pr-checks-result.json diff --git a/.github/workflows/pr-checks.yml b/.github/workflows/pr-checks.yml index 46d8f5b2a3..d7fda94d18 100644 --- a/.github/workflows/pr-checks.yml +++ b/.github/workflows/pr-checks.yml @@ -1,4 +1,4 @@ -name: PR (Check) +name: PR Checks # Read-only PR inspection. Computes a list of "actions" (sticky comments, # label changes, close, etc.) and uploads them as an artifact. The PR (Actions) @@ -15,29 +15,29 @@ concurrency: jobs: check: - name: ๐Ÿ” Check PR + name: Checks if: github.repository == 'remix-run/react-router' runs-on: ubuntu-latest permissions: pull-requests: read steps: - - name: โฌ‡๏ธ Checkout repo + - name: Checkout repo uses: actions/checkout@v6 - - name: ๐Ÿ“ฆ Setup pnpm + - name: Setup pnpm uses: pnpm/action-setup@v6 - - name: โŽ” Setup node + - name: Setup node uses: actions/setup-node@v6 with: node-version-file: ".nvmrc" cache: pnpm - - name: ๐Ÿ“ฅ Install deps + - name: Install deps run: pnpm install --frozen-lockfile - - name: ๐Ÿ” Run checks + - name: Run checks env: GITHUB_TOKEN: ${{ github.token }} PR_NUMBER: ${{ github.event.pull_request.number }} @@ -46,7 +46,7 @@ jobs: LABEL_NAME: ${{ github.event.label.name }} run: node scripts/pr.ts check - - name: ๐Ÿ“ค Upload result + - name: Upload result uses: actions/upload-artifact@v7 with: name: pr-checks-result diff --git a/.github/workflows/preview.yml b/.github/workflows/preview.yml index 58ed9e5819..127cc1b525 100644 --- a/.github/workflows/preview.yml +++ b/.github/workflows/preview.yml @@ -61,7 +61,7 @@ jobs: - name: Install Node.js uses: actions/setup-node@v6 with: - node-version-file: "package.json" + node-version-file: ".nvmrc" cache: pnpm - name: Install dependencies diff --git a/.github/workflows/release-comments.yml b/.github/workflows/release-comments-manual.yml similarity index 65% rename from .github/workflows/release-comments.yml rename to .github/workflows/release-comments-manual.yml index 273e80ab52..1d1aedc29d 100644 --- a/.github/workflows/release-comments.yml +++ b/.github/workflows/release-comments-manual.yml @@ -1,4 +1,4 @@ -name: ๐Ÿ’ฌ Release Comments (manual) +name: Release Comments (manual) on: workflow_dispatch: @@ -9,30 +9,30 @@ concurrency: jobs: comment: - name: ๐Ÿ“ Comment on released issues/pull requests + name: Comment on released issues/pull requests runs-on: ubuntu-latest permissions: issues: write # enable commenting on released issues pull-requests: write # enable commenting on released pull requests steps: - - name: โฌ‡๏ธ Checkout repo + - name: Checkout repo uses: actions/checkout@v6 with: fetch-depth: 0 - - name: ๐Ÿ“ฆ Setup pnpm + - name: Setup pnpm uses: pnpm/action-setup@v6 - - name: โŽ” Setup node + - name: Setup node uses: actions/setup-node@v6 with: - node-version: 24 # Needed for node TS support + node-version-file: ".nvmrc" cache: "pnpm" - - name: ๐Ÿ“ฅ Install deps + - name: Install deps run: pnpm install --frozen-lockfile - - name: ๐Ÿ“ Comment on released issues and pull requests + - name: Comment on released issues and pull requests env: GH_TOKEN: ${{ github.token }} run: pnpm run release-comments diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index f4c76e5aef..ef0eafb2d6 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -4,16 +4,18 @@ # # Specific jobs only run on the proper trigger: # -# - Change file driven stable releases (push to main/hotfix branches) +# - Change file driven stable releases (push to main/hotfix/v7 branches) +# - v8 prereleases (from a workflow_dispatch trigger on the v8 branch) # - Experimental releases (from a workflow_dispatch trigger) -name: ๐Ÿšข Release/Publish +name: Release on: push: branches: - "main" - "hotfix" + - "v7" workflow_dispatch: inputs: branch: @@ -88,7 +90,7 @@ jobs: - name: Install Node.js uses: actions/setup-node@v6 with: - node-version: 24 # Needed to run typescript scripts directly + node-version-file: ".nvmrc" package-manager-cache: false - name: Install dependencies @@ -108,68 +110,102 @@ jobs: contents: write # enable pushing changes to the origin id-token: write # enable generation of an ID token for publishing steps: - - name: โฌ‡๏ธ Checkout repo + - name: Checkout repo uses: actions/checkout@v6 - - name: ๐Ÿ“ฆ Setup pnpm + - name: Setup pnpm uses: pnpm/action-setup@v6 - - name: โŽ” Setup node + - name: Setup node uses: actions/setup-node@v6 with: - node-version: 24 # Needed for npm@11 for Trusted Publishing + node-version-file: ".nvmrc" package-manager-cache: false - - name: ๐Ÿ“ฅ Install deps + - name: Install deps run: pnpm install --frozen-lockfile - name: Build packages run: pnpm build - name: Publish to npm and create releases - run: pnpm changes:publish + run: pnpm changes:publish -- --branch=${{ github.ref_name }} env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} comment: - name: ๐Ÿ“ Comment on released issues/pull requests + name: Comment on released issues/pull requests needs: publish + # Only comment on issues/PRs for latest releases from main. + if: github.ref_name == 'main' runs-on: ubuntu-latest permissions: issues: write # enable commenting on released issues pull-requests: write # enable commenting on released pull requests steps: - - name: โฌ‡๏ธ Checkout repo + - name: Checkout repo uses: actions/checkout@v6 with: fetch-depth: 0 - - name: ๐Ÿ“ฆ Setup pnpm + - name: Setup pnpm uses: pnpm/action-setup@v6 - - name: โŽ” Setup node + - name: Setup node uses: actions/setup-node@v6 with: - node-version: 24 # Needed for node TS support + node-version-file: ".nvmrc" package-manager-cache: false - - name: ๐Ÿ“ฅ Install deps + - name: Install deps run: pnpm install --frozen-lockfile - - name: ๐Ÿ“ Comment on released issues and pull requests + - name: Comment on released issues and pull requests env: GH_TOKEN: ${{ github.token }} run: pnpm run release-comments + prerelease: + name: Publish prerelease (v8) + if: github.repository == 'remix-run/react-router' && github.event_name == 'workflow_dispatch' && github.event.inputs.branch == 'v8' + runs-on: ubuntu-latest + permissions: + contents: read + id-token: write # enable generation of an ID token for publishing + steps: + - name: Checkout repo + uses: actions/checkout@v6 + with: + ref: ${{ github.event.inputs.branch }} + fetch-depth: 0 # needed for tags + + - name: Setup pnpm + uses: pnpm/action-setup@v6 + + - name: Setup node + uses: actions/setup-node@v6 + with: + node-version-file: ".nvmrc" + package-manager-cache: false + + - name: Install deps + run: pnpm install --frozen-lockfile + + - name: Build + run: pnpm build + + - name: Publish prerelease + run: pnpm prerelease:publish + experimental-release: - name: ๐Ÿงช Experimental Release - if: github.repository == 'remix-run/react-router' && github.event_name == 'workflow_dispatch' + name: Experimental Release + if: github.repository == 'remix-run/react-router' && github.event_name == 'workflow_dispatch' && github.event.inputs.branch != 'v8' runs-on: ubuntu-latest permissions: contents: write # enable pushing changes to the origin id-token: write # enable generation of an ID token for publishing steps: - - name: โฌ‡๏ธ Checkout repo + - name: Checkout repo uses: actions/checkout@v6 with: ref: ${{ github.event.inputs.branch }} @@ -177,27 +213,27 @@ jobs: token: ${{ secrets.GITHUB_TOKEN }} fetch-depth: 0 - - name: ๐Ÿ“ฆ Setup pnpm + - name: Setup pnpm uses: pnpm/action-setup@v6 - - name: โŽ” Setup node + - name: Setup node uses: actions/setup-node@v6 with: - node-version: 24 # Needed for npm@11 for Trusted Publishing + node-version-file: ".nvmrc" package-manager-cache: false - - name: ๐Ÿ“ฅ Install deps + - name: Install deps run: pnpm install --frozen-lockfile - - name: โคด๏ธ Update version + - name: Update version run: | git config --local user.email "hello@remix.run" git config --local user.name "Remix Run Bot" pnpm run experimental:version git push origin --tags - - name: ๐Ÿ— Build + - name: Build run: pnpm build - - name: ๐Ÿš€ Publish + - name: Publish run: pnpm run experimental:publish diff --git a/.github/workflows/shared-build.yml b/.github/workflows/shared-build.yml deleted file mode 100644 index 06e5e44b48..0000000000 --- a/.github/workflows/shared-build.yml +++ /dev/null @@ -1,38 +0,0 @@ -name: ๐Ÿ› ๏ธ Build - -on: - workflow_call: - -env: - CI: true - -jobs: - build: - runs-on: ubuntu-latest - steps: - - name: โฌ‡๏ธ Checkout repo - uses: actions/checkout@v6 - - - name: ๐Ÿ“ฆ Setup pnpm - uses: pnpm/action-setup@v6 - - - name: โŽ” Setup node - uses: actions/setup-node@v6 - with: - node-version-file: ".nvmrc" - cache: "pnpm" - - # TODO: Track and renable once this has been fixed: https://github.com/google/wireit/issues/1297 - # - uses: google/wireit@setup-github-actions-caching/v2 - - - name: Disable GitHub Actions Annotations - run: | - echo "::remove-matcher owner=tsc::" - echo "::remove-matcher owner=eslint-compact::" - echo "::remove-matcher owner=eslint-stylish::" - - - name: ๐Ÿ“ฅ Install deps - run: pnpm install --frozen-lockfile - - - name: ๐Ÿ— Build - run: pnpm build diff --git a/.github/workflows/shared-integration.yml b/.github/workflows/shared-integration.yml deleted file mode 100644 index 34fade4888..0000000000 --- a/.github/workflows/shared-integration.yml +++ /dev/null @@ -1,69 +0,0 @@ -name: ๐Ÿงช Test (Integration) - -on: - workflow_call: - inputs: - os: - required: true - type: string - node_version: - required: true - # this is limited to string | boolean | number (https://github.community/t/can-action-inputs-be-arrays/16457) - # but we want to pass an array (node_version: "[20, 22]"), - # so we'll need to manually stringify it for now - type: string - browser: - required: true - # this is limited to string | boolean | number (https://github.community/t/can-action-inputs-be-arrays/16457) - # but we want to pass an array (browser: "['chromium', 'firefox']"), - # so we'll need to manually stringify it for now - type: string - timeout: - required: false - type: number - default: 45 - -env: - CI: true - -jobs: - integration: - name: "${{ inputs.os }} / node@${{ matrix.node }} / ${{ matrix.browser }}" - strategy: - fail-fast: false - matrix: - node: ${{ fromJSON(inputs.node_version) }} - browser: ${{ fromJSON(inputs.browser) }} - - runs-on: ${{ inputs.os }} - steps: - - name: โฌ‡๏ธ Checkout repo - uses: actions/checkout@v6 - - - name: ๐Ÿ“ฆ Setup pnpm - uses: pnpm/action-setup@v6 - - - name: โŽ” Setup node ${{ matrix.node }} - uses: actions/setup-node@v6 - with: - node-version: ${{ matrix.node }} - cache: "pnpm" - - # TODO: Track and renable once this has been fixed: https://github.com/google/wireit/issues/1297 - # - uses: google/wireit@setup-github-actions-caching/v2 - - - name: Disable GitHub Actions Annotations - run: | - echo "::remove-matcher owner=tsc::" - echo "::remove-matcher owner=eslint-compact::" - echo "::remove-matcher owner=eslint-stylish::" - - - name: ๐Ÿ“ฅ Install deps - run: pnpm install --frozen-lockfile - - - name: ๐Ÿ“ฅ Install Playwright - run: npx playwright install --with-deps ${{ matrix.browser }} - - - name: ๐Ÿ‘€ Run Integration Tests ${{ matrix.browser }} - run: "pnpm test:integration --project=${{ matrix.browser }}" - timeout-minutes: ${{inputs.timeout}} diff --git a/.github/workflows/test-integration-run.yml b/.github/workflows/test-integration-run.yml new file mode 100644 index 0000000000..5b88f76198 --- /dev/null +++ b/.github/workflows/test-integration-run.yml @@ -0,0 +1,58 @@ +name: Test (Integration) + +on: + workflow_call: + inputs: + os: + required: true + type: string + node_version: + required: true + type: string + browser: + required: true + type: string + timeout: + required: false + type: number + default: 30 + +env: + CI: true + +jobs: + integration: + name: "${{ inputs.os }} / node@${{ inputs.node_version }} / ${{ inputs.browser }}" + + runs-on: ${{ inputs.os }} + steps: + - name: Checkout repo + uses: actions/checkout@v6 + + - name: Setup pnpm + uses: pnpm/action-setup@v6 + + - name: Setup node ${{ inputs.node_version }} + uses: actions/setup-node@v6 + with: + node-version: ${{ inputs.node_version }} + cache: "pnpm" + + - name: Setup wireit cache + uses: google/wireit@setup-github-actions-caching/v2.0.4 + + - name: Disable GitHub Actions Annotations + run: | + echo "::remove-matcher owner=tsc::" + echo "::remove-matcher owner=eslint-compact::" + echo "::remove-matcher owner=eslint-stylish::" + + - name: Install deps + run: pnpm install --frozen-lockfile + + - name: Install Playwright + run: npx playwright install --with-deps ${{ inputs.browser }} + + - name: Run Integration Tests ${{ inputs.browser }} + run: "pnpm test:integration --project=${{ inputs.browser }}" + timeout-minutes: ${{inputs.timeout}} diff --git a/.github/workflows/test-integration.yml b/.github/workflows/test-integration.yml new file mode 100644 index 0000000000..53d0d05618 --- /dev/null +++ b/.github/workflows/test-integration.yml @@ -0,0 +1,166 @@ +name: Integration Test + +# Incrementally comprehensive based on the type of change: +# +# | Type | Description | Test Runs | +# |------|------------------------------------|-----------------------------------------------------| +# | base | Non-docs and draft PRs | Chromium (Node 24). | +# | dev | @react-router/dev or v8 branch PRs | + Firefox/Webkit/Edge (Node 24), Chromium (Node 22) | +# | full | Commits on `main` | + Firefox/Webkit (Node 22) | + +on: + push: + branches: + - main + paths: + - "packages/**" + - "integration/**" + - "package.json" + - "pnpm-lock.yaml" + - "pnpm-workspace.yaml" + - "build.utils.ts" + - "build.utils.d.ts" + - "!**/*.md" + pull_request: + paths: + - "packages/**" + - "integration/**" + - "package.json" + - "pnpm-lock.yaml" + - "pnpm-workspace.yaml" + - "build.utils.ts" + - "build.utils.d.ts" + - "!**/*.md" + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +permissions: + contents: read + pull-requests: read + +jobs: + changes: + name: "Check Changed Files" + if: github.repository == 'remix-run/react-router' + runs-on: ubuntu-latest + outputs: + type: ${{ steps.suites.outputs.type }} + steps: + # Need to checkout the repo so we can use the `gh` CLI + - name: Checkout repo + uses: actions/checkout@v6 + + - name: Select integration suites + id: suites + env: + GH_TOKEN: ${{ github.token }} + # If `gh pr diff` exits with a non-zero code, it might be because the PR + # has >300 files, or it could be for any number of unknown reasons. If + # that happens take the conservative route and run the larger `dev` suite. + run: | + if [ "${{ github.event_name }}" = "push" ]; then + echo "Selected integration suite: full (push to main)" + echo "type=full" >> "$GITHUB_OUTPUT" + elif [ "${{ github.event.pull_request.head.ref }}" = "v8" ]; then + echo "Selected integration suite: dev (v8 PR)" + echo "type=dev" >> "$GITHUB_OUTPUT" + elif [ "${{ github.event.pull_request.draft }}" = "true" ]; then + echo "Selected integration suite: base (draft PR)" + echo "type=base" >> "$GITHUB_OUTPUT" + else + set +e + OUTPUT=$(gh pr diff "${{ github.event.pull_request.number }}" --name-only) + CODE=$? + set -e + + if [ $CODE != 0 ]; then + echo "Selected integration suite: dev (failed to fetch PR diff - gh cli exited with $CODE)" + echo "type=dev" >> "$GITHUB_OUTPUT" + elif echo "$OUTPUT" | grep -q '^packages/react-router-dev/'; then + echo "Selected integration suite: dev (changes to packages/react-router-dev/)" + echo "type=dev" >> "$GITHUB_OUTPUT" + else + echo "Selected integration suite: base (no packages/react-router-dev/ changes detected)" + echo "type=base" >> "$GITHUB_OUTPUT" + fi + fi + + # base only runs Node 24/Chromium + integration-chromium: + name: "Chromium (24)" + needs: changes + if: github.repository == 'remix-run/react-router' + uses: ./.github/workflows/test-integration-run.yml + with: + os: "ubuntu-latest" + node_version: "24" + browser: "chromium" + + # dev/full add Node 22/Chromium + integration-chromium-node-22: + name: "Chromium (22)" + needs: changes + if: github.repository == 'remix-run/react-router' && contains(fromJSON('["dev", "full"]'), needs.changes.outputs.type) + uses: ./.github/workflows/test-integration-run.yml + with: + os: "ubuntu-latest" + node_version: "22.22" + browser: "chromium" + + # dev/full add Node 24/Firefox + integration-firefox: + name: "Firefox (24)" + needs: changes + if: github.repository == 'remix-run/react-router' && contains(fromJSON('["dev", "full"]'), needs.changes.outputs.type) + uses: ./.github/workflows/test-integration-run.yml + with: + os: "ubuntu-latest" + node_version: "24" + browser: "firefox" + + # dev/full add Node 24/Edge + integration-msedge: + name: "Edge (24)" + needs: changes + if: github.repository == 'remix-run/react-router' && contains(fromJSON('["dev", "full"]'), needs.changes.outputs.type) + uses: ./.github/workflows/test-integration-run.yml + with: + os: "windows-latest" + node_version: "24" + browser: "msedge" + timeout: 60 + + # dev/full add Node 24/WebKit + integration-webkit: + name: "WebKit (24)" + needs: changes + if: github.repository == 'remix-run/react-router' && contains(fromJSON('["dev", "full"]'), needs.changes.outputs.type) + uses: ./.github/workflows/test-integration-run.yml + with: + os: "macos-latest" + node_version: "24" + browser: "webkit" + + # full adds Node 22/Firefox + integration-firefox-node-22: + name: "Firefox (22)" + needs: changes + if: github.repository == 'remix-run/react-router' && needs.changes.outputs.type == 'full' + uses: ./.github/workflows/test-integration-run.yml + with: + os: "ubuntu-latest" + node_version: "22.22" + browser: "firefox" + + # full adds Node 22/WebKit + integration-webkit-node-22: + name: "WebKit (22)" + needs: changes + if: github.repository == 'remix-run/react-router' && needs.changes.outputs.type == 'full' + uses: ./.github/workflows/test-integration-run.yml + with: + os: "macos-latest" + node_version: "22.22" + browser: "webkit" diff --git a/.github/workflows/test.yml b/.github/workflows/test-unit.yml similarity index 65% rename from .github/workflows/test.yml rename to .github/workflows/test-unit.yml index ffd903f3cb..14f1f5a41c 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test-unit.yml @@ -1,4 +1,4 @@ -name: ๐Ÿงช Test +name: Unit Test on: push: @@ -8,7 +8,7 @@ on: - v* paths-ignore: - "docs/**" - - "**/README.md" + - "**/*.md" pull_request: paths-ignore: - "docs/**" @@ -23,32 +23,31 @@ permissions: jobs: test: - name: "๐Ÿงช Test: (Node: ${{ matrix.node }})" + name: "Node ${{ matrix.node }}" + runs-on: ubuntu-latest strategy: fail-fast: false matrix: node: - - 20.19 - - 22 - - runs-on: ubuntu-latest + - 22.22 + - 24 steps: - - name: โฌ‡๏ธ Checkout repo + - name: Checkout repo uses: actions/checkout@v6 - - name: ๐Ÿ“ฆ Setup pnpm + - name: Setup pnpm uses: pnpm/action-setup@v6 - - name: โŽ” Setup node + - name: Setup node uses: actions/setup-node@v6 with: node-version: ${{ matrix.node }} cache: pnpm check-latest: true - # TODO: Track and renable once this has been fixed: https://github.com/google/wireit/issues/1297 - # - uses: google/wireit@setup-github-actions-caching/v2 + - name: Setup wireit cache + uses: google/wireit@setup-github-actions-caching/v2.0.4 - name: Disable GitHub Actions Annotations run: | @@ -56,17 +55,17 @@ jobs: echo "::remove-matcher owner=eslint-compact::" echo "::remove-matcher owner=eslint-stylish::" - - name: ๐Ÿ“ฅ Install deps + - name: Install deps run: pnpm install --frozen-lockfile - - name: ๐Ÿ— Build + - name: Build run: pnpm build - - name: ๐Ÿ” Typecheck + - name: Typecheck run: pnpm typecheck - - name: ๐Ÿ”ฌ Lint + - name: Lint run: pnpm lint - - name: ๐Ÿงช Run tests + - name: Run tests run: pnpm test diff --git a/.gitignore b/.gitignore index c4c5ec46ea..52bd86ee6e 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,7 @@ npm-debug.log /website/build/ node_modules/ +.pnpm-store/ /examples/*/yarn.lock /examples/*/pnpm-lock.yaml @@ -28,7 +29,7 @@ node_modules/ .wireit .eslintcache .tmp -tsup.config.bundled_*.mjs +tsdown.config.bundled_*.mjs build.utils.d.ts worker-configuration.d.ts /.env diff --git a/.nvmrc b/.nvmrc index 8fdd954df9..cabf43b5dd 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -22 \ No newline at end of file +24 \ No newline at end of file diff --git a/.prettierignore b/.prettierignore index e293384554..bb1bedff36 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1,3 +1,4 @@ +# Prettier ignore patterns. /fixtures/ node_modules/ pnpm-lock.yaml @@ -15,8 +16,5 @@ build.utils.d.ts .tmp/ .react-router/ packages/**/dist/ -packages/react-router-dom/server.d.ts -packages/react-router-dom/server.js -packages/react-router-dom/server.mjs tutorial/dist/ public/ diff --git a/AGENTS.md b/AGENTS.md index 61fa0db792..e8ae5037a2 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -32,7 +32,6 @@ - **Key packages**: - `react-router`: Core (all modes) - `lib/components.tsx`, `lib/hooks.tsx`, `lib/router/`, `lib/dom/`, `lib/rsc/` - `@react-router/dev`: Framework tooling - `vite/plugin.ts` (Framework), `vite/rsc/plugin.ts` (RSC Framework), `typegen/` - - `react-router-dom`: Re-exports `react-router` (v6โ†’v7 compat) - `@react-router/node`, `@react-router/cloudflare`, `@react-router/express`: Server adapters - `@react-router/serve`: Minimal server for Framework Mode - `@react-router/fs-routes`: File-system routing (`flatRoutes()`) diff --git a/CHANGELOG.md b/CHANGELOG.md index dd39d23bfb..b2055c192f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,10 @@ # React Router Releases -This page lists all releases/release notes for React Router back to `v6.0.0`. For releases prior to v6, please refer to the [Github Releases Page](https://github.com/remix-run/react-router/releases). +This page lists all releases/release notes for React Router back to `v7.0.0`. + +- For v6.x releases, please refer to the [v6](https://github.com/remix-run/react-router/blob/v6/CHANGELOG.md) branch +- For releases prior to v6, please refer to the [Github Releases Page](https://github.com/remix-run/react-router/releases) We manage release notes in this file instead of the paginated Github Releases Page for 2 reasons: @@ -16,8 +19,6 @@ We manage release notes in this file instead of the paginated Github Releases Pa - [v7.18.0](#v7180) - [v7.17.0](#v7170) - [v7.16.0](#v7160) - - [Stabilized `future.v8_trailingSlashAwareDataRequests`](#stabilized-futurev8_trailingslashawaredatarequests) - - [Pre-v8 Future Flag Warnings](#pre-v8-future-flag-warnings) - [v7.15.1](#v7151) - [v7.15.0](#v7150) - [Stabilizations](#stabilizations) @@ -89,92 +90,6 @@ We manage release notes in this file instead of the paginated Github Releases Pa - [v7.0.2](#v702) - [v7.0.1](#v701) - [v7.0.0](#v700) -- [React Router v6 Releases](#react-router-v6-releases) - - [v6.30.3](#v6303) - - [v6.30.2](#v6302) - - [v6.30.1](#v6301) - - [v6.30.0](#v6300) - - [v6.29.0](#v6290) - - [v6.28.2](#v6282) - - [v6.28.1](#v6281) - - [v6.28.0](#v6280) - - [v6.27.0](#v6270) - - [Stabilized APIs](#stabilized-apis) - - [v6.26.2](#v6262) - - [v6.26.1](#v6261) - - [v6.26.0](#v6260) - - [v6.25.1](#v6251) - - [v6.25.0](#v6250) - - [Stabilized `v7_skipActionErrorRevalidation`](#stabilized-v7_skipactionerrorrevalidation) - - [v6.24.1](#v6241) - - [v6.24.0](#v6240) - - [Lazy Route Discovery (a.k.a. "Fog of War")](#lazy-route-discovery-aka-fog-of-war) - - [v6.23.1](#v6231) - - [v6.23.0](#v6230) - - [Data Strategy (unstable)](#data-strategy-unstable) - - [Skip Action Error Revalidation (unstable)](#skip-action-error-revalidation-unstable) - - [v6.22.3](#v6223) - - [v6.22.2](#v6222) - - [v6.22.1](#v6221) - - [v6.22.0](#v6220) - - [Core Web Vitals Technology Report Flag](#core-web-vitals-technology-report-flag) - - [v6.21.3](#v6213) - - [v6.21.2](#v6212) - - [v6.21.1](#v6211) - - [v6.21.0](#v6210) - - [`future.v7_relativeSplatPath`](#futurev7_relativesplatpath) - - [Partial Hydration](#partial-hydration) - - [v6.20.1](#v6201) - - [v6.20.0](#v6200) - - [v6.19.0](#v6190) - - [`unstable_flushSync` API](#unstable_flushsync-api) - - [v6.18.0](#v6180) - - [New Fetcher APIs](#new-fetcher-apis) - - [Persistence Future Flag (`future.v7_fetcherPersist`)](#persistence-future-flag-futurev7_fetcherpersist) - - [v6.17.0](#v6170) - - [View Transitions ๐Ÿš€](#view-transitions) - - [v6.16.0](#v6160) - - [v6.15.0](#v6150) - - [v6.14.2](#v6142) - - [v6.14.1](#v6141) - - [v6.14.0](#v6140) - - [JSON/Text Submissions](#jsontext-submissions) - - [v6.13.0](#v6130) - - [`future.v7_startTransition`](#futurev7_starttransition) - - [v6.12.1](#v6121) - - [v6.12.0](#v6120) - - [`React.startTransition` support](#reactstarttransition-support) - - [v6.11.2](#v6112) - - [v6.11.1](#v6111) - - [v6.11.0](#v6110) - - [v6.10.0](#v6100) - - [v6.9.0](#v690) - - [`Component`/`ErrorBoundary` route properties](#componenterrorboundary-route-properties) - - [Introducing Lazy Route Modules](#introducing-lazy-route-modules) - - [v6.8.2](#v682) - - [v6.8.1](#v681) - - [v6.8.0](#v680) - - [v6.7.0](#v670) - - [v6.6.2](#v662) - - [v6.6.1](#v661) - - [v6.6.0](#v660) - - [v6.5.0](#v650) - - [v6.4.5](#v645) - - [v6.4.4](#v644) - - [v6.4.3](#v643) - - [v6.4.2](#v642) - - [v6.4.1](#v641) - - [v6.4.0](#v640) - - [Remix Data APIs](#remix-data-apis) - - [v6.3.0](#v630) - - [v6.2.2](#v622) - - [v6.2.1](#v621) - - [v6.2.0](#v620) - - [v6.1.1](#v611) - - [v6.1.0](#v610) - - [v6.0.2](#v602) - - [v6.0.1](#v601) - - [v6.0.0](#v600) @@ -242,37 +157,37 @@ Date: 2026-06-04 Date: 2026-05-28 -### What's Changed - -#### Stabilized `future.v8_trailingSlashAwareDataRequests` - -We've stabilized this flag in preparation for the upcoming v8 release. Unless you are doing specific path-inspection on `.data` requests or have specific CDN/caching/pre-rendering logic around `.data` requests, this should largely be a zero-code-change adoptions. Please see the [docs](https://reactrouter.com/upgrading/future#futurev8_trailingslashawaredatarequests) for more info. - -#### Pre-v8 Future Flag Warnings - -In preparation for the upcoming v8 release, `7.16.0` begins logging console warnings during builds for future flags that you have not enabled yet. If you have all future flags enabled, the v8 upgrade should be mostly non-breaking (short of some underlying dependency minimum versions bumps - React 19, Node 22.12, Vite 7). You can suppress these warnings until you are ready top adopt flags by setting an explicit `false` in your `react-router.config.ts`. - ### Minor Changes - `react-router` - Stabilize `future.unstable_trailingSlashAwareDataRequests` as `future.v8_trailingSlashAwareDataRequests` ([#15098](https://github.com/remix-run/react-router/pull/15098)) + +- `@react-router/dev` - Stabilize `future.unstable_trailingSlashAwareDataRequests` as `future.v8_trailingSlashAwareDataRequests` ([#15098](https://github.com/remix-run/react-router/pull/15098)) + - The unstable flag is no longer supported and will error during config resolution + - `@react-router/dev` - Log future flag warnings for upcoming React Router v8 flags ([#15029](https://github.com/remix-run/react-router/pull/15029)) - `v8_middleware`, `v8_splitRouteModules`, `v8_viteEnvironmentApi`, `v8_passThroughRequests`, `v8_trailingSlashAwareDataRequests` ### Patch Changes -- `react-router` - Disable manifest path when lazy route discovery is disabled ([#15068](https://github.com/remix-run/react-router/pull/15068)) -- `react-router` - Fix browser URL creation to use the configured history `window` instead of the global `window` ([#15066](https://github.com/remix-run/react-router/pull/15066)) +- `react-router` - Disable manifest path when lazy route dicovery is disabled ([#15068](https://github.com/remix-run/react-router/pull/15068)) + +- `react-router` - Fix browser URL creation to use the configured history window instead of the global window. ([#15066](https://github.com/remix-run/react-router/pull/15066)) - Pass the history/router window through to `createBrowserURLImpl` so custom window contexts keep the correct URL origin. + - `react-router` - Fix `useNavigation()` return type to preserve discriminated union across navigation states ([#15095](https://github.com/remix-run/react-router/pull/15095)) + - `react-router` - Widen `MetaDescriptor` `script:ld+json` type from `LdJsonObject` to `LdJsonObject | LdJsonObject[]` to permit multiple JSON-LD schemas in a single `