diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 00000000..fd56bddd --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,55 @@ +# React Webpack Rails Tutorial - Development Guide + +## Build and Test Commands + +```bash +# Run development server +bin/dev + +# Run tests +bundle exec rspec + +# Run linting +bundle exec rubocop + +# Auto-fix linting issues +bundle exec rubocop -a +``` + +## Conductor Compatibility (Version Managers) + +### Problem + +Conductor runs commands in a non-interactive shell that doesn't source `.zshrc`. This means version manager shell hooks (like mise's PATH reordering based on `.tool-versions`) never run. Commands will use system Ruby/Node instead of project-specified versions. + +**Symptoms:** +- `ruby --version` returns system Ruby (e.g., 2.6.10) instead of project Ruby (e.g., 3.4.3) +- Pre-commit hooks fail with wrong tool versions +- `bundle` commands fail due to incompatible Ruby versions +- Node/pnpm commands use wrong Node version + +### Solution + +Use the `bin/conductor-exec` wrapper to ensure commands run with correct tool versions: + +```bash +# Instead of: +ruby --version +bundle exec rubocop +pnpm install +git commit -m "message" + +# Use: +bin/conductor-exec ruby --version +bin/conductor-exec bundle exec rubocop +bin/conductor-exec pnpm install +bin/conductor-exec git commit -m "message" # Pre-commit hooks work correctly +``` + +The wrapper: +- Uses `mise exec` when mise is available +- Falls back to direct execution for non-mise users (asdf, rbenv, nvm, nodenv) + +### Reference + +See [react_on_rails-demos#105](https://github.com/shakacode/react_on_rails-demos/issues/105) for detailed problem analysis and solution development. diff --git a/bin/conductor-exec b/bin/conductor-exec new file mode 100755 index 00000000..02259302 --- /dev/null +++ b/bin/conductor-exec @@ -0,0 +1,24 @@ +#!/usr/bin/env zsh +# Wrapper script to run commands in Conductor with proper tool versions +# Usage: bin/conductor-exec [args...] +# +# This is needed because Conductor (and other non-interactive shells) don't +# source .zshrc, so version manager PATH configuration isn't active by default. +# +# - If mise is available: uses `mise exec` for correct tool versions +# - Otherwise: falls back to direct execution (for asdf/rbenv/nvm users) +# +# Examples: +# bin/conductor-exec ruby --version # Uses correct Ruby version +# bin/conductor-exec bundle exec rubocop # Correct Ruby for linting +# bin/conductor-exec git commit -m "msg" # Pre-commit hooks work correctly +# bin/conductor-exec pnpm install # Uses correct Node version +# +# See: https://github.com/shakacode/react_on_rails-demos/issues/105 + +if command -v mise &> /dev/null; then + exec mise exec -- "$@" +else + # Fall back to direct execution for non-mise users + exec "$@" +fi diff --git a/conductor-setup.sh b/conductor-setup.sh index cb1fd7b1..b8f880d4 100755 --- a/conductor-setup.sh +++ b/conductor-setup.sh @@ -1,30 +1,107 @@ -#!/bin/bash +#!/bin/zsh set -e echo "🚀 Setting up React on Rails workspace..." +# Detect and initialize version manager +# Supports: mise, asdf, or direct PATH (rbenv/nvm/nodenv already in PATH) +VERSION_MANAGER="none" + +echo "📋 Detecting version manager..." + +if command -v mise &> /dev/null; then + VERSION_MANAGER="mise" + echo "✅ Found mise" + # Trust mise config for current directory only and install tools + mise trust 2>/dev/null || true + mise install +elif [[ -f ~/.asdf/asdf.sh ]]; then + VERSION_MANAGER="asdf" + source ~/.asdf/asdf.sh + echo "✅ Found asdf (from ~/.asdf/asdf.sh)" +elif command -v asdf &> /dev/null; then + VERSION_MANAGER="asdf" + # For homebrew-installed asdf + if [[ -f /opt/homebrew/opt/asdf/libexec/asdf.sh ]]; then + source /opt/homebrew/opt/asdf/libexec/asdf.sh + fi + echo "✅ Found asdf" +else + echo "â„šī¸ No version manager detected, using system PATH" + echo " (Assuming rbenv/nvm/nodenv or system tools are already configured)" +fi + +# Helper function to run commands with the detected version manager +run_cmd() { + if [[ "$VERSION_MANAGER" == "mise" ]] && [[ -x "bin/conductor-exec" ]]; then + bin/conductor-exec "$@" + else + "$@" + fi +} + # Note: This project requires Ruby 3.4.6. # Please ensure you have the correct Ruby version active before running this script. +# Check required tools +echo "📋 Checking required tools..." +run_cmd ruby --version >/dev/null 2>&1 || { echo "❌ Error: Ruby is not installed or not in PATH."; exit 1; } +run_cmd node --version >/dev/null 2>&1 || { echo "❌ Error: Node.js is not installed or not in PATH."; exit 1; } + +# Check Ruby version +RUBY_VERSION=$(run_cmd ruby -v | awk '{print $2}') +MIN_RUBY_VERSION="3.0.0" +if [[ $(echo -e "$MIN_RUBY_VERSION\n$RUBY_VERSION" | sort -V | head -n1) != "$MIN_RUBY_VERSION" ]]; then + echo "❌ Error: Ruby version $RUBY_VERSION is too old. This project requires Ruby >= 3.0.0" + echo " Please upgrade Ruby using your version manager or system package manager." + exit 1 +fi +echo "✅ Ruby version: $RUBY_VERSION" + +# Check Node version +NODE_VERSION=$(run_cmd node -v | cut -d'v' -f2) +MIN_NODE_VERSION="20.0.0" +if [[ $(echo -e "$MIN_NODE_VERSION\n$NODE_VERSION" | sort -V | head -n1) != "$MIN_NODE_VERSION" ]]; then + echo "❌ Error: Node.js version v$NODE_VERSION is too old. This project requires Node.js >= 20.0.0" + echo " Please upgrade Node.js using your version manager or system package manager." + exit 1 +fi +echo "✅ Node.js version: v$NODE_VERSION" + # Copy environment files if they exist in the root -if [ -f "$CONDUCTOR_ROOT_PATH/.env" ]; then +if [[ -f "$CONDUCTOR_ROOT_PATH/.env" ]]; then cp "$CONDUCTOR_ROOT_PATH/.env" .env echo "✅ Copied .env file from root" -elif [ -f "$CONDUCTOR_ROOT_PATH/.env.example" ]; then +elif [[ -f "$CONDUCTOR_ROOT_PATH/.env.example" ]]; then cp "$CONDUCTOR_ROOT_PATH/.env.example" .env echo "✅ Copied .env.example to .env" fi -if [ -f "$CONDUCTOR_ROOT_PATH/config/database.yml" ]; then +if [[ -f "$CONDUCTOR_ROOT_PATH/.env.local" ]]; then + cp "$CONDUCTOR_ROOT_PATH/.env.local" .env.local + echo "✅ Copied .env.local file from root" +fi + +if [[ -f "$CONDUCTOR_ROOT_PATH/config/database.yml" ]]; then cp "$CONDUCTOR_ROOT_PATH/config/database.yml" config/database.yml echo "✅ Copied database.yml from root" -elif [ -f "config/database.yml.example" ]; then +elif [[ -f "config/database.yml.example" ]]; then cp config/database.yml.example config/database.yml echo "✅ Copied database.yml.example to database.yml" fi # Run the standard Rails setup script echo "🔧 Running Rails setup script..." -bin/setup --skip-server +run_cmd bin/setup --skip-server -echo "✨ Setup complete! You can now run the development server." +echo "✨ Setup complete!" +echo "" +echo "📚 Key commands:" +echo " â€ĸ bin/dev - Start development server" +echo " â€ĸ bundle exec rspec - Run tests" +echo " â€ĸ bundle exec rubocop - Run Ruby linting" +echo "" +if [[ "$VERSION_MANAGER" == "mise" ]]; then + echo "💡 Tip: Use 'bin/conductor-exec ' if tool versions aren't detected correctly." +fi +echo "âš ī¸ Remember: Always run 'bundle exec rubocop' before committing!" diff --git a/conductor.json b/conductor.json index f883f6ac..0e5ad2a9 100644 --- a/conductor.json +++ b/conductor.json @@ -1,7 +1,9 @@ { "scripts": { "setup": "./conductor-setup.sh", - "run": "bin/dev", + "run": "bin/conductor-exec bin/dev", + "test": "bin/conductor-exec bundle exec rspec", + "lint": "bin/conductor-exec bundle exec rubocop", "archive": "" }, "runScriptMode": "nonconcurrent"