Add configurable working directory for dev server scripts (Vibe Kanban) (#1559)

* The implementation is complete. Here's a summary of all the changes made:

## Summary

Added the ability for users to specify a working directory for dev server scripts:

### Files Changed:

1. **Database migration** - `crates/db/migrations/20251216000000_add_dev_script_working_dir_to_projects.sql`
   - Added `dev_script_working_dir TEXT DEFAULT ''` column

2. **Rust model** - `crates/db/src/models/project.rs`
   - Added `dev_script_working_dir` field to `Project` and `UpdateProject` structs
   - Updated all SQL queries

3. **Dev server execution** - `crates/server/src/routes/task_attempts.rs`
   - `start_dev_server` now passes `project.dev_script_working_dir` to the script executor

4. **Backfill logic** - `crates/services/src/services/container.rs`
   - Changed `backfill_repo_names` to set `dev_script_working_dir` instead of prepending `cd ./repo &&`

5. **Frontend UI** - `frontend/src/pages/settings/ProjectSettings.tsx`
   - Added input field for "Dev Server Working Directory"

6. **Translations** - `frontend/src/i18n/locales/en/settings.json`
   - Added `devWorkingDir` label, placeholder, and helper text

7. **TypeScript types** - `shared/types.ts`
   - Regenerated with `dev_script_working_dir` field

* Cleanup script changes for task attempt 83423e2d-0d45-47fb-a6e4-dd91a2140f91

* Both packages compile successfully. The fix is complete:

1. **`project.rs`**: Removed `.or()` fallback for `dev_script` and `dev_script_working_dir` so `None` now clears the field
2. **`container.rs`**: Updated backfill to explicitly pass the existing project name instead of `None`

* Done. I've completed both review tasks:

1. Removed the comment from `container.rs` line 384
2. Added `devWorkingDir` translations to all four language files (es, ja, ko, zh-Hans) with:
   - `label`: The field label
   - `placeholder`: Example placeholder text
   - `helper`: Description of what the field does

I also updated the `dev.helper` text in each language to reference the new working directory option instead of suggesting users manually `cd` into the repo directory.

* Done. Removed both comments:
1. Removed the comment from the migration file
2. Removed the comment from `task_attempts.rs` line 1267

* Fixed. The TypeScript error in `NoServerContent.tsx` has been resolved by adding `dev_script_working_dir: null` to the `UpdateProject` data. All checks pass:

-  `npm run format` - completed
-  `npm run lint` - passed (frontend and backend)
-  `npx tsc --noEmit` - passed

* The Korean and Chinese translations already had the updated copy without the `cd` reference. The Spanish and Japanese were updated. All the translations now have the proper helper text that references the working directory field instead of telling users to manually `cd` into the repo.

* Done. I've removed the `cd my_website` line from both the Windows and Unix script placeholder examples in `scriptPlaceholders.ts`. Now the placeholder examples just show `npm run dev` without the `cd` command, since users can specify the working directory separately.
This commit is contained in:
Alex Netsch
2025-12-16 12:19:15 +00:00
committed by GitHub
parent 22ff27d8fd
commit ec8666da74
19 changed files with 162 additions and 52 deletions

View File

@@ -88,7 +88,10 @@ export function NoServerContent({
}
updateProject.mutate(
{ projectId: project.id, data: { name: null, dev_script: script } },
{
projectId: project.id,
data: { name: null, dev_script: script, dev_script_working_dir: null },
},
{
onSuccess: () => {
setIsEditingExistingScript(false);

View File

@@ -342,7 +342,12 @@
},
"dev": {
"label": "Dev Server Script",
"helper": "Starts a development server from task attempts. Scripts execute from the workspace directory (one level above each repo's worktree), so cd into the repo first (e.g., cd my-repo && pnpm run dev)."
"helper": "Starts a development server from task attempts. Scripts execute from the workspace directory (one level above each repo's worktree) unless a working directory is specified below."
},
"devWorkingDir": {
"label": "Dev Server Working Directory",
"placeholder": "e.g., my-repo",
"helper": "The directory to run the dev server script from, relative to the workspace root. Leave empty to run from the workspace root."
},
"cleanup": {
"label": "Cleanup Script",

View File

@@ -342,7 +342,12 @@
},
"dev": {
"label": "Script del Servidor de Desarrollo",
"helper": "Inicia un servidor de desarrollo desde los intentos de tarea. Los scripts se ejecutan desde el directorio del workspace (un nivel arriba del worktree de cada repositorio), así que primero entra al directorio del repositorio (ej., cd mi-repo && pnpm run dev)."
"helper": "Inicia un servidor de desarrollo desde los intentos de tarea. Los scripts se ejecutan desde el directorio del workspace (un nivel arriba del worktree de cada repositorio) a menos que se especifique un directorio de trabajo abajo."
},
"devWorkingDir": {
"label": "Directorio de Trabajo del Servidor de Desarrollo",
"placeholder": "ej., mi-repo",
"helper": "El directorio desde el cual ejecutar el script del servidor de desarrollo, relativo a la raíz del workspace. Déjalo vacío para ejecutar desde la raíz del workspace."
},
"cleanup": {
"label": "Script de Limpieza",

View File

@@ -342,7 +342,12 @@
},
"dev": {
"label": "開発サーバースクリプト",
"helper": "タスク試行から開発サーバーを起動します。スクリプトはワークスペースディレクトリ各リポジトリのワークツリーの1つ上のレベルから実行されるため、まずリポジトリディレクトリに移動してくださいcd my-repo && pnpm run dev。"
"helper": "タスク試行から開発サーバーを起動します。スクリプトは、下記で作業ディレクトリが指定されていない限り、ワークスペースディレクトリ各リポジトリのワークツリーの1つ上のレベルから実行されます。"
},
"devWorkingDir": {
"label": "開発サーバー作業ディレクトリ",
"placeholder": "例my-repo",
"helper": "開発サーバースクリプトを実行するディレクトリ。ワークスペースルートからの相対パス。空欄にするとワークスペースルートから実行します。"
},
"cleanup": {
"label": "クリーンアップスクリプト",

View File

@@ -342,7 +342,12 @@
},
"dev": {
"label": "개발 서버 스크립트",
"helper": "작업 시도에서 개발 서버를 시작합니다. 스크립트는 워크스페이스 디렉토리(각 저장소의 워크트리보다 한 단계 위)에서 실행되므로 먼저 저장소 디렉토리로 이동하세요 (예: cd my-repo && pnpm run dev)."
"helper": "작업 시도에서 개발 서버를 시작합니다. 스크립트는 아래에서 작업 디렉토리를 지정하지 않는 한 워크스페이스 디렉토리(각 저장소의 워크트리보다 한 단계 위)에서 실행됩니다."
},
"devWorkingDir": {
"label": "개발 서버 작업 디렉토리",
"placeholder": "예: my-repo",
"helper": "개발 서버 스크립트를 실행할 디렉토리로, 워크스페이스 루트 기준 상대 경로입니다. 비워두면 워크스페이스 루트에서 실행됩니다."
},
"cleanup": {
"label": "정리 스크립트",

View File

@@ -342,7 +342,12 @@
},
"dev": {
"label": "开发服务器脚本",
"helper": "从任务尝试中启动开发服务器。脚本从工作区目录(每个仓库工作树的上一级)执行,因此请先 cd 进入仓库目录例如cd my-repo && pnpm run dev。"
"helper": "从任务尝试中启动开发服务器。脚本从工作区目录(每个仓库工作树的上一级)执行,除非在下方指定了工作目录。"
},
"devWorkingDir": {
"label": "开发服务器工作目录",
"placeholder": "例如my-repo",
"helper": "运行开发服务器脚本的目录,相对于工作区根目录。留空则从工作区根目录运行。"
},
"cleanup": {
"label": "清理脚本",

View File

@@ -36,6 +36,7 @@ import type { Project, ProjectRepo, Repo, UpdateProject } from 'shared/types';
interface ProjectFormState {
name: string;
dev_script: string;
dev_script_working_dir: string;
}
interface RepoScriptsFormState {
@@ -49,6 +50,7 @@ function projectToFormState(project: Project): ProjectFormState {
return {
name: project.name,
dev_script: project.dev_script ?? '',
dev_script_working_dir: project.dev_script_working_dir ?? '',
};
}
@@ -390,6 +392,7 @@ export function ProjectSettings() {
const updateData: UpdateProject = {
name: draft.name.trim(),
dev_script: draft.dev_script.trim() || null,
dev_script_working_dir: draft.dev_script_working_dir.trim() || null,
};
updateProject.mutate({
@@ -583,6 +586,26 @@ export function ProjectSettings() {
</p>
</div>
<div className="space-y-2">
<Label htmlFor="dev-script-working-dir">
{t('settings.projects.scripts.devWorkingDir.label')}
</Label>
<Input
id="dev-script-working-dir"
value={draft.dev_script_working_dir}
onChange={(e) =>
updateDraft({ dev_script_working_dir: e.target.value })
}
placeholder={t(
'settings.projects.scripts.devWorkingDir.placeholder'
)}
className="font-mono"
/>
<p className="text-sm text-muted-foreground">
{t('settings.projects.scripts.devWorkingDir.helper')}
</p>
</div>
{/* Save Button */}
<div className="flex items-center justify-between pt-4 border-t">
{hasUnsavedProjectChanges ? (

View File

@@ -15,7 +15,6 @@ class WindowsScriptPlaceholderStrategy implements ScriptPlaceholderStrategy {
npm install
REM Add any setup commands here...`,
dev: `@echo off
cd my_website
npm run dev
REM Add dev server start command here...`,
cleanup: `@echo off
@@ -32,7 +31,6 @@ class UnixScriptPlaceholderStrategy implements ScriptPlaceholderStrategy {
npm install
# Add any setup commands here...`,
dev: `#!/bin/bash
cd my_website
npm run dev
# Add dev server start command here...`,
cleanup: `#!/bin/bash