Files
code-tools/tf/scripts/workspace-setup.sh

306 lines
11 KiB
Bash
Executable File

#!/bin/bash
set -e
# Set proper locale for emoji and UTF-8 support
export LANG=en_US.UTF-8
export LC_ALL=en_US.UTF-8
echo "🚀 Initializing development environment as user: $(whoami)"
# =============================================================================
# Create coder user if it doesn't exist
# =============================================================================
if ! id -u coder >/dev/null 2>&1; then
echo "👤 Creating coder user..."
useradd -m -s /bin/bash coder
usermod -aG sudo coder
echo "coder ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers
elif [ "$(id -u coder)" != "1000" ]; then
echo "👤 Coder user exists but with different UID, updating..."
usermod -u 1000 coder
fi
# =============================================================================
# Create necessary directories
# =============================================================================
echo "📁 Creating user directories..."
mkdir -p /home/coder/bin
mkdir -p /home/coder/.local/bin
mkdir -p /home/coder/.config
mkdir -p /tmp/git-metadata
mkdir -p /workspaces
# Ensure proper ownership (only if coder user exists, excluding read-only bind mounts)
if id -u coder >/dev/null 2>&1; then
chown -R coder:coder /home/coder/.local /home/coder/.config /home/coder/bin /workspaces
# Set ownership for coder home directory files (not subdirectories that might be bind mounted)
find /home/coder -maxdepth 1 -type f -exec chown coder:coder {} \; 2>/dev/null || true
fi
# =============================================================================
# Switch to coder user for remaining operations
# =============================================================================
echo "🔄 Switching to coder user context..."
export HOME=/home/coder
export USER=coder
# =============================================================================
# Git Configuration
# =============================================================================
echo "⚙️ Configuring Git..."
git config --global user.name "${GIT_AUTHOR_NAME}"
git config --global user.email "${GIT_AUTHOR_EMAIL}"
git config --global commit.gpgsign false
git config --global tag.gpgsign false
git config --global init.defaultBranch main
git config --global pull.rebase false
# Capture and log git information
echo "📝 Capturing Git metadata..."
cd /workspaces
if [ -d ".git" ]; then
git branch --show-current > /tmp/git-metadata/current-branch 2>/dev/null || echo "main" > /tmp/git-metadata/current-branch
git rev-parse HEAD > /tmp/git-metadata/commit-hash 2>/dev/null || echo "no-commits" > /tmp/git-metadata/commit-hash
git remote get-url origin > /tmp/git-metadata/remote-url 2>/dev/null || echo "no-remote" > /tmp/git-metadata/remote-url
else
echo "no-repo" > /tmp/git-metadata/current-branch
echo "no-repo" > /tmp/git-metadata/commit-hash
echo "no-repo" > /tmp/git-metadata/remote-url
fi
# =============================================================================
# System Package Updates and Installation
# =============================================================================
echo "📦 Installing system packages..."
export DEBIAN_FRONTEND=noninteractive
apt-get update -qq
apt-get install -y make tree jq curl wget unzip build-essential postgresql-client redis-tools ripgrep fd-find
# =============================================================================
# Node.js and npm Setup (as coder user)
# =============================================================================
echo "🟢 Setting up Node.js and npm..."
# Completely remove any existing npm caches and config files
rm -rf /home/coder/.npm /home/coder/.npm-global /home/coder/.npmrc 2>/dev/null || true
rm -rf /root/.npm /root/.npmrc 2>/dev/null || true
# Create coder user directories with proper permissions
mkdir -p /home/coder
chown coder:coder /home/coder
# DO NOT pre-create npm cache directories - let npm create them as the coder user
mkdir -p /home/coder/.npm-global/{lib,bin}
chown -R coder:coder /home/coder/.npm-global 2>/dev/null || true
# Create Node.js setup script
cat > /tmp/node_setup.sh << 'NODE_SCRIPT_END'
#!/bin/bash
# Create bash profile first
echo 'export NVM_DIR="$HOME/.nvm"' >> ~/.bashrc
echo '[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"' >> ~/.bashrc
echo '[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion"' >> ~/.bashrc
# Clean any npmrc files that might conflict with nvm
rm -f ~/.npmrc /home/coder/.npmrc 2>/dev/null || true
# Verify npm directories exist and are owned by coder
ls -la ~/.npm ~/.npm-global || echo "npm directories ready"
if ! command -v nvm &> /dev/null; then
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.0/install.sh | bash
fi
# Load nvm properly
export NVM_DIR="/home/coder/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh"
[ -s "$NVM_DIR/bash_completion" ] && . "$NVM_DIR/bash_completion"
nvm install ${NODE_VERSION}
nvm use ${NODE_VERSION}
nvm alias default ${NODE_VERSION}
# Clean npm config that conflicts with nvm
npm config delete globalconfig 2>/dev/null || true
npm config delete prefix 2>/dev/null || true
# Let npm create its cache directory naturally
# Create npm-global lib directory structure
mkdir -p ~/.npm-global/{lib,bin}
# Configure npm to use user-writable directories
npm config set prefix ~/.npm-global
echo 'export PATH=~/.npm-global/bin:$PATH' >> ~/.bashrc
export PATH=~/.npm-global/bin:$PATH
# Verify npm configuration
echo "📋 npm configuration:"
npm config get prefix
npm config get cache
echo "📦 Installing npm packages..."
npm install -g repomix create-next-app nodemon concurrently @types/node typescript eslint prettier
NODE_SCRIPT_END
chmod +x /tmp/node_setup.sh
su - coder -c "/tmp/node_setup.sh"
rm /tmp/node_setup.sh
# =============================================================================
# Python Setup with uv (as coder user)
# =============================================================================
echo "🐍 Setting up Python and uv..."
# Install Python version (add deadsnakes PPA for newer Python versions)
if [[ "${PYTHON_VERSION}" > "3.10" ]]; then
echo "📦 Adding deadsnakes PPA for Python ${PYTHON_VERSION}..."
apt-get install -y software-properties-common
add-apt-repository ppa:deadsnakes/ppa -y
apt-get update
fi
apt-get install -y python${PYTHON_VERSION} python${PYTHON_VERSION}-dev python${PYTHON_VERSION}-venv || {
echo "⚠️ Python ${PYTHON_VERSION} not available, falling back to default Python 3"
apt-get install -y python3 python3-dev python3-venv
export PYTHON_VERSION="3"
}
# Create Python setup script
cat > /tmp/python_setup.sh << 'PYTHON_SCRIPT_END'
#!/bin/bash
curl -LsSf https://astral.sh/uv/install.sh | sh
export PATH="/home/coder/.cargo/bin:$PATH"
echo "📦 Installing Python packages with uv..."
for package in fastapi uvicorn requests pandas numpy psycopg2-binary redis qdrant-client python-dotenv; do
uv tool install $package || echo "Failed to install $package"
done
uv venv /home/coder/.venv --python=${PYTHON_VERSION}
echo 'source /home/coder/.venv/bin/activate' >> /home/coder/.bashrc
PYTHON_SCRIPT_END
chmod +x /tmp/python_setup.sh
su - coder -c "/tmp/python_setup.sh"
rm /tmp/python_setup.sh
# =============================================================================
# Rust and Cargo Setup (as coder user)
# =============================================================================
echo "🦀 Installing Rust and Cargo..."
# Create Rust setup script
cat > /tmp/rust_setup.sh << 'RUST_SCRIPT_END'
#!/bin/bash
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --default-toolchain stable
source "/home/coder/.cargo/env"
echo 'export PATH="/home/coder/.cargo/bin:$PATH"' >> /home/coder/.bashrc
cargo install cargo-watch cargo-edit cargo-audit
RUST_SCRIPT_END
chmod +x /tmp/rust_setup.sh
su - coder -c "/tmp/rust_setup.sh"
rm /tmp/rust_setup.sh
# =============================================================================
# repomix Installation (as coder user)
# =============================================================================
echo "📁 Installing repomix..."
su - coder -c "npm install -g repomix"
# =============================================================================
# Shell Configuration (as coder user)
# =============================================================================
echo "🐚 Setting up shell environment..."
# Create devinfo script
cat > /tmp/devinfo_script.sh << 'DEVINFO_SCRIPT_END'
#!/bin/bash
mkdir -p /home/coder/bin
cat > /home/coder/bin/devinfo << 'DEVINFO_END'
#!/bin/bash
echo '🚀 Development Environment Info'
echo '==============================='
echo ''
echo '🔧 Installed Tools:'
echo ' Node.js: '$(node --version 2>/dev/null || echo 'Not found')
echo ' npm: '$(npm --version 2>/dev/null || echo 'Not found')
echo ' Python: '$(python${PYTHON_VERSION} --version 2>/dev/null || echo 'Not found')
echo ' uv: '$(uv --version 2>/dev/null || echo 'Not found')
echo ' Rust: '$(rustc --version 2>/dev/null || echo 'Not found')
echo ' Cargo: '$(cargo --version 2>/dev/null || echo 'Not found')
echo ' repomix: '$(repomix --version 2>/dev/null || echo 'Not found')
echo ''
echo '🗄️ Database Services:'
if [ "${ENABLE_SERVICES}" = "true" ]; then
echo ' PostgreSQL: '${POSTGRES_URL}
echo ' Redis: '${REDIS_URL}
echo ' Qdrant: '${QDRANT_URL}
else
echo ' Services disabled'
fi
echo ''
echo '📝 Git Metadata:'
if [ -f /tmp/git-metadata/current-branch ]; then
echo ' Branch: '$(cat /tmp/git-metadata/current-branch)
echo ' Commit: '$(cat /tmp/git-metadata/commit-hash)
echo ' Remote: '$(cat /tmp/git-metadata/remote-url)
fi
DEVINFO_END
chmod +x /home/coder/bin/devinfo
DEVINFO_SCRIPT_END
chmod +x /tmp/devinfo_script.sh
su - coder -c "/tmp/devinfo_script.sh"
rm /tmp/devinfo_script.sh
# Create bashrc aliases script
cat > /tmp/bashrc_setup.sh << 'BASHRC_SCRIPT_END'
#!/bin/bash
cat >> /home/coder/.bashrc << 'BASHRC_END'
# Development Environment Aliases
alias ll='ls -alF'
alias la='ls -A'
alias l='ls -CF'
alias gs='git status'
alias gp='git push'
alias gc='git commit'
alias gco='git checkout'
alias gb='git branch'
# Development workflow shortcuts
alias devinfo='/home/coder/bin/devinfo'
# Package managers
alias pip='uv pip'
alias python='python${PYTHON_VERSION}'
# Docker shortcuts
alias dps='docker ps'
alias dimg='docker images'
alias dlog='docker logs'
BASHRC_END
BASHRC_SCRIPT_END
chmod +x /tmp/bashrc_setup.sh
su - coder -c "/tmp/bashrc_setup.sh"
rm /tmp/bashrc_setup.sh
# =============================================================================
# Final Environment Setup
# =============================================================================
echo "✅ Development environment initialization complete!"
echo ""
echo "🎉 Available tools:"
echo " - Node.js ${NODE_VERSION} with npm packages"
echo " - Python ${PYTHON_VERSION} with uv package manager"
echo " - Rust with Cargo"
echo " - repomix for repository packaging"
echo " - make, tree, and other build tools"
if [ "${ENABLE_SERVICES}" = "true" ]; then
echo " - PostgreSQL, Redis, Qdrant databases"
fi
echo ""
echo "🔧 Run 'devinfo' for detailed environment information"
echo "🚀 Ready for development!"