Files
DevContainer User 70e74ab2d2 fix(init-repo): create $HOME before git config on fresh volumes
git config --global writes to $HOME/.gitconfig, but on a fresh PVC
$HOME (/config/userdata) doesn't exist yet. This causes the script to
fail with "could not lock config file" and exit due to set -e, leaving
the container in a crash loop with a black screen.

Move the mkdir -p $HOME + chown to the top of the script so it runs
before any git operations.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 16:47:30 +00:00

163 lines
5.7 KiB
Bash

#!/bin/bash
# Initialize repository
set -e
echo "=== Repository Initialization ==="
# Ensure home directory exists on the PVC before any git operations
# (git config --global writes to $HOME/.gitconfig, which fails on a fresh volume)
RUN_UID="${USER_ID:-1000}"
RUN_GID="${GROUP_ID:-1000}"
mkdir -p "$HOME"
chown "$RUN_UID:$RUN_GID" "$HOME"
# Set up basic git configuration
echo "Configuring git user settings..."
# Use environment variables if provided, otherwise use defaults
GIT_USER_NAME="${GIT_USER_NAME:-DevContainer User}"
GIT_USER_EMAIL="${GIT_USER_EMAIL:-devcontainer@example.com}"
git config --global user.name "$GIT_USER_NAME"
git config --global user.email "$GIT_USER_EMAIL"
# Set up git credentials early if GITHUB_TOKEN is provided
# This ensures all git operations have proper authentication
if [ -n "$GITHUB_TOKEN" ]; then
echo "Setting up git credentials..."
# Configure git to use credential store globally
git config --global credential.helper store
# Create or update the credentials file
CREDENTIALS_FILE="/config/userdata/.git-credentials"
mkdir -p "$(dirname "$CREDENTIALS_FILE")"
# Support multiple git hosting providers
# GitHub supports both oauth2 and token as username
echo "https://oauth2:${GITHUB_TOKEN}@github.com" > "$CREDENTIALS_FILE"
echo "https://${GITHUB_TOKEN}:x-oauth-basic@github.com" >> "$CREDENTIALS_FILE"
echo "https://token:${GITHUB_TOKEN}@github.com" >> "$CREDENTIALS_FILE"
# GitLab format (if same token works)
if [ -n "$GITLAB_HOST" ]; then
echo "https://oauth2:${GITHUB_TOKEN}@${GITLAB_HOST}" >> "$CREDENTIALS_FILE"
fi
chmod 600 "$CREDENTIALS_FILE"
# Also create a symlink in the home directory if it doesn't exist
# This handles cases where git might look in different locations
if [ ! -f "$HOME/.git-credentials" ] && [ "$HOME" != "/config/userdata" ]; then
ln -sf "$CREDENTIALS_FILE" "$HOME/.git-credentials"
fi
echo "Git credentials configured"
else
# Even without a token, ensure git has a proper credential helper configured
# This prevents errors when credentials are added later
echo "No GITHUB_TOKEN provided, configuring basic git settings..."
git config --global credential.helper store
# Create an empty credentials file with proper permissions
CREDENTIALS_FILE="/config/userdata/.git-credentials"
mkdir -p "$(dirname "$CREDENTIALS_FILE")"
touch "$CREDENTIALS_FILE"
chmod 600 "$CREDENTIALS_FILE"
# Create symlink if needed
if [ ! -f "$HOME/.git-credentials" ] && [ "$HOME" != "/config/userdata" ]; then
ln -sf "$CREDENTIALS_FILE" "$HOME/.git-credentials"
fi
fi
# Build list of repositories to clone
REPOS=()
if [ -n "$GITHUB_REPOS" ]; then
# GITHUB_REPOS is a comma-separated list (takes precedence over GITHUB_REPO)
IFS=',' read -ra RAW_REPOS <<< "$GITHUB_REPOS"
for repo in "${RAW_REPOS[@]}"; do
repo="$(echo "$repo" | xargs)" # trim whitespace
[ -n "$repo" ] && REPOS+=("$repo")
done
elif [ -n "$GITHUB_REPO" ]; then
REPOS+=("$GITHUB_REPO")
fi
if [ ${#REPOS[@]} -eq 0 ]; then
echo "No repositories configured, skipping clone"
WORKSPACE_DIR="/workspace/default"
mkdir -p "$WORKSPACE_DIR"
else
CLONED_DIRS=()
for REPO_URL in "${REPOS[@]}"; do
REPO_NAME=$(basename "$REPO_URL" .git)
REPO_DIR="/workspace/$REPO_NAME"
echo "Repository: $REPO_URL"
echo "Target directory: $REPO_DIR"
if [ -d "$REPO_DIR/.git" ]; then
echo "Repository already exists, pulling latest changes..."
cd "$REPO_DIR"
git pull || echo "Pull failed, continuing anyway..."
else
echo "Cloning repository..."
mkdir -p "$(dirname "$REPO_DIR")"
if [ -n "$GITHUB_TOKEN" ]; then
CLONE_URL=$(echo "$REPO_URL" | sed "s|https://github.com/|https://oauth2:${GITHUB_TOKEN}@github.com/|")
git clone "$CLONE_URL" "$REPO_DIR"
else
git clone "$REPO_URL" "$REPO_DIR"
fi
fi
CLONED_DIRS+=("$REPO_DIR")
done
if [ ${#CLONED_DIRS[@]} -eq 1 ]; then
# Single repo — open directory directly (same as legacy behavior)
WORKSPACE_DIR="${CLONED_DIRS[0]}"
else
# Multiple repos — generate a multi-root workspace file
WS_FILE="/workspace/workspace.code-workspace"
printf '{\n "folders": [\n' > "$WS_FILE"
for i in "${!CLONED_DIRS[@]}"; do
printf ' {"path": "%s"}' "${CLONED_DIRS[$i]}" >> "$WS_FILE"
if [ "$i" -lt $(( ${#CLONED_DIRS[@]} - 1 )) ]; then
printf ',\n' >> "$WS_FILE"
else
printf '\n' >> "$WS_FILE"
fi
done
printf ' ],\n "settings": {}\n}\n' >> "$WS_FILE"
WORKSPACE_DIR="$WS_FILE"
echo "Generated multi-root workspace: $WS_FILE"
fi
fi
# Set ownership using numeric IDs (username may not exist yet in baseimage-gui)
RUN_UID="${USER_ID:-1000}"
RUN_GID="${GROUP_ID:-1000}"
for dir in "${CLONED_DIRS[@]}"; do
chown -R "$RUN_UID:$RUN_GID" "$dir"
done
if [ -n "$WS_FILE" ] && [ -f "$WS_FILE" ]; then
chown "$RUN_UID:$RUN_GID" "$WS_FILE"
fi
# Ensure default workspace dir ownership if no repos were cloned
if [ ${#REPOS[@]} -eq 0 ]; then
chown -R "$RUN_UID:$RUN_GID" "$WORKSPACE_DIR"
fi
# Seed Claude Code settings if missing (disable auto-updater in Docker)
if [ ! -f "$HOME/.claude/settings.json" ]; then
mkdir -p "$HOME/.claude"
echo '{"env":{"DISABLE_AUTOUPDATER":"1"}}' > "$HOME/.claude/settings.json"
chown -R "$RUN_UID:$RUN_GID" "$HOME/.claude"
fi
# Export workspace directory for startapp.sh
echo "$WORKSPACE_DIR" > /tmp/workspace-dir
echo "=== Initialization Complete ==="