Skip to content

Instantly share code, notes, and snippets.

@jcdarwin
Last active September 15, 2025 21:45
Show Gist options
  • Select an option

  • Save jcdarwin/4657eef6987d221d0aca0d4ca0bf2bd6 to your computer and use it in GitHub Desktop.

Select an option

Save jcdarwin/4657eef6987d221d0aca0d4ca0bf2bd6 to your computer and use it in GitHub Desktop.
#!/bin/bash
# Git Worktree Setup Script for Conductor
# Sets up a new git workspace for the askyourteam repo (https://github.com/askyourteam-nz/askyourteam)
# under Conductor (https://docs.conductor.build/).
# This script should be run from within a new git worktree directory
# It symlinks necessary files and directories from the main worktree
# This allows us to use git worktrees, sharing the folders from the main directory that
# are not under version control (e.g. node_modules).
set -e
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
# Main worktree directory (current directory where this script is located)
CONDUCTOR_ROOT_PATH="/Users/jason/workspace/askyourteam"
# Function to print colored output
print_status() {
echo -e "${GREEN}[INFO]${NC} $1"
}
print_warning() {
echo -e "${YELLOW}[WARN]${NC} $1"
}
print_error() {
echo -e "${RED}[ERROR]${NC} $1"
}
# If the workspace name is not filesystem-safe, abort
if ! echo "$CONDUCTOR_WORKSPACE_NAME" | sed 's/[^a-zA-Z0-9_-]/_/g' >/dev/null 2>&1; then
print_error "Workspace name is not filesystem-safe"
exit 1
fi
print_status "CONDUCTOR_WORKSPACE_NAME: $CONDUCTOR_WORKSPACE_NAME"
print_status "CONDUCTOR_WORKSPACE_PATH: $CONDUCTOR_WORKSPACE_PATH"
print_status "CONDUCTOR_ROOT_PATH: $CONDUCTOR_ROOT_PATH"
print_status "CONDUCTOR_DEFAULT_BRANCH: $CONDUCTOR_DEFAULT_BRANCH"
# Verify we're not running from the main worktree
if [ "$CONDUCTOR_WORKSPACE_PATH" = "$CONDUCTOR_ROOT_PATH" ]; then
print_error "This script should be run from a git worktree, not the main worktree"
exit 1
fi
# Verify main worktree exists
if [ ! -d "$CONDUCTOR_ROOT_PATH" ]; then
print_error "Main worktree directory does not exist: $CONDUCTOR_ROOT_PATH"
exit 1
fi
# Create symlink function
create_symlink() {
local source="$1"
local target="$2"
local description="$3"
# Check if source exists in main worktree
if [ ! -e "$CONDUCTOR_ROOT_PATH/$source" ]; then
print_warning "Skipping $description - source does not exist: $CONDUCTOR_ROOT_PATH/$source"
return 0
fi
# Remove existing target if it exists
if [ -e "$target" ] || [ -L "$target" ]; then
print_status "Removing existing $description"
rm -rf "$target"
fi
# Create parent directory if needed
local target_dir=$(dirname "$target")
if [ ! -d "$target_dir" ]; then
mkdir -p "$target_dir"
fi
# Create symlink
print_status "Linking $description"
ln -sf "$CONDUCTOR_ROOT_PATH/$source" "$target"
}
# Files and directories to symlink
# Format: source_path:target_path:description
SYMLINKS=(
# .claude preferences
".claude:.claude:.claude preferences"
# Node.js dependencies
"node_modules:node_modules:Node.js modules"
# Webpack/Asset compilation outputs
"public/packs:public/packs:Webpack compiled assets"
"public/packs-test:public/packs-test:Webpack test assets"
# Generated/uploaded content
# "public/uploads:public/uploads:User uploads"
# "public/user:public/user:User files"
# "public/system:public/system:System files"
# "public/account:public/account:Account files"
# "public/image:public/image:Image files"
# "public/assets:public/assets:Asset files"
# "public/question_image:public/question_image:Question images"
# Logs and temporary files
# "log:log:Application logs"
# "logs:logs:Additional logs"
# "tmp:tmp:Temporary files"
# Coverage reports
# "coverage:coverage:Test coverage reports"
# Backups
# "backups:backups:Database backups"
# Build artifacts
# "results:results:Build results"
# Bundle/gem cache
".bundle:.bundle:Bundler cache"
# Environment files (if they exist)
".env.development.local:.env.development.local:Local development environment"
".env.test.local:.env.test.local:Local test environment"
# IDE and editor files
# ".idea:.idea:IntelliJ IDEA files"
# ".vscode:.vscode:VSCode settings"
# Git hooks and configuration (optional)
# ".overcommit.yml:.overcommit.yml:Overcommit configuration"
# Build configuration files that might be generated
# ".sentryclirc:.sentryclirc:Sentry CLI configuration"
# Ruby/Rails specific cache and history
# ".irb_history:.irb_history:IRB history"
# ".byebug_history:.byebug_history:Byebug history"
# Yarn files
# "yarn-error.log:yarn-error.log:Yarn error log"
# ".yarn-integrity:.yarn-integrity:Yarn integrity file"
# Other generated files
# ".out-storybook:.out-storybook:Storybook build output"
)
# Process symlinks
print_status "Creating symlinks..."
for item in "${SYMLINKS[@]}"; do
IFS=':' read -r source target description <<< "$item"
create_symlink "$source" "$target" "$description"
done
# Create necessary directories that might not exist
print_status "Creating additional required directories..."
# Directories that need to exist but might not be in main worktree
REQUIRED_DIRS=(
"tmp/pids"
"tmp/cache"
"tmp/sockets"
"log"
"public/uploads"
)
for dir in "${REQUIRED_DIRS[@]}"; do
if [ ! -d "$dir" ]; then
print_status "Creating directory: $dir"
mkdir -p "$dir"
fi
done
print_status "Worktree setup complete!"
print_status ""
print_status "Next steps:"
print_status "1. Run 'bundle install' if needed (gems should be shared via .bundle symlink)"
print_status "2. Run 'yarn install' if needed (node_modules is symlinked)"
print_status "3. The following are now symlinked from main worktree:"
print_status " - node_modules (JavaScript dependencies)"
print_status " - public/packs* (webpack compiled assets)"
print_status " - log, tmp, coverage (runtime directories)"
print_status " - Database backups and other generated content"
print_status ""
print_warning "Note: Database and Redis are shared across all worktrees"
print_warning "Be mindful when running migrations or making schema changes"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment