#!/bin/bash set -e GITHUB_DIR="/build/github" INITRAMFS_ROOT="/build/initramfs" CACHE_TIMEOUT=3600 # 1 hour cache echo "[+] Fetching GitHub components..." # DIAGNOSTIC: Check GitHub connectivity and cache echo "[DEBUG] Checking GitHub connectivity..." echo "[DEBUG] Cache directory: $GITHUB_DIR" echo "[DEBUG] Existing cache files: $(ls -la $GITHUB_DIR 2>/dev/null | wc -l)" echo "[DEBUG] GitHub API rate limit check..." github_status=$(curl -s -I https://api.github.com/repos/threefoldtech/zinit/releases/latest | head -1 | awk '{print $2}') echo "[DEBUG] GitHub API response code: $github_status" if [ "$github_status" != "200" ]; then echo "[DEBUG] WARNING: GitHub API may be inaccessible - code: $github_status" fi echo "[DEBUG] Available tools: curl=$(command -v curl >/dev/null && echo 'YES' || echo 'NO'), wget=$(command -v wget >/dev/null && echo 'YES' || echo 'NO')" # Create cache directory mkdir -p "$GITHUB_DIR" # Function to get latest release info get_latest_release() { local repo="$1" local cache_file="$GITHUB_DIR/${repo//\//_}_release.json" # Check cache first if [ -f "$cache_file" ] && [ $(($(date +%s) - $(stat -c %Y "$cache_file"))) -lt $CACHE_TIMEOUT ]; then cat "$cache_file" return fi # Fetch latest release info local api_url="https://api.github.com/repos/$repo/releases/latest" echo " Fetching release info for $repo..." >&2 if command -v curl >/dev/null; then curl -s "$api_url" | tee "$cache_file" else wget -qO- "$api_url" | tee "$cache_file" fi } # Function to extract download URL from release JSON get_download_url() { local release_json="$1" local pattern="$2" echo "$release_json" | grep -o '"browser_download_url": *"[^"]*"' | \ grep "$pattern" | head -1 | cut -d '"' -f 4 } # Function to download with retry download_with_retry() { local url="$1" local output="$2" local max_attempts=3 local attempt=1 while [ $attempt -le $max_attempts ]; do echo " Attempt $attempt/$max_attempts..." if command -v curl >/dev/null; then if curl -L --fail -o "$output" "$url"; then return 0 fi else if wget -O "$output" "$url"; then return 0 fi fi attempt=$((attempt + 1)) if [ $attempt -le $max_attempts ]; then echo " Retrying in 5 seconds..." sleep 5 fi done echo " Error: Failed to download after $max_attempts attempts" >&2 return 1 } # Function to download and install binary install_github_binary() { local repo="$1" local binary_name="$2" local install_path="$3" local download_pattern="$4" echo " Installing: $repo -> $install_path/$binary_name" # Get release information local release_json=$(get_latest_release "$repo") if [ -z "$release_json" ]; then echo " Error: Failed to get release info for $repo" >&2 echo "[DEBUG] GitHub API call failed for $repo - check network/rate limits" return 1 fi # Check if this is a "Not Found" response if echo "$release_json" | grep -q '"message": *"Not Found"'; then echo " Error: Repository $repo not found or has no releases" >&2 echo "[DEBUG] Repository $repo does not exist or has no releases" return 1 fi echo "[DEBUG] Successfully fetched release info for $repo" # Extract version for logging local version=$(echo "$release_json" | grep '"tag_name"' | cut -d '"' -f 4) echo " Version: $version" # Get download URL local download_url=$(get_download_url "$release_json" "$download_pattern") if [ -z "$download_url" ]; then echo " Error: No matching release found for pattern: $download_pattern" >&2 return 1 fi echo " Downloading: $(basename "$download_url")" local filename=$(basename "$download_url") local download_path="$GITHUB_DIR/$filename" # Download if not cached if [ ! -f "$download_path" ]; then download_with_retry "$download_url" "$download_path" else echo " Using cached file" fi # Create install directory mkdir -p "$INITRAMFS_ROOT$install_path" # Extract and install based on file type case "$filename" in *.tar.gz|*.tgz) echo " Extracting tar.gz..." tar -xzf "$download_path" -C "$GITHUB_DIR" # Find the binary in extracted files local extracted_binary=$(find "$GITHUB_DIR" -name "$binary_name" -type f -executable | head -1) if [ -n "$extracted_binary" ]; then cp "$extracted_binary" "$INITRAMFS_ROOT$install_path/$binary_name" else echo " Error: Binary '$binary_name' not found in archive" >&2 return 1 fi ;; *.zip) echo " Extracting zip..." unzip -q "$download_path" -d "$GITHUB_DIR" local extracted_binary=$(find "$GITHUB_DIR" -name "$binary_name" -type f -executable | head -1) if [ -n "$extracted_binary" ]; then cp "$extracted_binary" "$INITRAMFS_ROOT$install_path/$binary_name" else echo " Error: Binary '$binary_name' not found in archive" >&2 return 1 fi ;; *) # Assume it's a direct binary echo " Installing direct binary..." cp "$download_path" "$INITRAMFS_ROOT$install_path/$binary_name" ;; esac # Make executable chmod +x "$INITRAMFS_ROOT$install_path/$binary_name" # Verify installation if [ -x "$INITRAMFS_ROOT$install_path/$binary_name" ]; then echo " Success: $install_path/$binary_name installed" else echo " Error: Failed to install $binary_name" >&2 return 1 fi } # Function to clone source repository for compilation clone_source_repo() { local repo="$1" local target_dir="$2" echo " Cloning source: $repo -> $target_dir" # Check if directory already exists and is a git repo if [ -d "$target_dir/.git" ]; then echo " Repository already exists, updating..." cd "$target_dir" git fetch origin git reset --hard HEAD cd - >/dev/null else # Remove any existing non-git directory if [ -d "$target_dir" ]; then echo " Removing existing non-git directory..." rm -rf "$target_dir" fi # Clone repository (use default branch) echo " Cloning https://github.com/$repo.git..." git clone "https://github.com/$repo.git" "$target_dir" fi echo " ✓ Source repository cloned: $target_dir" } # Install each component echo "" # Clone source repositories for compilation COMPONENTS_DIR="/build/components" mkdir -p "$COMPONENTS_DIR" # Zinit - Clone source for compilation clone_source_repo "threefoldtech/zinit" "$COMPONENTS_DIR/zinit" # Mycelium - Clone source for compilation clone_source_repo "threefoldtech/mycelium" "$COMPONENTS_DIR/mycelium" # RFS - Clone source for compilation clone_source_repo "threefoldtech/rfs" "$COMPONENTS_DIR/rfs" # Core-X - Container control (still download binary as it's not in compile-components.sh) echo " Checking: threefoldtech/core-x" if install_github_binary "threefoldtech/core-x" "core-x" "/usr/bin" "linux.*amd64"; then echo " Core-X installed successfully" else echo " Warning: Core-X repository not found or no releases available - continuing without it" fi # Seektime - Disk detection (still download binary as it's not in compile-components.sh) install_github_binary "threefoldtech/seektime" "seektime" "/usr/bin" "linux-amd64" echo "" echo "[+] GitHub components setup completed" # Show cloned source repositories echo "" echo "[+] Cloned source repositories:" for repo in "zinit" "mycelium" "rfs"; do if [ -d "$COMPONENTS_DIR/$repo/.git" ]; then echo " $repo (source cloned for compilation)" else echo " $repo (MISSING)" fi done # Show installed binaries info echo "" echo "[+] Downloaded binary components:" for binary in "/usr/bin/core-x" "/usr/bin/seektime"; do if [ -x "$INITRAMFS_ROOT$binary" ]; then size=$(stat -c%s "$INITRAMFS_ROOT$binary" 2>/dev/null || echo "unknown") echo " $binary (${size} bytes)" else echo " $binary (MISSING)" fi done echo "" echo "[+] Note: zinit, mycelium, and rfs will be compiled from source using compile-components.sh"