diff --git a/scripts/local-docker-build-push.sh b/scripts/local-docker-build-push.sh new file mode 100755 index 000000000..48d27b2ba --- /dev/null +++ b/scripts/local-docker-build-push.sh @@ -0,0 +1,182 @@ +#!/bin/bash +set -e + +# ============================================================================= +# Local Docker Release Script +# ============================================================================= +# Build and push Docker images locally instead of waiting for GitHub Actions. +# Useful when CI is slow (Rust compile step) or failing. +# +# Prerequisites: +# - Docker with buildx: docker buildx create --use (if not already set up) +# - GHCR login: echo $GITHUB_TOKEN | docker login ghcr.io -u USERNAME --password-stdin +# - Docker Hub login: docker login (for all-in-one image) +# +# Usage: +# ./scripts/local-release.sh [options] +# +# Options: +# --version VERSION Version to release (e.g., 0.26.0). Auto-detected if not specified. +# --multi Build and push multi-container images (postgres, api, client, etc.) +# --aio Build and push all-in-one image +# --all Build all Docker images +# --dry-run Show what would be done without executing +# --skip-push Build but don't push (loads to local Docker instead) +# --amd64-only Build for amd64 only (faster, useful for testing) +# ============================================================================= + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +ROOT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)" + +# Colors +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' + +# Defaults +VERSION="" +BUILD_MULTI=false +BUILD_AIO=false +DRY_RUN=false +SKIP_PUSH=false +AMD64_ONLY=false + +while [[ $# -gt 0 ]]; do + case $1 in + --version) VERSION="$2"; shift 2 ;; + --multi) BUILD_MULTI=true; shift ;; + --aio) BUILD_AIO=true; shift ;; + --all) BUILD_MULTI=true; BUILD_AIO=true; shift ;; + --dry-run) DRY_RUN=true; shift ;; + --skip-push) SKIP_PUSH=true; shift ;; + --amd64-only) AMD64_ONLY=true; shift ;; + -h|--help) head -28 "$0" | tail -25; exit 0 ;; + *) echo -e "${RED}Unknown option: $1${NC}"; exit 1 ;; + esac +done + +if [[ "$BUILD_MULTI" == "false" && "$BUILD_AIO" == "false" ]]; then + echo "Usage: ./scripts/local-release.sh [--multi] [--aio] [--all] [options]" + echo "" + echo "Examples:" + echo " ./scripts/local-release.sh --aio # Build & push all-in-one" + echo " ./scripts/local-release.sh --multi # Build & push multi-container" + echo " ./scripts/local-release.sh --all # Build everything" + echo " ./scripts/local-release.sh --aio --dry-run # Preview commands" + echo " ./scripts/local-release.sh --aio --skip-push # Build locally only" + echo " ./scripts/local-release.sh --aio --amd64-only # Faster single-platform build" + exit 1 +fi + +# Auto-detect version +if [[ -z "$VERSION" ]]; then + VERSION=$(node -p "require('$ROOT_DIR/apps/browser-extension/package.json').version") +fi + +echo -e "${GREEN}======================================${NC}" +echo -e "${GREEN}AliasVault Docker Release - v$VERSION${NC}" +echo -e "${GREEN}======================================${NC}" +echo "" + +[[ "$DRY_RUN" == "true" ]] && echo -e "${YELLOW}DRY RUN MODE${NC}" && echo "" + +# Platform selection +if [[ "$AMD64_ONLY" == "true" ]]; then + PLATFORMS="linux/amd64" +else + PLATFORMS="linux/amd64,linux/arm64" +fi + +run_cmd() { + if [[ "$DRY_RUN" == "true" ]]; then + echo -e "${BLUE}[DRY RUN]${NC} $*" + else + echo -e "${GREEN}$${NC} $*" + eval "$@" + fi +} + +build_multi() { + echo -e "${GREEN}Building Multi-Container Images${NC}" + echo "" + cd "$ROOT_DIR" + + local images=( + "postgres:apps/server/Databases/AliasServerDb/Dockerfile" + "api:apps/server/AliasVault.Api/Dockerfile" + "client:apps/server/AliasVault.Client/Dockerfile" + "admin:apps/server/AliasVault.Admin/Dockerfile" + "reverse-proxy:apps/server/Dockerfile" + "smtp:apps/server/Services/AliasVault.SmtpService/Dockerfile" + "task-runner:apps/server/Services/AliasVault.TaskRunner/Dockerfile" + "installcli:apps/server/Utilities/AliasVault.InstallCli/Dockerfile" + ) + + local push_flag="" + if [[ "$SKIP_PUSH" == "false" ]]; then + push_flag="--push" + fi + # Without --push, buildx builds but doesn't output anywhere (validates the build) + + for item in "${images[@]}"; do + local name="${item%%:*}" + local dockerfile="${item#*:}" + + echo -e "${BLUE}→ ghcr.io/aliasvault/$name:$VERSION${NC}" + + run_cmd "docker buildx build \\ + --platform $PLATFORMS \\ + -f $dockerfile \\ + -t ghcr.io/aliasvault/$name:$VERSION \\ + -t ghcr.io/aliasvault/$name:latest \\ + $push_flag \\ + ." + echo "" + done +} + +build_aio() { + echo -e "${GREEN}Building All-in-One Image${NC}" + echo "" + cd "$ROOT_DIR" + + local push_flag="" + if [[ "$SKIP_PUSH" == "false" ]]; then + push_flag="--push" + fi + # Without --push, buildx builds but doesn't output anywhere (validates the build) + + echo -e "${BLUE}→ aliasvault/aliasvault:$VERSION${NC}" + + run_cmd "docker buildx build \\ + --platform $PLATFORMS \\ + -f dockerfiles/all-in-one/Dockerfile \\ + -t ghcr.io/aliasvault/aliasvault:$VERSION \\ + -t ghcr.io/aliasvault/aliasvault:latest \\ + -t aliasvault/aliasvault:$VERSION \\ + -t aliasvault/aliasvault:latest \\ + $push_flag \\ + ." +} + +# Check Docker +if ! command -v docker &> /dev/null; then + echo -e "${RED}Docker not found${NC}" + exit 1 +fi + +# Ensure buildx is available +if ! docker buildx version &> /dev/null; then + echo -e "${RED}Docker buildx not available. Run: docker buildx create --use${NC}" + exit 1 +fi + +[[ "$BUILD_MULTI" == "true" ]] && build_multi +[[ "$BUILD_AIO" == "true" ]] && build_aio + +echo "" +echo -e "${GREEN}Done!${NC}" +[[ "$DRY_RUN" == "true" ]] && echo -e "${YELLOW}(dry run - no changes made)${NC}" +[[ "$SKIP_PUSH" == "true" ]] && echo -e "${YELLOW}(skip-push - built locally only)${NC}"