Skip to content

Commit 9b94f11

Browse files
authored
feat: Remove RWSDK_DEPLOY for cross-platform builds and fix Windows E2E tests (#851)
This PR introduces fixes to resolve E2E test failures on Windows CI. ## User-Facing Fixes * **Cross-Platform Scripting:** * **Removed `RWSDK_DEPLOY` Env Var:** Replaced the non-portable `RWSDK_DEPLOY=1` syntax in starter's `package.json` scripts with a check against `process.env.NODE_ENV`. Vite automatically sets `NODE_ENV` to `"production"` for builds and `"development"` for the dev server. This provides a reliable, cross-platform way to determine the build context without requiring extra dependencies. This is also backwards compatible for existing projects created from the starter previously. ## E2E and CI Fixes * **Windows Path Normalization:** * **Vite Alias Resolution:** The primary cause of test failures was a path mismatch issue on Windows CI. Node.js was returning legacy "short" paths (e.g., `RUNNER~1`), while Vite's internals resolved to modern "long" paths (e.g., `runneradmin`). This inconsistency broke module alias resolution. The fix was to replace `fs.realpathSync` with `fs.realpathSync.native` throughout the E2E harness, which correctly canonicalizes paths to their long form. * **Yarn YAML Parsing:** Corrected an issue where backslashes in Windows paths would cause YAML parsing errors in `.yarnrc.yml` files by normalizing paths to use forward slashes. * **CI & E2E Test Harness Stability:** * **Dev Server Timeout:** Resolved an issue where the dev server would fail silently on Windows. The root cause was `execa`'s `detached: true` option severing `stdio` streams. The fix was to conditionally set this option to `false` on Windows, restoring error and log output. * **Package Manager Verbosity:** Added silent flags (`--reporter=silent`, `--silent`) to `pnpm`, `npm`, and `yarn` install commands to reduce log noise in CI. * **GitHub Actions Workflow:** Fixed syntax errors in the `playground-e2e-tests.yml` workflow by removing a faulty conditional `shell` property and relying on runner defaults. * **Windows Debugging Environment:** * An interactive debugging environment for Windows was created and refined. It can be triggered via `./scripts/start-windows-debug.sh`. * The environment automatically configures the runner with the user's local Git credentials, sets up custom git aliases, starts a Cursor tunnel, and launches a PowerShell session on SSH login. * Securely forwards local `CLOUDFLARE_` environment variables to the remote session for testing. ## Current Status The fixes in this PR have improved the stability of E2E tests on Windows, but several failures remain. Many of these appear to be timeouts, which may be transient. The current test results on Windows are as follows: * **pnpm:** * Test Files: 10 failed, 6 passed (16 total) * Tests: 9 failed, 22 passed, 23 skipped (54 total) * **npm:** * Test Files: 14 failed, 2 passed (16 total) * Tests: 1 failed, 4 passed, 49 skipped (54 total) * Note: Includes a hook timeout error. * **Yarn (Classic):** * Test Files: 12 failed, 4 passed (16 total) * Tests: 12 failed, 17 passed, 25 skipped (54 total)
1 parent 49ace5e commit 9b94f11

File tree

37 files changed

+1199
-503
lines changed

37 files changed

+1199
-503
lines changed

.github/workflows/playground-e2e-tests.yml

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ jobs:
9797
matrix: ${{ fromJson(needs.setup-matrix.outputs.matrix) }}
9898
timeout-minutes: 60
9999
env:
100+
DEBUG: rwsdk:e2e:*
100101
MAX_RETRIES: ${{ (github.event_name == 'schedule' || github.event_name == 'workflow_call') && '10' || '1' }}
101102
RWSDK_SETUP_PLAYGROUND_ENV_TIMEOUT: ${{ (github.event_name == 'schedule' || github.event_name == 'workflow_call') && '1800000' || '' }} # 30 mins
102103
RWSDK_DEPLOYMENT_TIMEOUT: ${{ (github.event_name == 'schedule' || github.event_name == 'workflow_call') && '900000' || '' }} # 15 mins
@@ -145,24 +146,26 @@ jobs:
145146
cache: "pnpm"
146147

147148
- name: Install dependencies
148-
shell: bash
149149
run: pnpm install
150150

151151
- name: Build SDK
152-
shell: bash
153152
run: |
154153
cd sdk
155154
pnpm build
156155
156+
- name: Setup E2E Cache
157+
uses: actions/cache@v4
158+
with:
159+
path: .tmp/rwsdk-e2e/rwsdk-e2e-cache
160+
key: ${{ runner.os }}-${{ matrix.package-manager }}-e2e-deps-${{ hashFiles('playground/**/package.json', 'playground/**/pnpm-lock.yaml', 'playground/**/yarn.lock', 'playground/**/package-lock.json') }}
161+
restore-keys: |
162+
${{ runner.os }}-${{ matrix.package-manager }}-e2e-deps-
163+
157164
- name: Run Playground E2E Tests
158165
id: tests
159-
shell: bash
160166
run: |
161167
pnpm install
162168
pnpm test:e2e
163-
env:
164-
CI: 1
165-
PACKAGE_MANAGER: ${{ matrix.package-manager }}
166169
167170
- name: Upload playground artifacts
168171
uses: actions/upload-artifact@v4

.github/workflows/windows-debug.yml

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,18 @@ on:
66
cursorTunnelName:
77
description: "Optional Cursor tunnel name (<=20 chars); leave blank for random"
88
required: false
9+
gitUserName:
10+
description: "Git user name (from local config)"
11+
required: false
12+
gitUserEmail:
13+
description: "Git user email (from local config)"
14+
required: false
15+
cloudflareAccountId:
16+
description: "Cloudflare Account ID (from local env)"
17+
required: false
18+
cloudflareApiToken:
19+
description: "Cloudflare API Token (from local env)"
20+
required: false
921

1022
jobs:
1123
debug-session:
@@ -34,5 +46,47 @@ jobs:
3446
tar -xvf $CursorArchive -C $CursorDir | Out-Null
3547
Write-Host "Cursor CLI extracted to $CursorDir"
3648
49+
- name: Download auto-commit script
50+
shell: pwsh
51+
run: |
52+
$AdScriptPath = "$env:GITHUB_WORKSPACE\.tmp\bin\ad"
53+
$AdScriptDir = Split-Path -Parent $AdScriptPath
54+
if (-not (Test-Path $AdScriptDir)) {
55+
New-Item -ItemType Directory -Path $AdScriptDir -Force | Out-Null
56+
}
57+
58+
# Download from gist
59+
$GistUrl = "https://gist.githubusercontent.com/justinvdm/fcd6da9d28057addd263214d90793137/raw/e7404b71a0a27b9538890a95dd7804b18ec10c5d/ad"
60+
Invoke-WebRequest -Uri $GistUrl -OutFile $AdScriptPath
61+
62+
# Make executable (bash will handle this)
63+
bash -c "chmod +x '$AdScriptPath'"
64+
65+
# Add to PATH for PowerShell
66+
$env:Path += ";$AdScriptDir"
67+
[Environment]::SetEnvironmentVariable("Path", $env:Path, [EnvironmentVariableTarget]::User)
68+
69+
Write-Host "ad script downloaded to: $AdScriptPath"
70+
71+
- name: Setup Auto-Run Scripts
72+
shell: pwsh
73+
run: |
74+
$params = @{
75+
CursorTunnelName = "${{ inputs.cursorTunnelName }}"
76+
}
77+
if ("${{ inputs.gitUserName }}" -ne "") {
78+
$params.GitUserName = "${{ inputs.gitUserName }}"
79+
}
80+
if ("${{ inputs.gitUserEmail }}" -ne "") {
81+
$params.GitUserEmail = "${{ inputs.gitUserEmail }}"
82+
}
83+
if ("${{ inputs.cloudflareAccountId }}" -ne "") {
84+
$params.CloudflareAccountId = "${{ inputs.cloudflareAccountId }}"
85+
}
86+
if ("${{ inputs.cloudflareApiToken }}" -ne "") {
87+
$params.CloudflareApiToken = "${{ inputs.cloudflareApiToken }}"
88+
}
89+
pwsh -File "$env:GITHUB_WORKSPACE/scripts/setup-windows-debug-env.ps1" @params
90+
3791
- name: Start Interactive Debug Session
3892
uses: mxschmitt/action-tmate@v3
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
**Fix:** The solution is to normalize the `cacheFolder` path to use forward slashes, which are universally accepted in YAML files, regardless of the operating system. I will modify the path string before it's written to the file.
2+
3+
### 2. Cross-Platform Environment Variables in `package.json`
4+
5+
**Issue:** The `release` script in the `starter` and all `playground` examples used `RWSDK_DEPLOY=1 wrangler deploy` to signal a production build to the Redwood plugin. This syntax for setting environment variables is not cross-platform and fails on Windows with shells like PowerShell or Command Prompt.
6+
7+
**Investigation:** My first thought was to introduce a dependency like `cross-env` to handle this. However, this would add a new dependency to user projects and felt like a workaround rather than a fundamental solution.
8+
9+
We then explored several alternatives to remove the need for the environment variable altogether:
10+
- **Using `process.argv`**: This was quickly dismissed as too brittle, as it depends on how Vite is invoked.
11+
- **Using Vite's `configResolved` hook**: This was also incorrect because the `dev:init` script needs to run *before* other plugins are instantiated, and this hook runs too late in the lifecycle.
12+
- **Exporting a function from `vite.config.mts`**: This is the idiomatic Vite way to handle command-dependent configuration. It would work but would constitute a significant breaking change for all existing users, forcing them to update their `vite.config.mts` files.
13+
14+
**Solution:** The most elegant and backward-compatible solution came from realizing we could rely on the `NODE_ENV` variable that Vite itself sets very early in its process.
15+
16+
- Vite sets `NODE_ENV` to `'production'` for builds.
17+
- Vite sets `NODE_ENV` to `'development'` for the dev server.
18+
19+
This aligns perfectly with our desired behavior: we want to run `dev:init` in any development context, and skip it in any production context. Using `process.env.NODE_ENV !== 'production'` as our condition is more accurate and robust than our previous `RWSDK_DEPLOY` flag. It correctly handles the default cases and also respects any user overrides of `NODE_ENV`.
20+
21+
This change is backward-compatible. For existing users who have `RWSDK_DEPLOY=1` in their scripts, the variable will simply be ignored by the plugin. However, for Windows users, the build was already broken; they will need to remove the variable from their `release` script to get the fix, which is a reasonable expectation. This will be noted for the pull request description.
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
# Worklog (2025-10-29): Windows CI Build Failures
2+
3+
## Executive Summary
4+
5+
The primary goal is to diagnose and fix a persistent `Rollup failed to resolve import` error that occurs during `pnpm build` on the Windows CI runner. This error seems to be related to Vite's tsconfig path alias resolution, specifically with the `vite-tsconfig-paths` plugin. The build succeeds when run manually in an interactive CI session within the temporary test directory but fails when executed as part of the automated E2E test suite. This suggests an environmental or contextual discrepancy.
6+
7+
## Investigation: `Rollup failed to resolve import`
8+
9+
The E2E tests for `hello-world` and `database-do` are failing on Windows with the following error:
10+
11+
```
12+
[vite:resolve] Rollup failed to resolve import "@/app/components/__SmokeTest" from "src/worker.tsx".
13+
file: D:/a/sdk/sdk/playground/hello-world-test-charmed-wombat-2a220268/src/worker.tsx
14+
```
15+
16+
The key observations are:
17+
- The error only occurs on Windows runners in the automated CI environment.
18+
- Manually running `pnpm build` in the temporary directory (e.g., `hello-world-test-charmed-wombat-2a220268`) created by the CI process succeeds without errors.
19+
- The error originates from the `vite-tsconfig-paths` plugin, which is responsible for resolving aliases defined in `tsconfig.json`.
20+
21+
This points to a subtle difference in how the plugin operates when invoked from our E2E test harness (`execa`) versus an interactive shell. The most likely culprits are differences in the current working directory, path normalization (e.g., handling of `/` vs `\`), or environment variables.
22+
23+
### Next Steps
24+
25+
To diagnose this, the immediate next step is to add instrumentation to the `vite-tsconfig-paths` plugin within the E2E test environment. By logging the inputs and outputs of its path resolution logic, we can pinpoint why the alias resolution is failing. I will modify the E2E test setup to temporarily patch the plugin's code with `console.log` statements before the build is executed.
26+
27+
## Update: The CI vs. Interactive Shell Discrepancy
28+
29+
A key insight is that the build succeeds when run manually in an interactive CI session (via `windows-debug.yml`) but fails in the automated `playground-e2e-tests.yml` workflow.
30+
31+
Upon reviewing the workflow files, a critical difference was identified:
32+
- The failing `playground-e2e-tests.yml` workflow was forcing all key steps to run with `shell: bash` on Windows runners.
33+
- The working interactive `windows-debug.yml` workflow uses the default Windows shell, PowerShell (`pwsh`).
34+
35+
This shell difference was the root cause of the path resolution errors. The `bash` environment on Windows (provided by Git) handles paths differently than native shells, causing issues when Node.js scripts spawned child processes for the build.
36+
37+
The fix was to modify `playground-e2e-tests.yml` to conditionally use `pwsh` on Windows runners, aligning the CI environment with the working interactive environment.

0 commit comments

Comments
 (0)