refactor: implement clean modular Electron build system
Replace chained npm commands with single build-electron.sh script supporting multiple build modes (dev/test/prod), platforms (windows/mac/linux), and package types (appimage/deb/dmg). Add platform validation to prevent cross-platform build issues and integrate cleaning functionality. - Replace 15+ chained npm scripts with single modular build script - Add platform detection and validation with early failure on mismatch - Support environment-specific builds (development/test/production) - Add comprehensive documentation in docs/electron-build-patterns.md - Update BUILDING.md with new build patterns and examples - Remove legacy electron:build:* scripts and consolidate under build:electron:* - Add clean:electron script integrated into build process - Improve error handling and user feedback throughout build process This refactoring follows DRY principles, eliminates command chaining, and provides a more maintainable and user-friendly build system.
This commit is contained in:
@@ -1,32 +1,36 @@
|
||||
#!/bin/bash
|
||||
# build-electron.sh
|
||||
# Author: Matthew Raymer
|
||||
# Description: Electron build script for TimeSafari application
|
||||
# This script handles the complete Electron build process including cleanup,
|
||||
# web build, Capacitor build, TypeScript compilation, and Electron packaging.
|
||||
# Description: Clean, modular Electron build script for TimeSafari application
|
||||
# This script handles Electron builds with proper separation of concerns and
|
||||
# no command chaining, following DRY principles.
|
||||
#
|
||||
# Usage:
|
||||
# ./scripts/build-electron.sh # Development build (runs app)
|
||||
# ./scripts/build-electron.sh --dev # Development build (runs app)
|
||||
# ./scripts/build-electron.sh --package # Package build (creates distributable)
|
||||
# ./scripts/build-electron.sh --appimage # Build AppImage package
|
||||
# ./scripts/build-electron.sh --deb # Build Debian package
|
||||
# ./scripts/build-electron.sh --test # Test environment build
|
||||
# ./scripts/build-electron.sh --prod # Production environment build
|
||||
# ./scripts/build-electron.sh --windows # Windows build
|
||||
# ./scripts/build-electron.sh --mac # macOS build
|
||||
# ./scripts/build-electron.sh --linux # Linux build
|
||||
# ./scripts/build-electron.sh --appimage # Linux AppImage
|
||||
# ./scripts/build-electron.sh --deb # Debian package
|
||||
# ./scripts/build-electron.sh --dmg # macOS DMG
|
||||
# ./scripts/build-electron.sh --help # Show help
|
||||
# ./scripts/build-electron.sh --verbose # Enable verbose logging
|
||||
#
|
||||
# NPM Script Equivalents:
|
||||
# npm run build:electron # Development build
|
||||
# npm run build:electron:package # Package build
|
||||
# npm run build:electron:appimage # AppImage package
|
||||
# npm run build:electron:deb # Debian package
|
||||
# Examples:
|
||||
# ./scripts/build-electron.sh --prod --windows # Windows production build
|
||||
# ./scripts/build-electron.sh --test --appimage # Linux AppImage test build
|
||||
# ./scripts/build-electron.sh --dev --mac # macOS development build
|
||||
#
|
||||
# Exit Codes:
|
||||
# 1 - Electron cleanup failed
|
||||
# 2 - Web build failed
|
||||
# 3 - Capacitor build failed
|
||||
# 4 - TypeScript compilation failed
|
||||
# 5 - Electron packaging failed
|
||||
# 6 - Capacitor sync failed
|
||||
# 1 - Invalid arguments
|
||||
# 2 - Electron cleanup failed
|
||||
# 3 - Web build failed
|
||||
# 4 - Capacitor sync failed
|
||||
# 5 - TypeScript compilation failed
|
||||
# 6 - Electron packaging failed
|
||||
# 7 - Asset generation failed
|
||||
# 8 - Electron app launch failed
|
||||
|
||||
@@ -36,112 +40,379 @@ set -e
|
||||
# Source common utilities
|
||||
source "$(dirname "$0")/common.sh"
|
||||
|
||||
# Parse command line arguments
|
||||
parse_args "$@"
|
||||
|
||||
# Print build header
|
||||
print_header "TimeSafari Electron Build Process"
|
||||
log_info "Starting Electron build process at $(date)"
|
||||
|
||||
# Setup environment for Electron build
|
||||
setup_build_env "electron"
|
||||
|
||||
# Setup application directories
|
||||
setup_app_directories
|
||||
|
||||
# Load environment from .env file if it exists
|
||||
load_env_file ".env"
|
||||
|
||||
# Step 1: Clean Electron app
|
||||
safe_execute "Cleaning Electron app" "npm run clean:electron || true" || exit 1
|
||||
|
||||
# Step 2: Clean dist directory
|
||||
log_info "Cleaning dist directory..."
|
||||
clean_build_artifacts "dist" "electron/app"
|
||||
|
||||
# Step 3: Build Capacitor version for Electron
|
||||
safe_execute "Building Electron version" "npm run build:electron" || exit 2
|
||||
|
||||
# Step 4: Prepare Electron app directory
|
||||
log_info "Preparing Electron app directory..."
|
||||
mkdir -p electron/app
|
||||
|
||||
# Step 5: Copy built files to Electron
|
||||
safe_execute "Copying web assets to Electron" "cp -r dist/* electron/app/" || exit 3
|
||||
|
||||
# Step 6: Validate and copy Capacitor configuration
|
||||
safe_execute "Validating Capacitor configuration" "cp capacitor.config.json electron/capacitor.config.json" || exit 3
|
||||
|
||||
# Step 7: Navigate to electron directory and build TypeScript
|
||||
safe_execute "Compiling TypeScript" "cd electron && npm run build && cd .." || exit 4
|
||||
|
||||
# Step 8: Sync with Capacitor (if needed)
|
||||
safe_execute "Syncing with Capacitor" "npx cap sync electron || true" || exit 6
|
||||
|
||||
# Step 9: Generate assets (if available)
|
||||
safe_execute "Generating assets" "npx capacitor-assets generate --electron || true" || exit 7
|
||||
|
||||
# Determine build action based on arguments
|
||||
# Default values
|
||||
BUILD_MODE="development"
|
||||
BUILD_PLATFORM=""
|
||||
BUILD_PACKAGE=""
|
||||
BUILD_ACTION="dev"
|
||||
PACKAGE_TYPE=""
|
||||
VERBOSE=false
|
||||
|
||||
# Parse additional arguments for build type
|
||||
for arg in "$@"; do
|
||||
case $arg in
|
||||
--package|--build)
|
||||
BUILD_ACTION="package"
|
||||
# Parse command line arguments
|
||||
parse_electron_args() {
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case $1 in
|
||||
--dev|--development)
|
||||
BUILD_MODE="development"
|
||||
BUILD_ACTION="dev"
|
||||
shift
|
||||
;;
|
||||
--test)
|
||||
BUILD_MODE="test"
|
||||
BUILD_ACTION="package"
|
||||
shift
|
||||
;;
|
||||
--prod|--production)
|
||||
BUILD_MODE="production"
|
||||
BUILD_ACTION="package"
|
||||
shift
|
||||
;;
|
||||
--windows)
|
||||
BUILD_PLATFORM="windows"
|
||||
shift
|
||||
;;
|
||||
--mac)
|
||||
BUILD_PLATFORM="mac"
|
||||
shift
|
||||
;;
|
||||
--linux)
|
||||
BUILD_PLATFORM="linux"
|
||||
shift
|
||||
;;
|
||||
--appimage)
|
||||
BUILD_PACKAGE="appimage"
|
||||
BUILD_PLATFORM="linux"
|
||||
shift
|
||||
;;
|
||||
--deb)
|
||||
BUILD_PACKAGE="deb"
|
||||
BUILD_PLATFORM="linux"
|
||||
shift
|
||||
;;
|
||||
--dmg)
|
||||
BUILD_PACKAGE="dmg"
|
||||
BUILD_PLATFORM="mac"
|
||||
shift
|
||||
;;
|
||||
--help)
|
||||
show_electron_help
|
||||
exit 0
|
||||
;;
|
||||
--clean)
|
||||
BUILD_ACTION="clean"
|
||||
shift
|
||||
;;
|
||||
--verbose)
|
||||
VERBOSE=true
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
log_error "Unknown argument: $1"
|
||||
show_electron_help
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
}
|
||||
|
||||
# Show help information
|
||||
show_electron_help() {
|
||||
cat << EOF
|
||||
TimeSafari Electron Build Script
|
||||
|
||||
Usage: $0 [OPTIONS]
|
||||
|
||||
Build Modes:
|
||||
--dev, --development Development build (runs app)
|
||||
--test Test environment build
|
||||
--prod, --production Production environment build
|
||||
--clean Clean Electron build artifacts only
|
||||
|
||||
Platforms:
|
||||
--windows Windows build
|
||||
--mac macOS build
|
||||
--linux Linux build
|
||||
|
||||
Packages:
|
||||
--appimage Linux AppImage
|
||||
--deb Debian package
|
||||
--dmg macOS DMG
|
||||
|
||||
Options:
|
||||
--verbose Enable verbose logging
|
||||
--help Show this help message
|
||||
|
||||
Platform Validation:
|
||||
The script validates that the target platform matches the current
|
||||
execution platform. Cross-platform builds are not supported and
|
||||
will fail with an error message.
|
||||
|
||||
Examples:
|
||||
$0 --prod --windows # Windows production build
|
||||
$0 --test --appimage # Linux AppImage test build
|
||||
$0 --dev --mac # macOS development build
|
||||
$0 --prod # Production build for all platforms
|
||||
$0 --clean # Clean Electron build artifacts only
|
||||
|
||||
EOF
|
||||
}
|
||||
|
||||
# Build web assets for Electron
|
||||
build_web_assets() {
|
||||
local mode=$1
|
||||
log_info "Building web assets for Electron (mode: $mode)"
|
||||
|
||||
if [[ "$mode" == "development" ]]; then
|
||||
safe_execute "Building web assets" "VITE_GIT_HASH=\$(git log -1 --pretty=format:%h) vite build --config vite.config.electron.mts"
|
||||
else
|
||||
safe_execute "Building web assets" "VITE_GIT_HASH=\$(git log -1 --pretty=format:%h) vite build --mode $mode --config vite.config.electron.mts"
|
||||
fi
|
||||
}
|
||||
|
||||
# Sync with Capacitor
|
||||
sync_capacitor() {
|
||||
log_info "Syncing with Capacitor"
|
||||
safe_execute "Capacitor sync" "npx cap sync electron || true"
|
||||
}
|
||||
|
||||
# Copy web assets to Electron
|
||||
copy_web_assets() {
|
||||
log_info "Copying web assets to Electron"
|
||||
safe_execute "Copying assets" "cp -r dist/* electron/app/"
|
||||
safe_execute "Copying config" "cp capacitor.config.json electron/capacitor.config.json"
|
||||
}
|
||||
|
||||
# Compile TypeScript
|
||||
compile_typescript() {
|
||||
log_info "Compiling TypeScript"
|
||||
safe_execute "TypeScript compilation" "cd electron && npm run build && cd .."
|
||||
}
|
||||
|
||||
# Generate assets
|
||||
generate_assets() {
|
||||
log_info "Generating assets"
|
||||
safe_execute "Asset generation" "npx capacitor-assets generate --electron || true"
|
||||
}
|
||||
|
||||
# Clean Electron build artifacts
|
||||
clean_electron_artifacts() {
|
||||
log_info "Cleaning Electron build artifacts"
|
||||
|
||||
# Clean Electron build directory
|
||||
if [[ -d "electron/build" ]]; then
|
||||
safe_execute "Cleaning Electron build directory" "rm -rf electron/build"
|
||||
fi
|
||||
|
||||
# Clean Electron dist directory (packaged apps)
|
||||
if [[ -d "electron/dist" ]]; then
|
||||
safe_execute "Cleaning Electron dist directory" "rm -rf electron/dist"
|
||||
fi
|
||||
|
||||
# Clean Electron app directory (web assets)
|
||||
if [[ -d "electron/app" ]]; then
|
||||
safe_execute "Cleaning Electron app directory" "rm -rf electron/app"
|
||||
fi
|
||||
|
||||
# Clean TypeScript compilation artifacts
|
||||
if [[ -d "electron/src" ]]; then
|
||||
safe_execute "Cleaning TypeScript artifacts" "find electron/src -name '*.js' -delete 2>/dev/null || true"
|
||||
safe_execute "Cleaning TypeScript artifacts" "find electron/src -name '*.js.map' -delete 2>/dev/null || true"
|
||||
fi
|
||||
|
||||
log_info "✅ Electron build artifacts cleaned"
|
||||
}
|
||||
|
||||
# Detect current platform
|
||||
detect_current_platform() {
|
||||
case "$(uname -s)" in
|
||||
Linux*)
|
||||
echo "linux"
|
||||
;;
|
||||
--appimage)
|
||||
BUILD_ACTION="package"
|
||||
PACKAGE_TYPE="appimage"
|
||||
Darwin*)
|
||||
echo "mac"
|
||||
;;
|
||||
--deb)
|
||||
BUILD_ACTION="package"
|
||||
PACKAGE_TYPE="deb"
|
||||
;;
|
||||
--dev|--development)
|
||||
BUILD_ACTION="dev"
|
||||
CYGWIN*|MINGW32*|MSYS*|MINGW*)
|
||||
echo "windows"
|
||||
;;
|
||||
*)
|
||||
# Ignore unknown arguments
|
||||
log_error "Unknown platform: $(uname -s)"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
}
|
||||
|
||||
# Execute build action
|
||||
case $BUILD_ACTION in
|
||||
"package")
|
||||
if [ -n "$PACKAGE_TYPE" ]; then
|
||||
safe_execute "Building Electron package ($PACKAGE_TYPE)" "cd electron && ./build-packages.sh $PACKAGE_TYPE && cd .." || exit 5
|
||||
else
|
||||
safe_execute "Building Electron package" "cd electron && ./build-packages.sh && cd .." || exit 5
|
||||
fi
|
||||
;;
|
||||
"dev")
|
||||
safe_execute "Starting Electron development app" "cd electron && npm run electron:start && cd .." || exit 8
|
||||
;;
|
||||
*)
|
||||
log_error "Unknown build action: $BUILD_ACTION"
|
||||
# Validate platform compatibility
|
||||
validate_platform_compatibility() {
|
||||
local target_platform=$1
|
||||
local current_platform=$2
|
||||
|
||||
if [[ -n "$target_platform" && "$target_platform" != "$current_platform" ]]; then
|
||||
log_error "❌ Platform mismatch detected!"
|
||||
log_error " Target platform: $target_platform"
|
||||
log_error " Current platform: $current_platform"
|
||||
log_error ""
|
||||
log_error "Cross-platform builds are not supported."
|
||||
log_error "Please run this build on the target platform: $target_platform"
|
||||
log_error ""
|
||||
log_error "Examples:"
|
||||
log_error " - For Windows builds: Run on Windows or WSL"
|
||||
log_error " - For macOS builds: Run on macOS"
|
||||
log_error " - For Linux builds: Run on Linux"
|
||||
log_error ""
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
}
|
||||
|
||||
# Print build summary
|
||||
case $BUILD_ACTION in
|
||||
"package")
|
||||
log_success "Electron package build completed successfully!"
|
||||
if [ -d "electron/dist" ]; then
|
||||
log_info "Package files available in: electron/dist/"
|
||||
ls -la electron/dist/ || true
|
||||
fi
|
||||
;;
|
||||
"dev")
|
||||
log_success "Electron development build completed successfully!"
|
||||
log_info "Electron app should now be running"
|
||||
;;
|
||||
esac
|
||||
# Build Electron package
|
||||
build_electron_package() {
|
||||
local platform=$1
|
||||
local package=$2
|
||||
|
||||
log_info "Building Electron package (platform: $platform, package: $package)"
|
||||
|
||||
cd electron
|
||||
|
||||
if [[ -n "$package" ]]; then
|
||||
case "$package" in
|
||||
"appimage")
|
||||
safe_execute "Building AppImage" "npm run build:appimage"
|
||||
;;
|
||||
"deb")
|
||||
safe_execute "Building DEB package" "npm run build:deb"
|
||||
;;
|
||||
"dmg")
|
||||
safe_execute "Building DMG package" "npm run build:dmg"
|
||||
;;
|
||||
*)
|
||||
log_error "Unknown package type: $package"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
else
|
||||
case "$platform" in
|
||||
"windows")
|
||||
safe_execute "Building Windows package" "npm run build:windows"
|
||||
;;
|
||||
"mac")
|
||||
safe_execute "Building macOS package" "npm run build:mac"
|
||||
;;
|
||||
"linux")
|
||||
safe_execute "Building Linux package" "npm run build:linux"
|
||||
;;
|
||||
*)
|
||||
log_error "Unknown platform: $platform"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
cd ..
|
||||
}
|
||||
|
||||
print_footer "Electron Build"
|
||||
# Start Electron development
|
||||
start_electron_dev() {
|
||||
log_info "Starting Electron development"
|
||||
safe_execute "Starting Electron" "cd electron && npm run electron:start && cd .."
|
||||
}
|
||||
|
||||
# Main build function
|
||||
main_electron_build() {
|
||||
# Parse arguments
|
||||
parse_electron_args "$@"
|
||||
|
||||
# Print build header
|
||||
print_header "TimeSafari Electron Build Process"
|
||||
local current_platform=$(detect_current_platform)
|
||||
log_info "Build mode: $BUILD_MODE"
|
||||
log_info "Build platform: ${BUILD_PLATFORM:-all}"
|
||||
log_info "Build package: ${BUILD_PACKAGE:-none}"
|
||||
log_info "Build action: $BUILD_ACTION"
|
||||
log_info "Current platform: $current_platform"
|
||||
|
||||
# Early platform validation (before any build work)
|
||||
if [[ "$BUILD_ACTION" == "package" && -n "$BUILD_PLATFORM" ]]; then
|
||||
log_info "Validating platform compatibility..."
|
||||
validate_platform_compatibility "$BUILD_PLATFORM" "$current_platform"
|
||||
log_info "✅ Platform validation passed"
|
||||
fi
|
||||
|
||||
# Setup environment
|
||||
setup_build_env "electron"
|
||||
setup_app_directories
|
||||
load_env_file ".env"
|
||||
|
||||
# Step 1: Clean Electron build artifacts
|
||||
clean_electron_artifacts
|
||||
|
||||
# Step 2: Clean dist directory
|
||||
log_info "Cleaning dist directory..."
|
||||
clean_build_artifacts "dist" "electron/app"
|
||||
|
||||
# Step 3: Build web assets
|
||||
build_web_assets "$BUILD_MODE"
|
||||
|
||||
# Step 4: Prepare Electron app directory
|
||||
log_info "Preparing Electron app directory..."
|
||||
mkdir -p electron/app
|
||||
|
||||
# Step 5: Copy web assets
|
||||
copy_web_assets
|
||||
|
||||
# Step 6: Compile TypeScript
|
||||
compile_typescript
|
||||
|
||||
# Step 7: Sync with Capacitor
|
||||
sync_capacitor
|
||||
|
||||
# Step 8: Generate assets
|
||||
generate_assets
|
||||
|
||||
# Step 9: Execute build action
|
||||
case $BUILD_ACTION in
|
||||
"clean")
|
||||
clean_electron_artifacts
|
||||
log_success "Electron build artifacts cleaned successfully!"
|
||||
print_footer "Electron Clean"
|
||||
exit 0
|
||||
;;
|
||||
"dev")
|
||||
start_electron_dev
|
||||
;;
|
||||
"package")
|
||||
if [[ -n "$BUILD_PLATFORM" ]]; then
|
||||
build_electron_package "$BUILD_PLATFORM" "$BUILD_PACKAGE"
|
||||
else
|
||||
log_info "No specific platform requested, building for all platforms"
|
||||
build_electron_package "windows" "$BUILD_PACKAGE"
|
||||
build_electron_package "mac" "$BUILD_PACKAGE"
|
||||
build_electron_package "linux" "$BUILD_PACKAGE"
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
log_error "Unknown build action: $BUILD_ACTION"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
# Print build summary
|
||||
case $BUILD_ACTION in
|
||||
"package")
|
||||
log_success "Electron package build completed successfully!"
|
||||
if [[ -d "electron/dist" ]]; then
|
||||
log_info "Package files available in: electron/dist/"
|
||||
ls -la electron/dist/ || true
|
||||
fi
|
||||
;;
|
||||
"dev")
|
||||
log_success "Electron development build completed successfully!"
|
||||
log_info "Electron app should now be running"
|
||||
;;
|
||||
esac
|
||||
|
||||
print_footer "Electron Build"
|
||||
}
|
||||
|
||||
# Run main function with all arguments
|
||||
main_electron_build "$@"
|
||||
|
||||
# Exit with success
|
||||
exit 0
|
||||
Reference in New Issue
Block a user