Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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 .rubocop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ AllCops:
- "node_modules/**/*"
- "_actions/**/*"
- "spec/dummy-rspack/**/*"
- "bin/conductor-exec" # Shell script, not Ruby

# Prefer &&/|| over and/or.
Style/AndOr:
Expand Down
8 changes: 8 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,3 +45,11 @@
- This gem supports both webpack and rspack configurations
- Test changes with both bundlers when modifying core functionality
- Be aware of the dual package.json/Gemfile dependency management

## Conductor Environment

- **Version manager support**: The setup script detects mise, asdf, or direct PATH tools (rbenv/nvm/nodenv)
- **bin/conductor-exec**: Use this wrapper for commands when tool versions aren't detected correctly in Conductor's non-interactive shell
- Example: `bin/conductor-exec bundle exec rubocop`
- The wrapper uses `mise exec` if mise is available, otherwise falls back to direct execution
- **conductor.json scripts** already use this wrapper, so you typically don't need to use it manually
24 changes: 24 additions & 0 deletions bin/conductor-exec
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#!/bin/zsh
# Wrapper script to run commands in Conductor with proper tool versions
# Usage: bin/conductor-exec <command> [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 yarn 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
155 changes: 116 additions & 39 deletions conductor-setup.sh
Original file line number Diff line number Diff line change
@@ -1,43 +1,124 @@
#!/usr/bin/env bash
#!/bin/zsh
set -euo pipefail

echo "🔧 Setting up Shakapacker workspace..."

# Set up Ruby version if asdf is available
if command -v asdf &> /dev/null; then
echo "📝 Using asdf Ruby version management..."
# Ensure we have the right Ruby version file
echo "ruby 3.3.4" > .tool-versions
# Use asdf exec to run commands with the right Ruby version
BUNDLE_CMD="asdf exec bundle"
# 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
mise trust 2>/dev/null || true
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

style: The mise trust command trusts the mise configuration in the current directory. This is necessary for mise to work, but could be a security concern if running in untrusted repositories. The old script didn't require this trust step.

Prompt To Fix With AI
This is a comment left during a code review.
Path: conductor-setup.sh
Line: 16:16

Comment:
**style:** The `mise trust` command trusts the mise configuration in the current directory. This is necessary for mise to work, but could be a security concern if running in untrusted repositories. The old script didn't require this trust step.

How can I resolve this? If you propose a fix, please make it concise.

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
BUNDLE_CMD="bundle"
echo "ℹ️ No version manager detected, using system PATH"
echo " (Assuming rbenv/nvm/nodenv or system tools are already configured)"
fi

# Ensure version config exists for asdf/mise users
if [[ "$VERSION_MANAGER" != "none" ]] && [[ ! -f .tool-versions ]] && [[ ! -f .mise.toml ]]; then
echo "📝 Creating .tool-versions from project version files..."

# Read Ruby version from .ruby-version or use default
if [[ -f .ruby-version ]]; then
RUBY_VER=$(cat .ruby-version | tr -d '[:space:]')
else
RUBY_VER="3.3.4" # Default: recent stable Ruby
fi

# Read Node version from .node-version or use default
if [[ -f .node-version ]]; then
NODE_VER=$(cat .node-version | tr -d '[:space:]')
else
NODE_VER="20.18.0" # Default: LTS Node
fi

cat > .tool-versions << EOF
ruby $RUBY_VER
nodejs $NODE_VER
EOF
echo " Using Ruby $RUBY_VER, Node $NODE_VER"
fi

# Check for required tools
if ! $BUNDLE_CMD --version &> /dev/null; then
echo "❌ Error: Ruby bundler is not installed"
echo "Please install bundler first: gem install bundler"
# Install tools via mise (after .tool-versions exists)
if [[ "$VERSION_MANAGER" == "mise" ]]; then
echo "📦 Installing tools via mise..."
mise install
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
}

# 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="2.7.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. Shakapacker requires Ruby >= 2.7.0"
echo " Please upgrade Ruby using your version manager or system package manager."
exit 1
fi
echo "✅ Ruby version: $RUBY_VERSION"

if ! command -v yarn &> /dev/null; then
echo "❌ Error: Yarn is not installed"
echo "Please install yarn first"
# Check Node version
NODE_VERSION=$(run_cmd node -v | cut -d'v' -f2)
MIN_NODE_VERSION="14.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. Shakapacker requires Node.js >= 14.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 any environment files from root if they exist
if [ -n "${CONDUCTOR_ROOT_PATH:-}" ]; then
if [ -f "$CONDUCTOR_ROOT_PATH/.env" ]; then
echo "📝 Copying .env file..."
cp "$CONDUCTOR_ROOT_PATH/.env" .env
fi

if [ -f "$CONDUCTOR_ROOT_PATH/.env.local" ]; then
echo "📝 Copying .env.local file..."
cp "$CONDUCTOR_ROOT_PATH/.env.local" .env.local
fi
fi

# Install Ruby dependencies
echo "📦 Installing Ruby dependencies..."
$BUNDLE_CMD install
echo "💎 Installing Ruby dependencies..."
run_cmd bundle install

# Install JavaScript dependencies
echo "📦 Installing JavaScript dependencies..."
yarn install --frozen-lockfile
run_cmd yarn install --frozen-lockfile

# Set up Husky git hooks
echo "🪝 Setting up Husky git hooks..."
npx husky
run_cmd npx husky
if [ ! -f .husky/pre-commit ]; then
echo "Creating pre-commit hook..."
cat > .husky/pre-commit << 'EOF'
Expand All @@ -47,24 +128,20 @@ EOF
chmod +x .husky/pre-commit
fi

# Copy environment files if they exist in root
if [ -n "${CONDUCTOR_ROOT_PATH:-}" ]; then
if [ -f "$CONDUCTOR_ROOT_PATH/.env" ]; then
echo "📋 Copying .env file from root..."
cp "$CONDUCTOR_ROOT_PATH/.env" .env
fi

if [ -f "$CONDUCTOR_ROOT_PATH/.env.local" ]; then
echo "📋 Copying .env.local file from root..."
cp "$CONDUCTOR_ROOT_PATH/.env.local" .env.local
fi
fi
# Verify linting tools are available
echo "✅ Verifying linting tools..."
run_cmd bundle exec rubocop --version

echo " Workspace setup complete!"
echo " Workspace setup complete!"
echo ""
echo "Available commands:"
echo " - Run tests: bundle exec rspec"
echo " - Run specific test suites: bundle exec rake run_spec:gem"
echo " - Run JavaScript tests: yarn test"
echo " - Lint JavaScript: yarn lint"
echo " - Lint Ruby: bundle exec rubocop"
echo "📚 Key commands:"
echo " • bundle exec rspec - Run Ruby tests"
echo " • bundle exec rake run_spec:gem - Run gem-specific tests"
echo " • yarn test - Run JavaScript tests"
echo " • yarn lint - Run JavaScript linting"
echo " • bundle exec rubocop - Run Ruby linting (required before commits)"
echo ""
if [[ "$VERSION_MANAGER" == "mise" ]]; then
echo "💡 Tip: Use 'bin/conductor-exec <command>' if tool versions aren't detected correctly."
fi
echo "⚠️ Remember: Always run 'bundle exec rubocop' before committing!"
4 changes: 3 additions & 1 deletion conductor.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
{
"scripts": {
"setup": "./conductor-setup.sh",
"run": "bundle exec rspec",
"run": "bin/conductor-exec bundle exec rspec",
"test": "bin/conductor-exec bundle exec rspec",
"lint": "bin/conductor-exec bundle exec rubocop && bin/conductor-exec yarn lint",
"archive": ""
}
}