-
Notifications
You must be signed in to change notification settings - Fork 2.8k
infra: Add code-server development workflow with reliable file watching #10776
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Draft
brunobergher
wants to merge
2
commits into
main
Choose a base branch
from
bb/ext-web
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Draft
Changes from all commits
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,6 +1,10 @@ | ||
| version: "1.0" | ||
| port: 8443 | ||
|
|
||
| commands: | ||
| - name: Install dependencies | ||
| run: pnpm install | ||
| timeout: 60 | ||
|
|
||
| - name: Serve | ||
| run: pnpm serve |
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
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,94 @@ | ||
| #!/bin/bash | ||
| set -e | ||
|
|
||
| PORT=${PORT:-8443} | ||
|
|
||
| # Install code-server if missing | ||
| if ! command -v code-server &> /dev/null; then | ||
| echo "Installing code-server..." | ||
| curl -fsSL https://code-server.dev/install.sh | sh | ||
| fi | ||
|
|
||
| # Set up extension symlink for live development | ||
| EXT_DIR="$HOME/.local/share/code-server/extensions" | ||
| mkdir -p "$EXT_DIR" | ||
| ln -sfn "$(pwd)/src" "$EXT_DIR/roo-cline" | ||
|
|
||
| echo "==============================================" | ||
| echo "Setting up environment variables for watchers" | ||
| echo "==============================================" | ||
|
|
||
| # Enable polling for file watchers (helps with symlinks and various environments) | ||
| # Chokidar (used by Vite and now esbuild) | ||
| export CHOKIDAR_USEPOLLING=true | ||
| export CHOKIDAR_INTERVAL=1000 | ||
| echo "CHOKIDAR_USEPOLLING=$CHOKIDAR_USEPOLLING" | ||
| echo "CHOKIDAR_INTERVAL=$CHOKIDAR_INTERVAL" | ||
|
|
||
| # Watchpack (used by webpack) | ||
| export WATCHPACK_POLLING=true | ||
|
|
||
| # TypeScript watch mode - use polling instead of fs events | ||
| export TSC_WATCHFILE=UseFsEventsWithFallbackDynamicPolling | ||
| export TSC_WATCHDIRECTORY=UseFsEventsWithFallbackDynamicPolling | ||
|
|
||
| # Disable atomic writes so file watchers detect changes properly | ||
| export DISABLE_ATOMICWRITES=true | ||
|
|
||
| # Set development environment (from .vscode/launch.json) | ||
| export NODE_ENV=development | ||
| export VSCODE_DEBUG_MODE=true | ||
|
|
||
| # Trap to clean up all background processes on exit | ||
| cleanup() { | ||
| echo "Stopping all processes..." | ||
| jobs -p | xargs -r kill 2>/dev/null | ||
| } | ||
| trap cleanup EXIT INT TERM | ||
|
|
||
| # Build all workspace packages first | ||
| echo "" | ||
| echo "==============================================" | ||
| echo "Building workspace packages..." | ||
| echo "==============================================" | ||
| pnpm build | ||
|
|
||
| # Start code-server in background FIRST | ||
| echo "" | ||
| echo "==============================================" | ||
| echo "Starting code-server on port $PORT" | ||
| echo "Extension files are at: $(pwd)/src" | ||
| echo "Symlinked to: $EXT_DIR/roo-cline" | ||
| echo "==============================================" | ||
| code-server --auth none --bind-addr 0.0.0.0:${PORT} . & | ||
| CODE_SERVER_PID=$! | ||
|
|
||
| # Give code-server a moment to start | ||
| sleep 2 | ||
|
|
||
| # Start watchers with explicit env vars using env command | ||
| echo "" | ||
| echo "==============================================" | ||
| echo "Starting file watchers..." | ||
| echo "==============================================" | ||
|
|
||
| # Run webview watcher (custom chokidar-based script) | ||
| env CHOKIDAR_USEPOLLING=true CHOKIDAR_INTERVAL=1000 pnpm --filter @roo-code/vscode-webview dev:watch & | ||
|
|
||
| # Run bundle watcher (custom chokidar-based script) | ||
| env CHOKIDAR_USEPOLLING=true CHOKIDAR_INTERVAL=1000 pnpm --filter roo-cline watch:bundle & | ||
|
|
||
| # Run tsc watcher | ||
| env TSC_WATCHFILE=UseFsEventsWithFallbackDynamicPolling pnpm --filter roo-cline watch:tsc & | ||
|
|
||
| echo "" | ||
| echo "==============================================" | ||
| echo "All processes started!" | ||
| echo "code-server running at http://localhost:${PORT}" | ||
| echo "Watchers are running - file changes should trigger rebuilds" | ||
| echo "Press Ctrl+C to stop all processes" | ||
| echo "==============================================" | ||
| echo "" | ||
|
|
||
| # Wait for all background processes | ||
| wait |
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
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
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
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,111 @@ | ||
| import chokidar from "chokidar" | ||
| import { exec } from "child_process" | ||
| import path from "path" | ||
| import { fileURLToPath } from "url" | ||
|
|
||
| const __filename = fileURLToPath(import.meta.url) | ||
| const __dirname = path.dirname(__filename) | ||
|
|
||
| const usePolling = process.env.CHOKIDAR_USEPOLLING === "true" | ||
| const pollInterval = parseInt(process.env.CHOKIDAR_INTERVAL || "1000", 10) | ||
|
|
||
| console.log(`[webview] ========================================`) | ||
| console.log(`[webview] Starting watch mode`) | ||
| console.log(`[webview] Polling: ${usePolling}, Interval: ${pollInterval}ms`) | ||
| console.log(`[webview] Watching: ${path.join(__dirname, "src")}`) | ||
| console.log(`[webview] ========================================`) | ||
|
|
||
| let buildInProgress = false | ||
| let pendingBuild = false | ||
|
|
||
| const runBuild = () => { | ||
| if (buildInProgress) { | ||
| pendingBuild = true | ||
| return | ||
| } | ||
|
|
||
| buildInProgress = true | ||
| console.log(`[webview] Building...`) | ||
|
|
||
| exec("pnpm vite build", { cwd: __dirname }, (error, stdout, stderr) => { | ||
| buildInProgress = false | ||
|
|
||
| if (error) { | ||
| console.error(`[webview] Build failed:`, error.message) | ||
| if (stderr) console.error(stderr) | ||
| } else { | ||
| console.log(`[webview] Build complete`) | ||
| } | ||
|
|
||
| if (pendingBuild) { | ||
| pendingBuild = false | ||
| runBuild() | ||
| } | ||
| }) | ||
| } | ||
|
|
||
| const srcDir = path.join(__dirname, "src") | ||
| console.log(`[webview] srcDir: ${srcDir}`) | ||
|
|
||
| const watcher = chokidar.watch(srcDir, { | ||
| ignored: (filePath) => { | ||
| const relativePath = path.relative(srcDir, filePath) | ||
| return relativePath.includes("node_modules") || | ||
| relativePath.endsWith(".spec.ts") || | ||
| relativePath.endsWith(".spec.tsx") || | ||
| relativePath.endsWith(".test.ts") || | ||
| relativePath.endsWith(".test.tsx") | ||
| }, | ||
| persistent: true, | ||
| usePolling, | ||
| interval: pollInterval, | ||
| ignoreInitial: false, // Count files during initial scan | ||
| depth: 10, | ||
| }) | ||
|
|
||
| let fileCount = 0 | ||
| let isReady = false | ||
|
|
||
| let debounceTimeout = null | ||
| watcher.on("change", (filePath) => { | ||
| if (!isReady) return | ||
| if (debounceTimeout) clearTimeout(debounceTimeout) | ||
| debounceTimeout = setTimeout(() => { | ||
| console.log(`[webview] File changed: ${filePath}`) | ||
| runBuild() | ||
| }, 200) | ||
| }) | ||
|
|
||
| watcher.on("add", (filePath) => { | ||
| if (!isReady) { | ||
| fileCount++ | ||
| return | ||
| } | ||
| if (debounceTimeout) clearTimeout(debounceTimeout) | ||
| debounceTimeout = setTimeout(() => { | ||
| console.log(`[webview] File added: ${filePath}`) | ||
| runBuild() | ||
| }, 200) | ||
| }) | ||
|
|
||
| watcher.on("unlink", (filePath) => { | ||
| if (!isReady) return | ||
| if (debounceTimeout) clearTimeout(debounceTimeout) | ||
| debounceTimeout = setTimeout(() => { | ||
| console.log(`[webview] File deleted: ${filePath}`) | ||
| runBuild() | ||
| }, 200) | ||
| }) | ||
|
|
||
| watcher.on("ready", () => { | ||
| isReady = true | ||
| console.log(`[webview] ========================================`) | ||
| console.log(`[webview] Watcher ready!`) | ||
| console.log(`[webview] Watching ${fileCount} files`) | ||
| console.log(`[webview] Listening for changes...`) | ||
| console.log(`[webview] ========================================`) | ||
| }) | ||
|
|
||
| watcher.on("error", (error) => { | ||
| console.error(`[webview] Watcher error:`, error) | ||
| }) |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The manual
[esbuild-problem-matcher#onStart]and[esbuild-problem-matcher#onEnd]markers here are redundant since theesbuild-problem-matcherplugin (lines 80-94) already emits these markers via esbuild'sbuild.onStart()andbuild.onEnd()hooks. This causes duplicate markers in the output which could confuse VS Code problem matchers that expect balanced start/end pairs.Fix it with Roo Code or mention @roomote and request a fix.