Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
15 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions registry/mavrickrishi/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,4 @@ participating in LFX CNCF programs, and helping the developer community grow.
## Modules

- **aws-ami-snapshot**: Create and manage AMI snapshots for Coder workspaces with restore capabilities
- [auto-start-dev-server](modules/auto-start-dev-server/README.md) - Automatically detect and start development servers for various project types
233 changes: 233 additions & 0 deletions registry/mavrickrishi/modules/auto-start-dev-server/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,233 @@
---
display_name: Auto-Start Development Servers
description: Automatically detect and start development servers for various project types
icon: ../../../../.icons/server.svg
verified: false
tags:
- development
- automation
- servers
- nodejs
- python
- java
- go
- rust
- php
- rails
- django
- flask
- spring-boot
- dotnet
---

# Auto-Start Development Servers

Automatically detect and start development servers for various project types when a workspace starts. This module scans your workspace for common project structures and starts the appropriate development servers in the background without manual intervention.

```tf
module "auto_start_dev_servers" {
source = "registry.coder.com/mavrickrishi/auto-start-dev-server/coder"
version = "1.0.0"
agent_id = coder_agent.main.id
}
```

## Features

- **Multi-language support**: Detects and starts servers for Node.js, Python (Django/Flask), Ruby (Rails), Java (Spring Boot), Go, PHP, Rust, and .NET projects
- **Smart script prioritization**: Prioritizes `dev` scripts over `start` scripts for better development experience
- **Intelligent frontend detection**: Automatically identifies frontend projects (React, Vue, Angular, Next.js, Nuxt, Svelte, Vite) and prioritizes them for preview apps
- **Devcontainer integration**: Respects custom start commands defined in `.devcontainer/devcontainer.json`
- **Configurable scanning**: Adjustable directory scan depth and project type toggles
- **Non-blocking startup**: Servers start in the background with configurable startup delay
- **Comprehensive logging**: All server output and detection results logged to a central file
- **Smart detection**: Uses project-specific files and configurations to identify project types
- **Integrated live preview**: Automatically creates a preview app for the primary frontend project

## Supported Project Types

| Framework/Language | Detection Files | Start Commands (in priority order) |
| ------------------ | -------------------------------------------- | ----------------------------------------------------- |
| **Node.js/npm** | `package.json` | `npm run dev`, `npm run serve`, `npm start` (or yarn) |
| **Ruby on Rails** | `Gemfile` with rails gem | `bundle exec rails server` |
| **Django** | `manage.py` | `python manage.py runserver` |
| **Flask** | `requirements.txt` with Flask | `python app.py/main.py/run.py` |
| **Spring Boot** | `pom.xml` or `build.gradle` with spring-boot | `mvn spring-boot:run`, `gradle bootRun` |
| **Go** | `go.mod` | `go run main.go` |
| **PHP** | `composer.json` | `php -S 0.0.0.0:8080` |
| **Rust** | `Cargo.toml` | `cargo run` |
| **.NET** | `*.csproj` | `dotnet run` |

## Usage

```hcl
module "auto_start_dev_servers" {
source = "./modules/auto-start-dev-server"
agent_id = coder_agent.main.id

# Optional: Configure which project types to detect
enable_npm = true
enable_rails = true
enable_django = true
enable_flask = true
enable_spring_boot = true
enable_go = true
enable_php = true
enable_rust = true
enable_dotnet = true

# Optional: Enable devcontainer.json integration
enable_devcontainer = true

# Optional: Workspace directory to scan (supports environment variables)
workspace_directory = "$HOME"

# Optional: Directory scan depth (1-5)
scan_depth = 2

# Optional: Startup delay in seconds
startup_delay = 10

# Optional: Log file path
log_path = "/tmp/dev-servers.log"

# Optional: Enable automatic preview app (default: true)
enable_preview_app = true
}
```

## Configuration Options

### Required Variables

- `agent_id` (string): The ID of a Coder agent

## Devcontainer Integration

When `enable_devcontainer` is true, the module will check for `.devcontainer/devcontainer.json` files and look for custom start commands in the VS Code settings:

```json
{
"customizations": {
"vscode": {
"settings": {
"npm.script.start": "npm run custom-dev-command"
}
}
}
}
```

If found, the custom command will be used instead of the default project detection logic.

## Monitoring and Debugging

### View Logs

```bash
# Real-time log viewing
tail -f /tmp/dev-servers.log

# View full log
cat /tmp/dev-servers.log
```

## Security Considerations

- Servers are started with the same user permissions as the Coder agent
- All project detection is read-only (only checks for existence of files)
- Server processes run in the background and inherit workspace environment
- Log files contain server output which may include sensitive information

## Troubleshooting

### Common Issues

1. **No servers starting**: Check that project files exist and scan depth covers your project directories
2. **Permission denied**: Ensure the script has execute permissions and dependencies are installed
3. **Wrong directory**: Verify `workspace_directory` path is correct and accessible
4. **Missing dependencies**: Install required runtimes (node, python, java, etc.) in your base image

## Live Preview App

The module automatically creates a "Live Preview" app in your Coder workspace that intelligently selects the best project for preview:

- **Smart frontend detection**: Prioritizes frontend projects (React, Vue, Angular, etc.) over backend services
- **Automatic detection**: Uses the port from the primary frontend project, or first detected project if no frontend found
- **Dynamic URL**: Points to `http://localhost:{detected_port}`
- **Monorepo friendly**: In multi-project setups, automatically selects the most likely UI project
- **Configurable**: Can be disabled by setting `enable_preview_app = false`
- **Fallback**: Defaults to port 3000 if no projects are detected

## Module Outputs

| Output | Description | Example Value |
| ------------------------ | ---------------------------------------------------------------------- | --------------------------------- |
| `detected_projects_file` | Path to JSON file with detected projects (includes `is_frontend` flag) | `/tmp/detected-projects.json` |
| `log_path` | Path to dev server log file | `/tmp/dev-servers.log` |
| `common_ports` | Map of default ports by project type | `{nodejs=3000, django=8000, ...}` |
| `preview_url` | URL of the live preview app | `http://localhost:3000` |
| `detected_port` | Port of the first detected project | `3000` |

## Examples

### Basic Usage

```hcl
module "auto_start" {
source = "./modules/auto-start-dev-server"
agent_id = coder_agent.main.id
}
```

### Disable Preview App

```hcl
module "auto_start" {
source = "./modules/auto-start-dev-server"
agent_id = coder_agent.main.id

# Disable automatic preview app creation
enable_preview_app = false
}
```

### Selective Project Types

```hcl
module "auto_start" {
source = "./modules/auto-start-dev-server"
agent_id = coder_agent.main.id

# Only enable web development projects
enable_npm = true
enable_rails = true
enable_django = true
enable_flask = true

# Disable other project types
enable_spring_boot = false
enable_go = false
enable_php = false
enable_rust = false
enable_dotnet = false
}
```

### Deep Workspace Scanning

```hcl
module "auto_start" {
source = "./modules/auto-start-dev-server"
agent_id = coder_agent.main.id

workspace_directory = "/workspaces"
scan_depth = 3
startup_delay = 5
log_path = "/var/log/dev-servers.log"
}
```

## License

This module is provided under the same license as the Coder Registry.
109 changes: 109 additions & 0 deletions registry/mavrickrishi/modules/auto-start-dev-server/main.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
import { describe, expect, it } from "bun:test";
import {
runTerraformApply,
runTerraformInit,
testRequiredVariables,
} from "~test";

describe("auto-start-dev-server", async () => {
await runTerraformInit(import.meta.dir);

testRequiredVariables(import.meta.dir, {
agent_id: "test-agent-123",
});

it("validates scan_depth range", () => {
const t1 = async () => {
await runTerraformApply(import.meta.dir, {
agent_id: "test-agent-123",
scan_depth: "0",
});
};
expect(t1).toThrow("Scan depth must be between 1 and 5");

const t2 = async () => {
await runTerraformApply(import.meta.dir, {
agent_id: "test-agent-123",
scan_depth: "6",
});
};
expect(t2).toThrow("Scan depth must be between 1 and 5");
});

it("applies successfully with default values", async () => {
await runTerraformApply(import.meta.dir, {
agent_id: "test-agent-123",
});
});

it("applies successfully with all project types enabled", async () => {
await runTerraformApply(import.meta.dir, {
agent_id: "test-agent-123",
enable_npm: "true",
enable_rails: "true",
enable_django: "true",
enable_flask: "true",
enable_spring_boot: "true",
enable_go: "true",
enable_php: "true",
enable_rust: "true",
enable_dotnet: "true",
enable_devcontainer: "true",
});
});

it("applies successfully with all project types disabled", async () => {
await runTerraformApply(import.meta.dir, {
agent_id: "test-agent-123",
enable_npm: "false",
enable_rails: "false",
enable_django: "false",
enable_flask: "false",
enable_spring_boot: "false",
enable_go: "false",
enable_php: "false",
enable_rust: "false",
enable_dotnet: "false",
enable_devcontainer: "false",
});
});

it("applies successfully with custom configuration", async () => {
await runTerraformApply(import.meta.dir, {
agent_id: "test-agent-123",
workspace_directory: "/custom/workspace",
scan_depth: "3",
startup_delay: "5",
log_path: "/var/log/custom-dev-servers.log",
display_name: "Custom Dev Server Startup",
});
});

it("validates scan_depth boundary values", async () => {
// Test valid boundary values
await runTerraformApply(import.meta.dir, {
agent_id: "test-agent-123",
scan_depth: "1",
});

await runTerraformApply(import.meta.dir, {
agent_id: "test-agent-123",
scan_depth: "5",
});
});

it("applies with selective project type configuration", async () => {
await runTerraformApply(import.meta.dir, {
agent_id: "test-agent-123",
enable_npm: "true",
enable_django: "true",
enable_go: "true",
enable_rails: "false",
enable_flask: "false",
enable_spring_boot: "false",
enable_php: "false",
enable_rust: "false",
enable_dotnet: "false",
});
});
});
Loading