From a7c697ddc5bfe0e4ad98d2a396dd52645f25e39a Mon Sep 17 00:00:00 2001 From: mavrick-1 Date: Sun, 10 Aug 2025 01:56:53 +0530 Subject: [PATCH 1/9] feat: add auto-start development server module with multi-language support and configuration options --- .../modules/auto-start-dev-server/README.md | 240 +++++++++++++ .../auto-start-dev-server/main.test.ts | 109 ++++++ .../modules/auto-start-dev-server/main.tf | 132 +++++++ .../modules/auto-start-dev-server/run.sh | 327 ++++++++++++++++++ 4 files changed, 808 insertions(+) create mode 100644 registry/mavrickrishi/modules/auto-start-dev-server/README.md create mode 100644 registry/mavrickrishi/modules/auto-start-dev-server/main.test.ts create mode 100644 registry/mavrickrishi/modules/auto-start-dev-server/main.tf create mode 100755 registry/mavrickrishi/modules/auto-start-dev-server/run.sh diff --git a/registry/mavrickrishi/modules/auto-start-dev-server/README.md b/registry/mavrickrishi/modules/auto-start-dev-server/README.md new file mode 100644 index 000000000..ddb8d5e25 --- /dev/null +++ b/registry/mavrickrishi/modules/auto-start-dev-server/README.md @@ -0,0 +1,240 @@ +# 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. + +## 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 +- **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 + +## Supported Project Types + +| Framework/Language | Detection Files | Start Commands | +|-------------------|----------------|----------------| +| **Node.js/npm** | `package.json` | `npm start`, `npm run dev`, `yarn start` | +| **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" +} +``` + +## Configuration Options + +### Required Variables + +- `agent_id` (string): The ID of a Coder agent + +### Optional Variables + +| Variable | Type | Default | Description | +|----------|------|---------|-------------| +| `workspace_directory` | string | `"$HOME"` | Directory to scan for projects | +| `enable_npm` | bool | `true` | Enable Node.js/npm project detection | +| `enable_rails` | bool | `true` | Enable Ruby on Rails project detection | +| `enable_django` | bool | `true` | Enable Django project detection | +| `enable_flask` | bool | `true` | Enable Flask project detection | +| `enable_spring_boot` | bool | `true` | Enable Spring Boot project detection | +| `enable_go` | bool | `true` | Enable Go project detection | +| `enable_php` | bool | `true` | Enable PHP project detection | +| `enable_rust` | bool | `true` | Enable Rust project detection | +| `enable_dotnet` | bool | `true` | Enable .NET project detection | +| `enable_devcontainer` | bool | `true` | Enable devcontainer.json integration | +| `log_path` | string | `"/tmp/dev-servers.log"` | Path for logging output | +| `scan_depth` | number | `2` | Maximum directory depth to scan (1-5) | +| `startup_delay` | number | `10` | Delay in seconds before starting servers | +| `display_name` | string | `"Auto-Start Dev Servers"` | Display name for the script | + +## 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 + +### Check Running Servers + +```bash +# View all running development servers +ps aux | grep -E "(npm|rails|python|java|go|php|cargo|dotnet)" +``` + +### View Logs + +```bash +# Real-time log viewing +tail -f /tmp/dev-servers.log + +# View full log +cat /tmp/dev-servers.log +``` + +### Manual Testing + +```bash +# Test the detection script manually +cd /path/to/workspace +bash /path/to/run.sh +``` + +## Example Projects + +### Node.js Project Structure +``` +my-app/ +├── package.json # ← Detected +├── src/ +└── node_modules/ +``` + +### Django Project Structure +``` +my-project/ +├── manage.py # ← Detected +├── myapp/ +└── requirements.txt +``` + +### Spring Boot Project Structure +``` +my-service/ +├── pom.xml # ← Detected (Maven) +├── src/ +└── target/ +``` + +## 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 + +### Debug Mode + +Enable verbose logging by modifying the script to include debug output: + +```bash +# Add to beginning of run.sh for debugging +set -x # Enable bash debug mode +``` + +## Examples + +### Basic Usage +```hcl +module "auto_start" { + source = "./modules/auto-start-dev-server" + agent_id = coder_agent.main.id +} +``` + +### 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" +} +``` + +## Contributing + +This module is part of the Coder Registry. To contribute improvements: + +1. Test your changes thoroughly across different project types +2. Update documentation for any new features +3. Ensure backward compatibility with existing configurations +4. Add appropriate error handling and logging + +## License + +This module is provided under the same license as the Coder Registry. \ No newline at end of file diff --git a/registry/mavrickrishi/modules/auto-start-dev-server/main.test.ts b/registry/mavrickrishi/modules/auto-start-dev-server/main.test.ts new file mode 100644 index 000000000..c37a37a13 --- /dev/null +++ b/registry/mavrickrishi/modules/auto-start-dev-server/main.test.ts @@ -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", + }); + }); +}); \ No newline at end of file diff --git a/registry/mavrickrishi/modules/auto-start-dev-server/main.tf b/registry/mavrickrishi/modules/auto-start-dev-server/main.tf new file mode 100644 index 000000000..984739982 --- /dev/null +++ b/registry/mavrickrishi/modules/auto-start-dev-server/main.tf @@ -0,0 +1,132 @@ +terraform { + required_version = ">= 1.0" + + required_providers { + coder = { + source = "coder/coder" + version = ">= 2.5" + } + } +} + +variable "agent_id" { + type = string + description = "The ID of a Coder agent." +} + +variable "workspace_directory" { + type = string + description = "The directory to scan for development projects." + default = "$HOME" +} + +variable "enable_npm" { + type = bool + description = "Enable auto-detection and startup of npm projects." + default = true +} + +variable "enable_rails" { + type = bool + description = "Enable auto-detection and startup of Rails projects." + default = true +} + +variable "enable_django" { + type = bool + description = "Enable auto-detection and startup of Django projects." + default = true +} + +variable "enable_flask" { + type = bool + description = "Enable auto-detection and startup of Flask projects." + default = true +} + +variable "enable_spring_boot" { + type = bool + description = "Enable auto-detection and startup of Spring Boot projects." + default = true +} + +variable "enable_go" { + type = bool + description = "Enable auto-detection and startup of Go projects." + default = true +} + +variable "enable_php" { + type = bool + description = "Enable auto-detection and startup of PHP projects." + default = true +} + +variable "enable_rust" { + type = bool + description = "Enable auto-detection and startup of Rust projects." + default = true +} + +variable "enable_dotnet" { + type = bool + description = "Enable auto-detection and startup of .NET projects." + default = true +} + +variable "enable_devcontainer" { + type = bool + description = "Enable integration with devcontainer.json configuration." + default = true +} + +variable "log_path" { + type = string + description = "The path to log development server output to." + default = "/tmp/dev-servers.log" +} + +variable "scan_depth" { + type = number + description = "Maximum directory depth to scan for projects (1-5)." + default = 2 + validation { + condition = var.scan_depth >= 1 && var.scan_depth <= 5 + error_message = "Scan depth must be between 1 and 5." + } +} + +variable "startup_delay" { + type = number + description = "Delay in seconds before starting dev servers (allows other setup to complete)." + default = 10 +} + +variable "display_name" { + type = string + description = "Display name for the auto-start dev server script." + default = "Auto-Start Dev Servers" +} + +resource "coder_script" "auto_start_dev_server" { + agent_id = var.agent_id + display_name = var.display_name + icon = "/icon/server.svg" + script = templatefile("${path.module}/run.sh", { + WORKSPACE_DIR = var.workspace_directory + ENABLE_NPM = var.enable_npm + ENABLE_RAILS = var.enable_rails + ENABLE_DJANGO = var.enable_django + ENABLE_FLASK = var.enable_flask + ENABLE_SPRING_BOOT = var.enable_spring_boot + ENABLE_GO = var.enable_go + ENABLE_PHP = var.enable_php + ENABLE_RUST = var.enable_rust + ENABLE_DOTNET = var.enable_dotnet + ENABLE_DEVCONTAINER = var.enable_devcontainer + LOG_PATH = var.log_path + SCAN_DEPTH = var.scan_depth + STARTUP_DELAY = var.startup_delay + }) + run_on_start = true +} \ No newline at end of file diff --git a/registry/mavrickrishi/modules/auto-start-dev-server/run.sh b/registry/mavrickrishi/modules/auto-start-dev-server/run.sh new file mode 100755 index 000000000..6c85c5bf4 --- /dev/null +++ b/registry/mavrickrishi/modules/auto-start-dev-server/run.sh @@ -0,0 +1,327 @@ +#!/usr/bin/env bash + +set -e + +# Color codes for output +BOLD='\033[0;1m' +GREEN='\033[0;32m' +YELLOW='\033[0;33m' +BLUE='\033[0;34m' +RED='\033[0;31m' +RESET='\033[0m' + +echo -e "$${BOLD}🚀 Auto-Start Development Servers$${RESET}" +echo "Workspace Directory: ${WORKSPACE_DIR}" +echo "Log Path: ${LOG_PATH}" +echo "Scan Depth: ${SCAN_DEPTH}" + +# Wait for startup delay to allow other setup to complete +if [ "${STARTUP_DELAY}" -gt 0 ]; then + echo -e "$${YELLOW}⏳ Waiting ${STARTUP_DELAY} seconds for system initialization...$${RESET}" + sleep "${STARTUP_DELAY}" +fi + +# Initialize log file +echo "=== Auto-Start Dev Servers Log ===" > "${LOG_PATH}" +echo "Started at: $(date)" >> "${LOG_PATH}" + +# Function to log messages +log_message() { + echo -e "$1" + echo "$1" >> "${LOG_PATH}" +} + +# Function to detect and start npm/yarn projects +detect_npm_projects() { + if [ "${ENABLE_NPM}" != "true" ]; then + return + fi + + log_message "$${BLUE}🔍 Scanning for Node.js/npm projects...$${RESET}" + + # Use find with maxdepth to respect scan depth + while IFS= read -r -d '' package_json; do + project_dir=$(dirname "$package_json") + log_message "$${GREEN}📦 Found Node.js project: $project_dir$${RESET}" + + cd "$project_dir" + + # Check devcontainer.json for custom start command first + if [ "${ENABLE_DEVCONTAINER}" = "true" ] && [ -f ".devcontainer/devcontainer.json" ]; then + start_cmd=$(jq -r '.customizations.vscode.settings."npm.script.start" // empty' ".devcontainer/devcontainer.json" 2>/dev/null) + if [ -n "$start_cmd" ]; then + log_message "$${YELLOW}🐳 Using devcontainer start command: $start_cmd$${RESET}" + nohup bash -c "$start_cmd" >> "${LOG_PATH}" 2>&1 & + continue + fi + fi + + # Check package.json for start script + if [ -f "package.json" ] && command -v jq &> /dev/null; then + start_script=$(jq -r '.scripts.start // empty' package.json) + dev_script=$(jq -r '.scripts.dev // empty' package.json) + + if [ -n "$start_script" ]; then + log_message "$${GREEN}🟢 Starting npm project with 'npm start' in $project_dir$${RESET}" + nohup npm start >> "${LOG_PATH}" 2>&1 & + elif [ -n "$dev_script" ]; then + log_message "$${GREEN}🟢 Starting npm project with 'npm run dev' in $project_dir$${RESET}" + nohup npm run dev >> "${LOG_PATH}" 2>&1 & + fi + elif [ -f "yarn.lock" ] && command -v yarn &> /dev/null; then + log_message "$${GREEN}🟢 Starting yarn project with 'yarn start' in $project_dir$${RESET}" + nohup yarn start >> "${LOG_PATH}" 2>&1 & + fi + + done < <(find "${WORKSPACE_DIR}" -maxdepth "${SCAN_DEPTH}" -name "package.json" -type f -print0) +} + +# Function to detect and start Rails projects +detect_rails_projects() { + if [ "${ENABLE_RAILS}" != "true" ]; then + return + fi + + log_message "$${BLUE}🔍 Scanning for Ruby on Rails projects...$${RESET}" + + while IFS= read -r -d '' gemfile; do + project_dir=$(dirname "$gemfile") + log_message "$${GREEN}💎 Found Rails project: $project_dir$${RESET}" + + cd "$project_dir" + + # Check if it's actually a Rails project + if grep -q "gem ['\"]rails['\"]" Gemfile 2>/dev/null; then + log_message "$${GREEN}🟢 Starting Rails server in $project_dir$${RESET}" + nohup bundle exec rails server >> "${LOG_PATH}" 2>&1 & + fi + + done < <(find "${WORKSPACE_DIR}" -maxdepth "${SCAN_DEPTH}" -name "Gemfile" -type f -print0) +} + +# Function to detect and start Django projects +detect_django_projects() { + if [ "${ENABLE_DJANGO}" != "true" ]; then + return + fi + + log_message "$${BLUE}🔍 Scanning for Django projects...$${RESET}" + + while IFS= read -r -d '' manage_py; do + project_dir=$(dirname "$manage_py") + log_message "$${GREEN}🐍 Found Django project: $project_dir$${RESET}" + + cd "$project_dir" + log_message "$${GREEN}🟢 Starting Django development server in $project_dir$${RESET}" + nohup python manage.py runserver 0.0.0.0:8000 >> "${LOG_PATH}" 2>&1 & + + done < <(find "${WORKSPACE_DIR}" -maxdepth "${SCAN_DEPTH}" -name "manage.py" -type f -print0) +} + +# Function to detect and start Flask projects +detect_flask_projects() { + if [ "${ENABLE_FLASK}" != "true" ]; then + return + fi + + log_message "$${BLUE}🔍 Scanning for Flask projects...$${RESET}" + + while IFS= read -r -d '' requirements_txt; do + project_dir=$(dirname "$requirements_txt") + + # Check if Flask is in requirements + if grep -q -i "flask" "$requirements_txt" 2>/dev/null; then + log_message "$${GREEN}🌶️ Found Flask project: $project_dir$${RESET}" + + cd "$project_dir" + + # Look for common Flask app files + for app_file in app.py main.py run.py; do + if [ -f "$app_file" ]; then + log_message "$${GREEN}🟢 Starting Flask application ($app_file) in $project_dir$${RESET}" + export FLASK_ENV=development + nohup python "$app_file" >> "${LOG_PATH}" 2>&1 & + break + fi + done + fi + + done < <(find "${WORKSPACE_DIR}" -maxdepth "${SCAN_DEPTH}" -name "requirements.txt" -type f -print0) +} + +# Function to detect and start Spring Boot projects +detect_spring_boot_projects() { + if [ "${ENABLE_SPRING_BOOT}" != "true" ]; then + return + fi + + log_message "$${BLUE}🔍 Scanning for Spring Boot projects...$${RESET}" + + # Maven projects + while IFS= read -r -d '' pom_xml; do + project_dir=$(dirname "$pom_xml") + + # Check if it's a Spring Boot project + if grep -q "spring-boot" "$pom_xml" 2>/dev/null; then + log_message "$${GREEN}🍃 Found Spring Boot Maven project: $project_dir$${RESET}" + + cd "$project_dir" + if command -v ./mvnw &> /dev/null; then + log_message "$${GREEN}🟢 Starting Spring Boot application with Maven wrapper in $project_dir$${RESET}" + nohup ./mvnw spring-boot:run >> "${LOG_PATH}" 2>&1 & + elif command -v mvn &> /dev/null; then + log_message "$${GREEN}🟢 Starting Spring Boot application with Maven in $project_dir$${RESET}" + nohup mvn spring-boot:run >> "${LOG_PATH}" 2>&1 & + fi + fi + + done < <(find "${WORKSPACE_DIR}" -maxdepth "${SCAN_DEPTH}" -name "pom.xml" -type f -print0) + + # Gradle projects + while IFS= read -r -d '' build_gradle; do + project_dir=$(dirname "$build_gradle") + + # Check if it's a Spring Boot project + if grep -q "spring-boot" "$build_gradle" 2>/dev/null; then + log_message "$${GREEN}🍃 Found Spring Boot Gradle project: $project_dir$${RESET}" + + cd "$project_dir" + if command -v ./gradlew &> /dev/null; then + log_message "$${GREEN}🟢 Starting Spring Boot application with Gradle wrapper in $project_dir$${RESET}" + nohup ./gradlew bootRun >> "${LOG_PATH}" 2>&1 & + elif command -v gradle &> /dev/null; then + log_message "$${GREEN}🟢 Starting Spring Boot application with Gradle in $project_dir$${RESET}" + nohup gradle bootRun >> "${LOG_PATH}" 2>&1 & + fi + fi + + done < <(find "${WORKSPACE_DIR}" -maxdepth "${SCAN_DEPTH}" -name "build.gradle" -type f -print0) +} + +# Function to detect and start Go projects +detect_go_projects() { + if [ "${ENABLE_GO}" != "true" ]; then + return + fi + + log_message "$${BLUE}🔍 Scanning for Go projects...$${RESET}" + + while IFS= read -r -d '' go_mod; do + project_dir=$(dirname "$go_mod") + log_message "$${GREEN}🐹 Found Go project: $project_dir$${RESET}" + + cd "$project_dir" + + # Look for main.go or check if there's a main function + if [ -f "main.go" ]; then + log_message "$${GREEN}🟢 Starting Go application in $project_dir$${RESET}" + nohup go run main.go >> "${LOG_PATH}" 2>&1 & + elif [ -f "cmd/main.go" ]; then + log_message "$${GREEN}🟢 Starting Go application (cmd/main.go) in $project_dir$${RESET}" + nohup go run cmd/main.go >> "${LOG_PATH}" 2>&1 & + fi + + done < <(find "${WORKSPACE_DIR}" -maxdepth "${SCAN_DEPTH}" -name "go.mod" -type f -print0) +} + +# Function to detect and start PHP projects +detect_php_projects() { + if [ "${ENABLE_PHP}" != "true" ]; then + return + fi + + log_message "$${BLUE}🔍 Scanning for PHP projects...$${RESET}" + + while IFS= read -r -d '' composer_json; do + project_dir=$(dirname "$composer_json") + log_message "$${GREEN}🐘 Found PHP project: $project_dir$${RESET}" + + cd "$project_dir" + + # Look for common PHP entry points + for entry_file in index.php public/index.php; do + if [ -f "$entry_file" ]; then + log_message "$${GREEN}🟢 Starting PHP development server in $project_dir$${RESET}" + nohup php -S 0.0.0.0:8080 -t "$(dirname "$entry_file")" >> "${LOG_PATH}" 2>&1 & + break + fi + done + + done < <(find "${WORKSPACE_DIR}" -maxdepth "${SCAN_DEPTH}" -name "composer.json" -type f -print0) +} + +# Function to detect and start Rust projects +detect_rust_projects() { + if [ "${ENABLE_RUST}" != "true" ]; then + return + fi + + log_message "$${BLUE}🔍 Scanning for Rust projects...$${RESET}" + + while IFS= read -r -d '' cargo_toml; do + project_dir=$(dirname "$cargo_toml") + log_message "$${GREEN}🦀 Found Rust project: $project_dir$${RESET}" + + cd "$project_dir" + + # Check if it's a binary project (has [[bin]] or default main.rs) + if grep -q "\[\[bin\]\]" Cargo.toml 2>/dev/null || [ -f "src/main.rs" ]; then + log_message "$${GREEN}🟢 Starting Rust application in $project_dir$${RESET}" + nohup cargo run >> "${LOG_PATH}" 2>&1 & + fi + + done < <(find "${WORKSPACE_DIR}" -maxdepth "${SCAN_DEPTH}" -name "Cargo.toml" -type f -print0) +} + +# Function to detect and start .NET projects +detect_dotnet_projects() { + if [ "${ENABLE_DOTNET}" != "true" ]; then + return + fi + + log_message "$${BLUE}🔍 Scanning for .NET projects...$${RESET}" + + while IFS= read -r -d '' csproj; do + project_dir=$(dirname "$csproj") + log_message "$${GREEN}🔷 Found .NET project: $project_dir$${RESET}" + + cd "$project_dir" + log_message "$${GREEN}🟢 Starting .NET application in $project_dir$${RESET}" + nohup dotnet run >> "${LOG_PATH}" 2>&1 & + + done < <(find "${WORKSPACE_DIR}" -maxdepth "${SCAN_DEPTH}" -name "*.csproj" -type f -print0) +} + +# Main execution +main() { + log_message "Starting auto-detection of development projects..." + + # Expand workspace directory if it contains variables + WORKSPACE_DIR=$(eval echo "${WORKSPACE_DIR}") + + # Check if workspace directory exists + if [ ! -d "$WORKSPACE_DIR" ]; then + log_message "$${RED}❌ Workspace directory does not exist: $WORKSPACE_DIR$${RESET}" + exit 1 + fi + + cd "$WORKSPACE_DIR" + + # Run all detection functions + detect_npm_projects + detect_rails_projects + detect_django_projects + detect_flask_projects + detect_spring_boot_projects + detect_go_projects + detect_php_projects + detect_rust_projects + detect_dotnet_projects + + log_message "$${GREEN}✅ Auto-start scan completed!$${RESET}" + log_message "$${YELLOW}💡 Check running processes with 'ps aux | grep -E \"(npm|rails|python|java|go|php|cargo|dotnet)\"'$${RESET}" + log_message "$${YELLOW}💡 View logs: tail -f ${LOG_PATH}$${RESET}" +} + +# Run main function +main "$@" \ No newline at end of file From 92ff187227873b052dbb8b42de456ea9f29238f5 Mon Sep 17 00:00:00 2001 From: mavrick-1 Date: Wed, 13 Aug 2025 20:58:34 +0530 Subject: [PATCH 2/9] feat: enhance auto-start dev server with project detection and logging outputs --- .../modules/auto-start-dev-server/README.md | 130 +++++------------- .../modules/auto-start-dev-server/main.tf | 55 ++++++-- .../modules/auto-start-dev-server/run.sh | 49 +++++-- 3 files changed, 111 insertions(+), 123 deletions(-) diff --git a/registry/mavrickrishi/modules/auto-start-dev-server/README.md b/registry/mavrickrishi/modules/auto-start-dev-server/README.md index ddb8d5e25..e5f06588d 100644 --- a/registry/mavrickrishi/modules/auto-start-dev-server/README.md +++ b/registry/mavrickrishi/modules/auto-start-dev-server/README.md @@ -13,17 +13,17 @@ Automatically detect and start development servers for various project types whe ## Supported Project Types -| Framework/Language | Detection Files | Start Commands | -|-------------------|----------------|----------------| -| **Node.js/npm** | `package.json` | `npm start`, `npm run dev`, `yarn start` | -| **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` | +| Framework/Language | Detection Files | Start Commands | +| ------------------ | -------------------------------------------- | ---------------------------------------- | +| **Node.js/npm** | `package.json` | `npm start`, `npm run dev`, `yarn start` | +| **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 @@ -31,10 +31,10 @@ Automatically detect and start development servers for various project types whe 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_rails = true enable_django = true enable_flask = true enable_spring_boot = true @@ -42,19 +42,19 @@ module "auto_start_dev_servers" { 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" } @@ -66,26 +66,6 @@ module "auto_start_dev_servers" { - `agent_id` (string): The ID of a Coder agent -### Optional Variables - -| Variable | Type | Default | Description | -|----------|------|---------|-------------| -| `workspace_directory` | string | `"$HOME"` | Directory to scan for projects | -| `enable_npm` | bool | `true` | Enable Node.js/npm project detection | -| `enable_rails` | bool | `true` | Enable Ruby on Rails project detection | -| `enable_django` | bool | `true` | Enable Django project detection | -| `enable_flask` | bool | `true` | Enable Flask project detection | -| `enable_spring_boot` | bool | `true` | Enable Spring Boot project detection | -| `enable_go` | bool | `true` | Enable Go project detection | -| `enable_php` | bool | `true` | Enable PHP project detection | -| `enable_rust` | bool | `true` | Enable Rust project detection | -| `enable_dotnet` | bool | `true` | Enable .NET project detection | -| `enable_devcontainer` | bool | `true` | Enable devcontainer.json integration | -| `log_path` | string | `"/tmp/dev-servers.log"` | Path for logging output | -| `scan_depth` | number | `2` | Maximum directory depth to scan (1-5) | -| `startup_delay` | number | `10` | Delay in seconds before starting servers | -| `display_name` | string | `"Auto-Start Dev Servers"` | Display name for the script | - ## 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: @@ -106,13 +86,6 @@ If found, the custom command will be used instead of the default project detecti ## Monitoring and Debugging -### Check Running Servers - -```bash -# View all running development servers -ps aux | grep -E "(npm|rails|python|java|go|php|cargo|dotnet)" -``` - ### View Logs ```bash @@ -123,40 +96,6 @@ tail -f /tmp/dev-servers.log cat /tmp/dev-servers.log ``` -### Manual Testing - -```bash -# Test the detection script manually -cd /path/to/workspace -bash /path/to/run.sh -``` - -## Example Projects - -### Node.js Project Structure -``` -my-app/ -├── package.json # ← Detected -├── src/ -└── node_modules/ -``` - -### Django Project Structure -``` -my-project/ -├── manage.py # ← Detected -├── myapp/ -└── requirements.txt -``` - -### Spring Boot Project Structure -``` -my-service/ -├── pom.xml # ← Detected (Maven) -├── src/ -└── target/ -``` - ## Security Considerations - Servers are started with the same user permissions as the Coder agent @@ -173,18 +112,18 @@ my-service/ 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 -### Debug Mode - -Enable verbose logging by modifying the script to include debug output: +## Module Outputs -```bash -# Add to beginning of run.sh for debugging -set -x # Enable bash debug mode -``` +| Output | Description | Example Value | +| ------------------------ | ---------------------------------------- | --------------------------------- | +| `detected_projects_file` | Path to JSON file with detected projects | `/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, ...}` | ## Examples ### Basic Usage + ```hcl module "auto_start" { source = "./modules/auto-start-dev-server" @@ -193,17 +132,18 @@ module "auto_start" { ``` ### 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 @@ -214,11 +154,12 @@ module "auto_start" { ``` ### 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 @@ -226,15 +167,6 @@ module "auto_start" { } ``` -## Contributing - -This module is part of the Coder Registry. To contribute improvements: - -1. Test your changes thoroughly across different project types -2. Update documentation for any new features -3. Ensure backward compatibility with existing configurations -4. Add appropriate error handling and logging - ## License -This module is provided under the same license as the Coder Registry. \ No newline at end of file +This module is provided under the same license as the Coder Registry. diff --git a/registry/mavrickrishi/modules/auto-start-dev-server/main.tf b/registry/mavrickrishi/modules/auto-start-dev-server/main.tf index 984739982..6f7747a6e 100644 --- a/registry/mavrickrishi/modules/auto-start-dev-server/main.tf +++ b/registry/mavrickrishi/modules/auto-start-dev-server/main.tf @@ -113,20 +113,47 @@ resource "coder_script" "auto_start_dev_server" { display_name = var.display_name icon = "/icon/server.svg" script = templatefile("${path.module}/run.sh", { - WORKSPACE_DIR = var.workspace_directory - ENABLE_NPM = var.enable_npm - ENABLE_RAILS = var.enable_rails - ENABLE_DJANGO = var.enable_django - ENABLE_FLASK = var.enable_flask - ENABLE_SPRING_BOOT = var.enable_spring_boot - ENABLE_GO = var.enable_go - ENABLE_PHP = var.enable_php - ENABLE_RUST = var.enable_rust - ENABLE_DOTNET = var.enable_dotnet - ENABLE_DEVCONTAINER = var.enable_devcontainer - LOG_PATH = var.log_path - SCAN_DEPTH = var.scan_depth - STARTUP_DELAY = var.startup_delay + WORKSPACE_DIR = var.workspace_directory + ENABLE_NPM = var.enable_npm + ENABLE_RAILS = var.enable_rails + ENABLE_DJANGO = var.enable_django + ENABLE_FLASK = var.enable_flask + ENABLE_SPRING_BOOT = var.enable_spring_boot + ENABLE_GO = var.enable_go + ENABLE_PHP = var.enable_php + ENABLE_RUST = var.enable_rust + ENABLE_DOTNET = var.enable_dotnet + ENABLE_DEVCONTAINER = var.enable_devcontainer + LOG_PATH = var.log_path + SCAN_DEPTH = var.scan_depth + STARTUP_DELAY = var.startup_delay }) run_on_start = true +} + +# Output to expose detected projects +output "detected_projects_file" { + value = "/tmp/detected-projects.json" + description = "Path to JSON file containing detected projects with their types, ports, and commands" +} + +output "log_path" { + value = var.log_path + description = "Path to the log file for dev server output" +} + +# Example output values for common port mappings +output "common_ports" { + value = { + nodejs = 3000 + rails = 3000 + django = 8000 + flask = 5000 + spring = 8080 + go = 8080 + php = 8080 + rust = 8000 + dotnet = 5000 + } + description = "Common default ports for different project types" } \ No newline at end of file diff --git a/registry/mavrickrishi/modules/auto-start-dev-server/run.sh b/registry/mavrickrishi/modules/auto-start-dev-server/run.sh index 6c85c5bf4..894671529 100755 --- a/registry/mavrickrishi/modules/auto-start-dev-server/run.sh +++ b/registry/mavrickrishi/modules/auto-start-dev-server/run.sh @@ -25,12 +25,36 @@ fi echo "=== Auto-Start Dev Servers Log ===" > "${LOG_PATH}" echo "Started at: $(date)" >> "${LOG_PATH}" +# Initialize detected projects JSON file +DETECTED_PROJECTS_FILE="/tmp/detected-projects.json" +echo '[]' > "$DETECTED_PROJECTS_FILE" + # Function to log messages log_message() { echo -e "$1" echo "$1" >> "${LOG_PATH}" } +# Function to add detected project to JSON +add_detected_project() { + local project_dir="$1" + local project_type="$2" + local port="$3" + local command="$4" + + # Create JSON entry for this project + local project_json=$(jq -n \ + --arg dir "$project_dir" \ + --arg type "$project_type" \ + --arg port "$port" \ + --arg cmd "$command" \ + '{"directory": $dir, "type": $type, "port": $port, "command": $cmd}') + + # Append to the detected projects file + jq ". += [$project_json]" "$DETECTED_PROJECTS_FILE" > "$DETECTED_PROJECTS_FILE.tmp" && \ + mv "$DETECTED_PROJECTS_FILE.tmp" "$DETECTED_PROJECTS_FILE" +} + # Function to detect and start npm/yarn projects detect_npm_projects() { if [ "${ENABLE_NPM}" != "true" ]; then @@ -46,16 +70,6 @@ detect_npm_projects() { cd "$project_dir" - # Check devcontainer.json for custom start command first - if [ "${ENABLE_DEVCONTAINER}" = "true" ] && [ -f ".devcontainer/devcontainer.json" ]; then - start_cmd=$(jq -r '.customizations.vscode.settings."npm.script.start" // empty' ".devcontainer/devcontainer.json" 2>/dev/null) - if [ -n "$start_cmd" ]; then - log_message "$${YELLOW}🐳 Using devcontainer start command: $start_cmd$${RESET}" - nohup bash -c "$start_cmd" >> "${LOG_PATH}" 2>&1 & - continue - fi - fi - # Check package.json for start script if [ -f "package.json" ] && command -v jq &> /dev/null; then start_script=$(jq -r '.scripts.start // empty' package.json) @@ -64,13 +78,16 @@ detect_npm_projects() { if [ -n "$start_script" ]; then log_message "$${GREEN}🟢 Starting npm project with 'npm start' in $project_dir$${RESET}" nohup npm start >> "${LOG_PATH}" 2>&1 & + add_detected_project "$project_dir" "nodejs" "3000" "npm start" elif [ -n "$dev_script" ]; then log_message "$${GREEN}🟢 Starting npm project with 'npm run dev' in $project_dir$${RESET}" nohup npm run dev >> "${LOG_PATH}" 2>&1 & + add_detected_project "$project_dir" "nodejs" "3000" "npm run dev" fi elif [ -f "yarn.lock" ] && command -v yarn &> /dev/null; then log_message "$${GREEN}🟢 Starting yarn project with 'yarn start' in $project_dir$${RESET}" nohup yarn start >> "${LOG_PATH}" 2>&1 & + add_detected_project "$project_dir" "nodejs" "3000" "yarn start" fi done < <(find "${WORKSPACE_DIR}" -maxdepth "${SCAN_DEPTH}" -name "package.json" -type f -print0) @@ -94,6 +111,7 @@ detect_rails_projects() { if grep -q "gem ['\"]rails['\"]" Gemfile 2>/dev/null; then log_message "$${GREEN}🟢 Starting Rails server in $project_dir$${RESET}" nohup bundle exec rails server >> "${LOG_PATH}" 2>&1 & + add_detected_project "$project_dir" "rails" "3000" "bundle exec rails server" fi done < <(find "${WORKSPACE_DIR}" -maxdepth "${SCAN_DEPTH}" -name "Gemfile" -type f -print0) @@ -114,6 +132,7 @@ detect_django_projects() { cd "$project_dir" log_message "$${GREEN}🟢 Starting Django development server in $project_dir$${RESET}" nohup python manage.py runserver 0.0.0.0:8000 >> "${LOG_PATH}" 2>&1 & + add_detected_project "$project_dir" "django" "8000" "python manage.py runserver" done < <(find "${WORKSPACE_DIR}" -maxdepth "${SCAN_DEPTH}" -name "manage.py" -type f -print0) } @@ -141,6 +160,7 @@ detect_flask_projects() { log_message "$${GREEN}🟢 Starting Flask application ($app_file) in $project_dir$${RESET}" export FLASK_ENV=development nohup python "$app_file" >> "${LOG_PATH}" 2>&1 & + add_detected_project "$project_dir" "flask" "5000" "python $app_file" break fi done @@ -169,9 +189,11 @@ detect_spring_boot_projects() { if command -v ./mvnw &> /dev/null; then log_message "$${GREEN}🟢 Starting Spring Boot application with Maven wrapper in $project_dir$${RESET}" nohup ./mvnw spring-boot:run >> "${LOG_PATH}" 2>&1 & + add_detected_project "$project_dir" "spring-boot" "8080" "./mvnw spring-boot:run" elif command -v mvn &> /dev/null; then log_message "$${GREEN}🟢 Starting Spring Boot application with Maven in $project_dir$${RESET}" nohup mvn spring-boot:run >> "${LOG_PATH}" 2>&1 & + add_detected_project "$project_dir" "spring-boot" "8080" "mvn spring-boot:run" fi fi @@ -189,9 +211,11 @@ detect_spring_boot_projects() { if command -v ./gradlew &> /dev/null; then log_message "$${GREEN}🟢 Starting Spring Boot application with Gradle wrapper in $project_dir$${RESET}" nohup ./gradlew bootRun >> "${LOG_PATH}" 2>&1 & + add_detected_project "$project_dir" "spring-boot" "8080" "./gradlew bootRun" elif command -v gradle &> /dev/null; then log_message "$${GREEN}🟢 Starting Spring Boot application with Gradle in $project_dir$${RESET}" nohup gradle bootRun >> "${LOG_PATH}" 2>&1 & + add_detected_project "$project_dir" "spring-boot" "8080" "gradle bootRun" fi fi @@ -216,9 +240,11 @@ detect_go_projects() { if [ -f "main.go" ]; then log_message "$${GREEN}🟢 Starting Go application in $project_dir$${RESET}" nohup go run main.go >> "${LOG_PATH}" 2>&1 & + add_detected_project "$project_dir" "go" "8080" "go run main.go" elif [ -f "cmd/main.go" ]; then log_message "$${GREEN}🟢 Starting Go application (cmd/main.go) in $project_dir$${RESET}" nohup go run cmd/main.go >> "${LOG_PATH}" 2>&1 & + add_detected_project "$project_dir" "go" "8080" "go run cmd/main.go" fi done < <(find "${WORKSPACE_DIR}" -maxdepth "${SCAN_DEPTH}" -name "go.mod" -type f -print0) @@ -243,6 +269,7 @@ detect_php_projects() { if [ -f "$entry_file" ]; then log_message "$${GREEN}🟢 Starting PHP development server in $project_dir$${RESET}" nohup php -S 0.0.0.0:8080 -t "$(dirname "$entry_file")" >> "${LOG_PATH}" 2>&1 & + add_detected_project "$project_dir" "php" "8080" "php -S 0.0.0.0:8080" break fi done @@ -268,6 +295,7 @@ detect_rust_projects() { if grep -q "\[\[bin\]\]" Cargo.toml 2>/dev/null || [ -f "src/main.rs" ]; then log_message "$${GREEN}🟢 Starting Rust application in $project_dir$${RESET}" nohup cargo run >> "${LOG_PATH}" 2>&1 & + add_detected_project "$project_dir" "rust" "8000" "cargo run" fi done < <(find "${WORKSPACE_DIR}" -maxdepth "${SCAN_DEPTH}" -name "Cargo.toml" -type f -print0) @@ -288,6 +316,7 @@ detect_dotnet_projects() { cd "$project_dir" log_message "$${GREEN}🟢 Starting .NET application in $project_dir$${RESET}" nohup dotnet run >> "${LOG_PATH}" 2>&1 & + add_detected_project "$project_dir" "dotnet" "5000" "dotnet run" done < <(find "${WORKSPACE_DIR}" -maxdepth "${SCAN_DEPTH}" -name "*.csproj" -type f -print0) } From e629722f773a5f2a8e62895948fef1e374347605 Mon Sep 17 00:00:00 2001 From: mavrick-1 Date: Wed, 13 Aug 2025 21:59:31 +0530 Subject: [PATCH 3/9] feat: enhance auto-start dev server with project detection and logging outputs --- .github/typos.toml | 2 ++ registry/mavrickrishi/.images/avatar.jpeg | Bin 0 -> 7821 bytes registry/mavrickrishi/README.md | 25 ++++++++++++++ .../modules/auto-start-dev-server/README.md | 32 ++++++++++++++++++ 4 files changed, 59 insertions(+) create mode 100644 registry/mavrickrishi/.images/avatar.jpeg create mode 100644 registry/mavrickrishi/README.md diff --git a/.github/typos.toml b/.github/typos.toml index f27257a23..7d53f9bf1 100644 --- a/.github/typos.toml +++ b/.github/typos.toml @@ -2,6 +2,8 @@ muc = "muc" # For Munich location code Hashi = "Hashi" HashiCorp = "HashiCorp" +mavrickrishi = "mavrickrishi" # Username +mavrick = "mavrick" # Username [files] extend-exclude = ["registry/coder/templates/aws-devcontainer/architecture.svg"] #False positive \ No newline at end of file diff --git a/registry/mavrickrishi/.images/avatar.jpeg b/registry/mavrickrishi/.images/avatar.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..a624cf8fc8d1c168f42f82df3af4b8279df0d871 GIT binary patch literal 7821 zcmb7obyOVBw)G6|3@$;2Ai-UNy9Eh@I}C(igS!L`1cwlu5ZrWe z4Zr*Dz2E!uovyWdb)R!;)$Xp^yG}jMKCS{luN0IO06-uB07P7X#|3~a02vACsUZvn z(NHl^QBhD(vCz@cFmSMNaImqkv2pPTLAZDXc-Yt=QV;&1E;cUl|JfdY0theweSkh>;Bx>H0T7u0_}B%Yei|k!@M*mNHgv=g z(J+vJm>*xf~80&u5FZWrJ~3 zH@}AUuVgk&dmg1^!MB{1o?`rWglj%rju;ibs-J2q3^W~+N$yTR8o!z*GjZtkO3EH9 z;$j)9dWv*gVZM4zd0};JQ~O&&{buIbq=&Gt_cz*kk*VMPQwxoHkm! zc1GFE5jk|~vPVZWy8}wubi%!z*XKfl$!q&F+0~Sf0B(;~w5hd>34h_eKPIAM@cWQp zLPQ2~w5Ym}Au;^d)cHFHK8H>RFGpX_!!nmk1!1uwv!?L(mZIj&yVbisPu&CBcS@#D zv_qdME$h|kPH>bBTCrDF5x35mep2;dkE?m1=9#)&fEVZd6h|7C&1_Zcf1SyDi;K@SHOE`s{rAtYA?X}6_S-G; zIbUN-HlZ>J;xi);NAt9r3tKRbXR(aju2k5cDaF;KU3hrrH!R(+v;hyFJp#%Mi)aO+ zhlMk3#}5KBcbZh*-Jd6N#5;ivn%I^xs&G7IW4Vm|jrNMw`R$hUY7JKI?${X*RVa<} z3*%@H%!p?CZ)cm&-1kqH_xr{5jVxPkuf^>6&n_yA6#{AOHXj zh>V1aSU^u-3t|77hUf%@M0B9%+&sL*BvPbcK4}I<4aC&MKulX8D$*mM!7W*LjA=sW zO{-N&gF{6Np=6cm(+(_yzlJk4L2 zREVbeW^0Tui`Po6`&o|^))OJqP#lWYxiDO7B^+UJVso1BJVBd;QP&+ z#=W8LFNbA6QdKX)E`>hcW)v0UWftyqe)_9w_ExWI3%=;cQI=T~n*cqt8(GKrL;6wk z8HaCrmcjgJg)zzdnj!esccXP#3lymVs@zk?k$m$PzT`FiM1It}=G z@`ugUs4qAs3R>tWzal#A8mLwmAMWXh&07U2*IwVtnTI zk1<0bR>Co<<|@=?k(d5+)^BliXN7AE*yr$WKY!;DJv+<|L-V@%&b@3KL^$xIJQ zB0Z5TP}sIS>+Y{6?`K_+aw`n;<8>Tt-RS~48>j1~n5&TiuKlC(ZV`(lwlh|Igj4Uj zM70CXAq-}3>%9M%*k#3>XIgO%{RAs*sz%Kuqxq95Uy+7DSVd$gXPMs*<=2?kd=g$^ zb1qT}I)Ghvn&9RA^jAz-d>`-&8;x~sQzY2h7CboVFAZjF=|xg8>-ko0TL;xW9E=}b zq@t&Nm4^|%!ksqg>3u{Rmmj{|8N?se9MbdAyQoyaVuS0stn93Hy2Upb{-!d96w|e& zc_0l+o~tB(*XIMW)66R;I^1x1?`|AX6|!>D#bkKO#P-G{mXo;+mee|bFVk+h9mmeR zO+0+TmFrEs1y{;L1g&}P5!;S(QEJR4#~Xob!GnpP%`KnY1XzrMnP&<8u?H0r3PNAI ziCZ7{g?C6i3!&MB%HcO& zWK1+)C$k!aKLQdW-1ca{qhGGek@feIo@JkM1rmQ5Fzagyp$k*JrHV(;$O{4h5Cw>Y zhJ;YAe;Go-kO>IEbSNMq1c^vPi0P$*|KSgW=t%=1-QV2b{tSmOS4Fn?oMFpf(kK0JJFu9*~U=@4=*C0dhNEI$|qL?mVmt`P4o`?K0(80p07*eG6w z+NuwpCNwy%QGD^N^UQNl0Ln*1byo~(kS9yNPMTfwg-TCs3wr-de!MFRZGS!2Y{-jkv2dShy`1e) zz1---H&pG_K{A8iq(3LR$~hpz%iz*{pJop$11B8vyTAHZYqj%jQo0p$D;`?Z!eC4K@4A&AbXj>TCFTB5&{PyR4j$!@A>leNr`=@kT{#7S**13MtRsAD{qh}^ z5B}(cNX?7vAAebT1aMFlS!43Yq86)+F#4^T)4Xd+b9K&3p$}Wd15C|;)NnN)aWG+%ZMfQ zUR*f9YhCpTZ1lq!b#iV$U;Ny=y0`w4DOz0F3$=DP|4*rR-t;e`R{Mca9pSZPiPE72 z&@xuAnuDkM-rQQ-pI@_9b@L{k%)Qx+wx8Q)EerSfyrOK#&rP(Bh&dP5>4Poy3+;RR zKhoteIW)Ga+KVUi9`*KWIxU-Q4(I zcSR4$%za4its4`2i`5c{>YjmE#Z9qlfOhd(^~kw8h2JK=-s+`0@yPRyib@NiD=ztB zkAOEu$lKXT)JA~>y#rD41sX!6oiwH|BDdXD2u7OupPhy@T+ra(JpcwYKA+D21&WL}${}E74%J~RT9{S!*oyh6u zcz<%Ae5aGAA`9=^+hvVn$%Gdv@zN_uTjidKGDVd#2*al!n6PsRO!VeXxf!DajrmR5 znfR}%rvidPhSU@{9BDpc(Cv)vFIOfM9D*Mfqj)s6hoZa;%8y?1ieb>OQN5N$^}+h= zPg-<>Pjf6&XlDYplIGv&C*#5kgQXPrNZ`x|M5dT2^VIvq;U;JG2K0YdSiKSjtrcrw zw{~LYqxS?b_!95RGMH$8^y~D6#fVy>*Z8S_qQ5He#EEgzG_;=gS&Y@EEE}hZsug{! z3Vq=Qw{eFwewuHr?r*(5&$iNDP)n5Q#a)PJn49P96Eq!pU-}|xb!qXH`?zSkGq%mA z(cE3Rt7qS=Fz8)t3?FtHV9uVG3{sb#&@vj)3sHF;Us$5-mAyh|vucK1q;dZVf*6FZcS`1GTF*~g^sdIaoPTfDQuKB7eqK~N|w z2tk>^r{eVAx(Eai&>_SS>JrTTF&9+bF(!2aUOWBI##)l@5wKvGGj?<@HaTa$bjX@B z`XRe3i&H>StGwFf+LDYCyZdgEJH#gYXVqX+Zfqd!8RNEqS6T$k_${zTkJH_@hRstD zBlgZb-?zYDcd0*?tvNR2y8b})ALaEw!PMaIT$->kG!F$xp8 z9r!}oVJ$j#ib3O4Q^G&D4{VV&2u`|w5~Ioit$B;6dT z-EydU^PE-3M%Rp!)y!kb>adSs(fHM`i4D4=}G|n2=KYoukE--lXwL1*nH^ymWSP(Phl5BtmBJY ztkqI0jIvhLG^u|N&s{42N&Qg;aZSo&qqUIz!=FMJci{{t_;dUXw;AIyKTceVuetE_XFHR}NCSO3y6$f86 zw}-J##eN)LEUP+T^>SJ|KiEPZoQGU7Svg&CUO`_-p93zs9G*T~MsKORCQqI#mD?oV zqjFCh^oz~OJE1%#Z@c?I19pqJNiS`9K})hfyLWiNn_&{YNju2pg3Bl+=Xg+pXHLz- zE+E*)JgD2BvvqTM*^6ak_$42I-4KK!7TRRB8)mQB*DJJ05mKzr&KlUldOy&L{qqP* zQnFpR)_bx#K*Q(;LU9b0G)Y13{5MEZ+<|~G`h=PzT|KpdD&-Wo z`^+aIS)eHKehCfh@1B^VcsYTSe5ecivjX~|JGOzdl@qjZZbo764{gM$GDERkffy`S zw9P+cU~MxIvCokUf=IX`bW+U$K1=!rru;LaUC4q&u5Z$33{k%j_1#7*n2*~}HJ@D7 zj0+nbE-mk@QAo{wZI1KnJ^4QHPzbI|A*e2g#C^-;J^TvKo(m1@rX^w ztGBbJS|l2(K@%q5U-n2)PMHSK2T8%w7eS;_q)Co|4r$!=x2eZ(Z5U? zjL%@e?to47LV@OsnsS+Uy;y92GnUxjbQz7F!=QA}m+YVAoc(qtMimKY#+bF@3pFgQ z;RpE&DE1&hZt<=1DAVIiQ~H>$mmie1Y(}2#aBNpHk{Net$TI;QLO=Bvrzi22!M&>< z0af3jNN-!iG|ye|-2Sf)2b4x>9f-R*$Xyr_cdCU~>%3ayegxdLJ+m7X2->;g}G&bVqPk zo&i64gjmoa+oJOa4mtnFY4A^W_iG5C)0^RJqi z0CQAqCPLas9p{xpH0dc#)@{=eV<*CgKPhi@&h$63_k`?rDO%K1Wk*YtsNi=ohiMm1 zl)}HOAZ66#-vbeV8J++m0Z|agtp5d!r~$y-5UBLW+-j-dlmC=Fpuf0V9qJfuy_f{W zRrWSj#W4HOj*NY8ZOKd$UU2ppr(9c_eR+8Gs?5(K>$&eXUg;LM3$Hb5OFg$upl0&& zgk1tEdwGQ4(N`=+21ws>U}&qUux{yvwH>z(JjdqkIa1a#F!1vOhg*#Ox<)P0m$0Dw zR`Mz$0hur-Bt=v9ASdCq23Yv{;V%fF134(1&j0+hH;y>~s*MI0Ou|Q%gu7!%gT5`? zo?<{ssCZHo(Q+%JI4+uk6`p{y{G-+goIn&rjrxT3ziRz4ms<)^-hir4!T%L&&?Dfm zjm6?wH*K;>J7kjFbM};MP$4UquAA$yb<6odT9WiG4fYv@n)#e(-zBoc;$B25puUOd z;{#se9Mu|BUJJ{FM~SmKao=%oKVGv0U&QUODdkd|WJNw5k ze?b+-d`(TK92~W|Lq40sJBXacF>mq`v%X#poj25(^O@9ovZy2n0cB8$ZasHNVJuTMoT%=0K`s)y2o0 z0hZkCg4d|$-9T%-rL%_7gfu+4yF?{t$v@c$3{imqY@_X1!P4~~8;8N+Azm2p!E`@{ zdVvyG$4_@f2inP8ld`(3!Sl3iMNyGc>^o5Ap#lu4s`~C*LoFazhXRePM;m<&!XS|g#78li+wDg5fa~P$nD9e~gM;c_L zO9J^ZA`XVHWb;WY3un#x6AJz1HTb5TVyxQn3RwpN#*nIy zCo8g<1KxS!hzVVk%VVR>8K@`oRz)xNVz^5|`9i&8nGG3r>5A5LQ#QYYOY9@R zu*imqnZ2~{Zx`I{F!fOQ%Pf*5OL*c~>Flb@HMV@c9|6v-tFy)7pE`*>vl2}EkiV}n zuTh0YC3{pfB5}%5+9|!x^m{-PjlZfjp$@DU#jfEm7dB^KvbkzeMVtWao@iHS*5Gi8 zM6IOhd=yC{qr7hDt6JNhc^BO z>+IpQvBy;`^=0!h9iYZeh@NWfvltGi%iwfkPwTV4Sq|A$I=>}SNK^?xZq%UV$EMbN z&Wto%tqbU$G{ZuN)>|l4P|-lb^Ghpo>EJ#+?+$LTiU@q7)7CN-m0SK{bKN$~R^-pbLyBc3}vi?w)r^B2ZH z58owT*C{n%W2*V(C+iB3^_8TqVz%Iu8UWnlGEur zc5MlMNl(EgSXn8*H-FU6N_of|PS-`6xQaqn*zqE(EQlU;Cda!EJ%!P2MO=M)1Te>o zUKt-rNh2_2;P>QtR#*hya26byZ^`9);9PENTR+%CfD0(97>B7@}$7Fwotahe-aJ#;z9-Niow%sF-O zlg}FlQ;F~5nLfK1!Ag5N(3Yy$+-?@`pII6vp|cB#NTVYypP8v+MKuWKAKC9OlC->& zk)p&Ya3QalOIy#;F zt>yMSpNiigGTjLGW|Af6gh=Ap(#Mp-t#zL8{D|@j{BTXpRW(hK9lm+HYeoF8DnV=Y z<)E563(fR&PMD;i8+aTK06 z*vN%=c>VA}&uws-7%rKW)+lrDO*C?@vT5V-rZPk=?OQ0OWclnKylw_?`Pz)~`K<&P zGrGdk{AFqK=7exO43$6?+to^G>6RW(#f-OoJnYhSBvKG4U1xp2*{6 NUh;}UK=I?;{{wmqIY Date: Wed, 13 Aug 2025 22:43:16 +0530 Subject: [PATCH 4/9] feat: enhance auto-start dev server with project detection and logging outputs --- .../modules/auto-start-dev-server/README.md | 27 +++++++++++++++ .../modules/auto-start-dev-server/main.tf | 33 +++++++++++++++++++ .../modules/auto-start-dev-server/run.sh | 17 ++++++++++ 3 files changed, 77 insertions(+) diff --git a/registry/mavrickrishi/modules/auto-start-dev-server/README.md b/registry/mavrickrishi/modules/auto-start-dev-server/README.md index f86444e0d..ec39e0b3e 100644 --- a/registry/mavrickrishi/modules/auto-start-dev-server/README.md +++ b/registry/mavrickrishi/modules/auto-start-dev-server/README.md @@ -42,6 +42,7 @@ module "auto_start_dev_servers" { - **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 first detected project ## Supported Project Types @@ -89,6 +90,9 @@ module "auto_start_dev_servers" { # Optional: Log file path log_path = "/tmp/dev-servers.log" + + # Optional: Enable automatic preview app (default: true) + enable_preview_app = true } ``` @@ -144,6 +148,15 @@ cat /tmp/dev-servers.log 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 points to the first detected development server. This gives you instant access to your running application through the Coder dashboard. + +- **Automatic detection**: Uses the port from the first project detected +- **Dynamic URL**: Points to `http://localhost:{detected_port}` +- **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 | @@ -151,6 +164,8 @@ cat /tmp/dev-servers.log | `detected_projects_file` | Path to JSON file with detected projects | `/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 @@ -163,6 +178,18 @@ module "auto_start" { } ``` +### 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 diff --git a/registry/mavrickrishi/modules/auto-start-dev-server/main.tf b/registry/mavrickrishi/modules/auto-start-dev-server/main.tf index 6f7747a6e..e7d87aad8 100644 --- a/registry/mavrickrishi/modules/auto-start-dev-server/main.tf +++ b/registry/mavrickrishi/modules/auto-start-dev-server/main.tf @@ -108,6 +108,17 @@ variable "display_name" { default = "Auto-Start Dev Servers" } +variable "enable_preview_app" { + type = bool + description = "Enable automatic creation of a preview app for the first detected project." + default = true +} + +# Read the detected port from the file written by the script +locals { + detected_port = var.enable_preview_app ? try(tonumber(trimspace(file("/tmp/detected-port.txt"))), 3000) : 3000 +} + resource "coder_script" "auto_start_dev_server" { agent_id = var.agent_id display_name = var.display_name @@ -131,6 +142,18 @@ resource "coder_script" "auto_start_dev_server" { run_on_start = true } +# Create preview app for first detected project +resource "coder_app" "preview" { + count = var.enable_preview_app ? 1 : 0 + agent_id = var.agent_id + slug = "dev-preview" + display_name = "Live Preview" + url = "http://localhost:${local.detected_port}" + icon = "/icon/globe.svg" + subdomain = true + share = "owner" +} + # Output to expose detected projects output "detected_projects_file" { value = "/tmp/detected-projects.json" @@ -156,4 +179,14 @@ output "common_ports" { dotnet = 5000 } description = "Common default ports for different project types" +} + +output "preview_url" { + value = var.enable_preview_app ? try(coder_app.preview[0].url, null) : null + description = "URL of the live preview app (if enabled)" +} + +output "detected_port" { + value = local.detected_port + description = "Port of the first detected development server" } \ No newline at end of file diff --git a/registry/mavrickrishi/modules/auto-start-dev-server/run.sh b/registry/mavrickrishi/modules/auto-start-dev-server/run.sh index 894671529..e6c10f8a1 100755 --- a/registry/mavrickrishi/modules/auto-start-dev-server/run.sh +++ b/registry/mavrickrishi/modules/auto-start-dev-server/run.sh @@ -29,6 +29,10 @@ echo "Started at: $(date)" >> "${LOG_PATH}" DETECTED_PROJECTS_FILE="/tmp/detected-projects.json" echo '[]' > "$DETECTED_PROJECTS_FILE" +# Initialize detected port file for preview app +DETECTED_PORT_FILE="/tmp/detected-port.txt" +FIRST_PORT_DETECTED=false + # Function to log messages log_message() { echo -e "$1" @@ -42,6 +46,13 @@ add_detected_project() { local port="$3" local command="$4" + # Set the first detected port for preview app + if [ "$FIRST_PORT_DETECTED" = false ]; then + echo "$port" > "$DETECTED_PORT_FILE" + FIRST_PORT_DETECTED=true + log_message "$${BLUE}🎯 First project detected - Preview app will be available on port $port$${RESET}" + fi + # Create JSON entry for this project local project_json=$(jq -n \ --arg dir "$project_dir" \ @@ -350,6 +361,12 @@ main() { log_message "$${GREEN}✅ Auto-start scan completed!$${RESET}" log_message "$${YELLOW}💡 Check running processes with 'ps aux | grep -E \"(npm|rails|python|java|go|php|cargo|dotnet)\"'$${RESET}" log_message "$${YELLOW}💡 View logs: tail -f ${LOG_PATH}$${RESET}" + + # Set default port if no projects were detected + if [ "$FIRST_PORT_DETECTED" = false ]; then + echo "3000" > "$DETECTED_PORT_FILE" + log_message "$${YELLOW}⚠️ No projects detected - Preview app will default to port 3000$${RESET}" + fi } # Run main function From a1933b7303914bee6d4616093a176fa83a2a8986 Mon Sep 17 00:00:00 2001 From: Rishi Mondal Date: Thu, 14 Aug 2025 01:04:32 +0530 Subject: [PATCH 5/9] Update registry/mavrickrishi/modules/auto-start-dev-server/README.md Co-authored-by: DevCats --- .../modules/auto-start-dev-server/README.md | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/registry/mavrickrishi/modules/auto-start-dev-server/README.md b/registry/mavrickrishi/modules/auto-start-dev-server/README.md index ec39e0b3e..4cb77d0ef 100644 --- a/registry/mavrickrishi/modules/auto-start-dev-server/README.md +++ b/registry/mavrickrishi/modules/auto-start-dev-server/README.md @@ -3,23 +3,7 @@ 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, - ] +tags: [development, automation, servers, nodejs, python, java, go, rust, php, rails, django, flask, spring-boot, dotnet] --- # Auto-Start Development Servers From 85cd00376ba76e9f5649d7d689b4867caecdc6cc Mon Sep 17 00:00:00 2001 From: Rishi Mondal Date: Thu, 14 Aug 2025 01:04:45 +0530 Subject: [PATCH 6/9] Update registry/mavrickrishi/README.md Co-authored-by: DevCats --- registry/mavrickrishi/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/registry/mavrickrishi/README.md b/registry/mavrickrishi/README.md index 954037eef..05ce961af 100644 --- a/registry/mavrickrishi/README.md +++ b/registry/mavrickrishi/README.md @@ -1,7 +1,7 @@ --- display_name: "Rishi Mondal" bio: "Breaking code, fixing bugs, and occasionally making it work! Always caffeinated, always committing" -avatar_url: "./.images/avatar.jpeg" +avatar: "./.images/avatar.jpeg" github: "MAVRICK-1" linkedin: "https://www.linkedin.com/in/rishi-mondal-5238b2282/" website: "https://mavrick-portfolio.vercel.app/" From cd4643ecc2626fa4fd5c488ec11c97a4b431dfff Mon Sep 17 00:00:00 2001 From: mavrick-1 Date: Thu, 14 Aug 2025 01:17:58 +0530 Subject: [PATCH 7/9] feat: enhance auto-start dev server with project detection and logging outputs --- .../modules/auto-start-dev-server/README.md | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/registry/mavrickrishi/modules/auto-start-dev-server/README.md b/registry/mavrickrishi/modules/auto-start-dev-server/README.md index 4cb77d0ef..ec39e0b3e 100644 --- a/registry/mavrickrishi/modules/auto-start-dev-server/README.md +++ b/registry/mavrickrishi/modules/auto-start-dev-server/README.md @@ -3,7 +3,23 @@ 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] +tags: + [ + development, + automation, + servers, + nodejs, + python, + java, + go, + rust, + php, + rails, + django, + flask, + spring-boot, + dotnet, + ] --- # Auto-Start Development Servers From ed65cb5e7caaa4b2aeb3fa8a6701d76a2422658e Mon Sep 17 00:00:00 2001 From: mavrick-1 Date: Thu, 14 Aug 2025 01:24:16 +0530 Subject: [PATCH 8/9] fix(aws-ami-snapshot): update provider configuration for clarity and testing --- .../modules/auto-start-dev-server/README.md | 30 +++++++++---------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/registry/mavrickrishi/modules/auto-start-dev-server/README.md b/registry/mavrickrishi/modules/auto-start-dev-server/README.md index ec39e0b3e..b4847480a 100644 --- a/registry/mavrickrishi/modules/auto-start-dev-server/README.md +++ b/registry/mavrickrishi/modules/auto-start-dev-server/README.md @@ -4,22 +4,20 @@ description: Automatically detect and start development servers for various proj icon: ../../../../.icons/server.svg verified: false tags: - [ - development, - automation, - servers, - nodejs, - python, - java, - go, - rust, - php, - rails, - django, - flask, - spring-boot, - dotnet, - ] + - development + - automation + - servers + - nodejs + - python + - java + - go + - rust + - php + - rails + - django + - flask + - spring-boot + - dotnet --- # Auto-Start Development Servers From 88aeb00a664e6d4dfd3716dcc7e9e3b8d81990f6 Mon Sep 17 00:00:00 2001 From: mavrick-1 Date: Thu, 14 Aug 2025 18:47:58 +0530 Subject: [PATCH 9/9] feat: enhance auto-start dev server with improved frontend detection and prioritization --- .../modules/auto-start-dev-server/README.md | 46 +++--- .../modules/auto-start-dev-server/main.tf | 3 + .../modules/auto-start-dev-server/run.sh | 133 +++++++++++++++--- 3 files changed, 145 insertions(+), 37 deletions(-) diff --git a/registry/mavrickrishi/modules/auto-start-dev-server/README.md b/registry/mavrickrishi/modules/auto-start-dev-server/README.md index b4847480a..63a5bac3e 100644 --- a/registry/mavrickrishi/modules/auto-start-dev-server/README.md +++ b/registry/mavrickrishi/modules/auto-start-dev-server/README.md @@ -35,26 +35,28 @@ module "auto_start_dev_servers" { ## 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 first detected project +- **Integrated live preview**: Automatically creates a preview app for the primary frontend project ## Supported Project Types -| Framework/Language | Detection Files | Start Commands | -| ------------------ | -------------------------------------------- | ---------------------------------------- | -| **Node.js/npm** | `package.json` | `npm start`, `npm run dev`, `yarn start` | -| **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` | +| 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 @@ -148,22 +150,24 @@ cat /tmp/dev-servers.log ## Live Preview App -The module automatically creates a "Live Preview" app in your Coder workspace that points to the first detected development server. This gives you instant access to your running application through the Coder dashboard. +The module automatically creates a "Live Preview" app in your Coder workspace that intelligently selects the best project for preview: -- **Automatic detection**: Uses the port from the first project detected +- **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 | `/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` | +| 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 diff --git a/registry/mavrickrishi/modules/auto-start-dev-server/main.tf b/registry/mavrickrishi/modules/auto-start-dev-server/main.tf index e7d87aad8..0683a4bcf 100644 --- a/registry/mavrickrishi/modules/auto-start-dev-server/main.tf +++ b/registry/mavrickrishi/modules/auto-start-dev-server/main.tf @@ -117,6 +117,9 @@ variable "enable_preview_app" { # Read the detected port from the file written by the script locals { detected_port = var.enable_preview_app ? try(tonumber(trimspace(file("/tmp/detected-port.txt"))), 3000) : 3000 + # Attempt to read project information for better preview naming + detected_projects = try(jsondecode(file("/tmp/detected-projects.json")), []) + preview_project = length(local.detected_projects) > 0 ? local.detected_projects[0] : null } resource "coder_script" "auto_start_dev_server" { diff --git a/registry/mavrickrishi/modules/auto-start-dev-server/run.sh b/registry/mavrickrishi/modules/auto-start-dev-server/run.sh index e6c10f8a1..4da877be9 100755 --- a/registry/mavrickrishi/modules/auto-start-dev-server/run.sh +++ b/registry/mavrickrishi/modules/auto-start-dev-server/run.sh @@ -32,6 +32,7 @@ echo '[]' > "$DETECTED_PROJECTS_FILE" # Initialize detected port file for preview app DETECTED_PORT_FILE="/tmp/detected-port.txt" FIRST_PORT_DETECTED=false +FRONTEND_PROJECT_DETECTED=false # Function to log messages log_message() { @@ -39,6 +40,56 @@ log_message() { echo "$1" >> "${LOG_PATH}" } +# Function to determine if a project is likely a frontend project +is_frontend_project() { + local project_dir="$1" + local project_type="$2" + + # Check for common frontend indicators + if [ "$project_type" = "nodejs" ]; then + # Check package.json for frontend dependencies + if [ -f "$project_dir/package.json" ] && command -v jq &> /dev/null; then + # Check for common frontend frameworks + local has_react=$(jq '.dependencies.react // .devDependencies.react // empty' "$project_dir/package.json") + local has_vue=$(jq '.dependencies.vue // .devDependencies.vue // empty' "$project_dir/package.json") + local has_angular=$(jq '.dependencies["@angular/core"] // .devDependencies["@angular/core"] // empty' "$project_dir/package.json") + local has_next=$(jq '.dependencies.next // .devDependencies.next // empty' "$project_dir/package.json") + local has_nuxt=$(jq '.dependencies.nuxt // .devDependencies.nuxt // empty' "$project_dir/package.json") + local has_svelte=$(jq '.dependencies.svelte // .devDependencies.svelte // empty' "$project_dir/package.json") + local has_vite=$(jq '.dependencies.vite // .devDependencies.vite // empty' "$project_dir/package.json") + + if [ -n "$has_react" ] || [ -n "$has_vue" ] || [ -n "$has_angular" ] || \ + [ -n "$has_next" ] || [ -n "$has_nuxt" ] || [ -n "$has_svelte" ] || \ + [ -n "$has_vite" ]; then + return 0 # It's a frontend project + fi + fi + + # Check for common frontend directory structures + if [ -d "$project_dir/src/components" ] || [ -d "$project_dir/components" ] || \ + [ -d "$project_dir/pages" ] || [ -d "$project_dir/views" ] || \ + [ -f "$project_dir/index.html" ] || [ -f "$project_dir/public/index.html" ]; then + return 0 # It's likely a frontend project + fi + fi + + # Rails projects with webpack/webpacker are frontend-enabled + if [ "$project_type" = "rails" ]; then + if [ -f "$project_dir/config/webpacker.yml" ] || [ -f "$project_dir/webpack.config.js" ]; then + return 0 + fi + fi + + # Django projects with static/templates are frontend-enabled + if [ "$project_type" = "django" ]; then + if [ -d "$project_dir/static" ] || [ -d "$project_dir/templates" ]; then + return 0 + fi + fi + + return 1 # Not a frontend project +} + # Function to add detected project to JSON add_detected_project() { local project_dir="$1" @@ -46,11 +97,24 @@ add_detected_project() { local port="$3" local command="$4" - # Set the first detected port for preview app - if [ "$FIRST_PORT_DETECTED" = false ]; then + # Check if this is a frontend project + local is_frontend=false + if is_frontend_project "$project_dir" "$project_type"; then + is_frontend=true + log_message "$${BLUE}🎨 Detected frontend project at $project_dir$${RESET}" + fi + + # Prioritize frontend projects for the preview app + # Set port if: 1) No port set yet, OR 2) This is frontend and no frontend detected yet + if [ "$FIRST_PORT_DETECTED" = false ] || ([ "$is_frontend" = true ] && [ "$FRONTEND_PROJECT_DETECTED" = false ]); then echo "$port" > "$DETECTED_PORT_FILE" FIRST_PORT_DETECTED=true - log_message "$${BLUE}🎯 First project detected - Preview app will be available on port $port$${RESET}" + if [ "$is_frontend" = true ]; then + FRONTEND_PROJECT_DETECTED=true + log_message "$${BLUE}🎯 Frontend project detected - Preview app will be available on port $port$${RESET}" + else + log_message "$${BLUE}🎯 Project detected - Preview app will be available on port $port$${RESET}" + fi fi # Create JSON entry for this project @@ -59,7 +123,8 @@ add_detected_project() { --arg type "$project_type" \ --arg port "$port" \ --arg cmd "$command" \ - '{"directory": $dir, "type": $type, "port": $port, "command": $cmd}') + --arg frontend "$is_frontend" \ + '{"directory": $dir, "type": $type, "port": $port, "command": $cmd, "is_frontend": ($frontend == "true")}') # Append to the detected projects file jq ". += [$project_json]" "$DETECTED_PROJECTS_FILE" > "$DETECTED_PROJECTS_FILE.tmp" && \ @@ -85,20 +150,56 @@ detect_npm_projects() { if [ -f "package.json" ] && command -v jq &> /dev/null; then start_script=$(jq -r '.scripts.start // empty' package.json) dev_script=$(jq -r '.scripts.dev // empty' package.json) + serve_script=$(jq -r '.scripts.serve // empty' package.json) - if [ -n "$start_script" ]; then - log_message "$${GREEN}🟢 Starting npm project with 'npm start' in $project_dir$${RESET}" - nohup npm start >> "${LOG_PATH}" 2>&1 & - add_detected_project "$project_dir" "nodejs" "3000" "npm start" - elif [ -n "$dev_script" ]; then - log_message "$${GREEN}🟢 Starting npm project with 'npm run dev' in $project_dir$${RESET}" - nohup npm run dev >> "${LOG_PATH}" 2>&1 & - add_detected_project "$project_dir" "nodejs" "3000" "npm run dev" + # Determine port (check for common port configurations) + local project_port=3000 + if [ -n "$dev_script" ] && echo "$dev_script" | grep -q "\-\-port"; then + project_port=$(echo "$dev_script" | grep -oE "\-\-port[[:space:]]+[0-9]+" | grep -oE "[0-9]+$" || echo "3000") + fi + + # Use yarn if yarn.lock exists + local pkg_manager="npm" + local cmd_prefix="" + if [ -f "yarn.lock" ] && command -v yarn &> /dev/null; then + pkg_manager="yarn" + cmd_prefix="" + else + cmd_prefix="run " + fi + + # Prioritize scripts: 'dev' > 'serve' > 'start' for development environments + if [ -n "$dev_script" ]; then + if [ "$pkg_manager" = "yarn" ]; then + log_message "$${GREEN}🟢 Starting project with 'yarn dev' in $project_dir$${RESET}" + nohup yarn dev >> "${LOG_PATH}" 2>&1 & + add_detected_project "$project_dir" "nodejs" "$project_port" "yarn dev" + else + log_message "$${GREEN}🟢 Starting project with 'npm run dev' in $project_dir$${RESET}" + nohup npm run dev >> "${LOG_PATH}" 2>&1 & + add_detected_project "$project_dir" "nodejs" "$project_port" "npm run dev" + fi + elif [ -n "$serve_script" ]; then + if [ "$pkg_manager" = "yarn" ]; then + log_message "$${GREEN}🟢 Starting project with 'yarn serve' in $project_dir$${RESET}" + nohup yarn serve >> "${LOG_PATH}" 2>&1 & + add_detected_project "$project_dir" "nodejs" "$project_port" "yarn serve" + else + log_message "$${GREEN}🟢 Starting project with 'npm run serve' in $project_dir$${RESET}" + nohup npm run serve >> "${LOG_PATH}" 2>&1 & + add_detected_project "$project_dir" "nodejs" "$project_port" "npm run serve" + fi + elif [ -n "$start_script" ]; then + if [ "$pkg_manager" = "yarn" ]; then + log_message "$${GREEN}🟢 Starting project with 'yarn start' in $project_dir$${RESET}" + nohup yarn start >> "${LOG_PATH}" 2>&1 & + add_detected_project "$project_dir" "nodejs" "$project_port" "yarn start" + else + log_message "$${GREEN}🟢 Starting project with 'npm start' in $project_dir$${RESET}" + nohup npm start >> "${LOG_PATH}" 2>&1 & + add_detected_project "$project_dir" "nodejs" "$project_port" "npm start" + fi fi - elif [ -f "yarn.lock" ] && command -v yarn &> /dev/null; then - log_message "$${GREEN}🟢 Starting yarn project with 'yarn start' in $project_dir$${RESET}" - nohup yarn start >> "${LOG_PATH}" 2>&1 & - add_detected_project "$project_dir" "nodejs" "3000" "yarn start" fi done < <(find "${WORKSPACE_DIR}" -maxdepth "${SCAN_DEPTH}" -name "package.json" -type f -print0)