Files
gremiumhub/pipeline.sh

562 lines
15 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/bin/bash
set -e
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
MAGENTA='\033[0;35m'
NC='\033[0m'
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
TEMP_DIR=$(mktemp -d)
DEPLOY_FLAG=false
RUN_FRONTEND=true
RUN_BACKEND=true
RUN_LANDING=true
cleanup() {
rm -rf "$TEMP_DIR"
}
trap cleanup EXIT
log_info() {
echo -e "${BLUE} ${NC}$1"
}
log_success() {
echo -e "${GREEN}${NC} $1"
}
log_error() {
echo -e "${RED}${NC} $1"
}
log_warning() {
echo -e "${YELLOW}${NC} $1"
}
prefix_output() {
local prefix=$1
local color=$2
while IFS= read -r line; do
echo -e "${color}[${prefix}]${NC} $line"
done
}
show_help() {
cat << EOF
Usage: $(basename "$0") [OPTIONS]
CI/CD Pipeline Script - Runs frontend, backend, and landing builds in parallel with optional deployment
OPTIONS:
--deploy Deploy to server after successful build
--frontend-only Run only the frontend job
--backend-only Run only the backend job
--landing-only Run only the landing page job
--no-frontend Skip the frontend job
--no-backend Skip the backend job
--no-landing Skip the landing page job
--help Show this help message
EXAMPLES:
$(basename "$0") # Run all jobs in parallel
$(basename "$0") --deploy # Run all jobs and deploy
$(basename "$0") --frontend-only # Run only frontend job
$(basename "$0") --backend-only # Run only backend job
$(basename "$0") --landing-only # Run only landing page job
$(basename "$0") --no-landing # Run frontend and backend only
$(basename "$0") --frontend-only --deploy # Run frontend and deploy
ENVIRONMENT:
GIT_SHA Git commit SHA (default: current HEAD)
NOTE:
On macOS, the script will automatically launch in a new iTerm window.
EOF
exit 0
}
check_command() {
if ! command -v "$1" &> /dev/null; then
log_error "Required command '$1' not found. Please install it first."
exit 1
fi
}
check_version() {
local cmd=$1
local expected=$2
local version_arg=$3
local version_output=$($cmd $version_arg 2>&1 || true)
log_info "Checking $cmd version (expected: $expected)"
echo " Found: $version_output"
}
validate_environment() {
log_info "Validating environment..."
check_command "node"
check_command "pnpm"
check_command "java"
check_command "docker"
if [ "$DEPLOY_FLAG" = true ]; then
check_command "ssh"
fi
check_version "node" "22.16.0" "--version"
check_version "java" "21" "--version"
if [ -z "$GIT_SHA" ]; then
GIT_SHA=$(git rev-parse HEAD 2>/dev/null || echo "unknown")
export GIT_SHA
log_info "GIT_SHA set to: $GIT_SHA"
fi
log_success "Environment validation completed"
}
frontend_job() {
local log_file="$TEMP_DIR/frontend.log"
local use_prefix=$1
(
set +e
echo "==================== FRONTEND JOB ===================="
log_info "Starting frontend build..."
cd "$SCRIPT_DIR/legalconsenthub" || exit 1
log_info "Installing dependencies..."
pnpm install --frozen-lockfile
if [ $? -ne 0 ]; then
log_error "Dependencies installation failed"
exit 1
fi
log_success "Dependencies installed"
log_info "Running linting..."
pnpm lint
if [ $? -ne 0 ]; then
log_error "Linting failed"
exit 1
fi
log_success "Linting passed"
log_info "Running type checking..."
pnpm type-check
if [ $? -ne 0 ]; then
log_error "Type checking failed"
exit 1
fi
log_success "Type checking passed"
log_info "Building Docker image..."
docker buildx build \
--platform linux/amd64 \
--tag "gitea.lugnas.de/denis/legalconsenthub:latest" \
--tag "gitea.lugnas.de/denis/legalconsenthub:$GIT_SHA" \
--file ./Dockerfile \
--cache-from type=local,src="$SCRIPT_DIR/.buildx-cache/frontend" \
--cache-to type=local,dest="$SCRIPT_DIR/.buildx-cache/frontend",mode=max \
--push \
..
if [ $? -ne 0 ]; then
log_error "Docker build failed"
exit 1
fi
log_success "Docker image built and pushed successfully"
log_info "Image: gitea.lugnas.de/denis/legalconsenthub:latest"
log_info "Image: gitea.lugnas.de/denis/legalconsenthub:$GIT_SHA"
exit 0
) 2>&1 | if [ "$use_prefix" = true ]; then prefix_output "FRONTEND" "$BLUE"; else cat; fi | tee "$log_file"
return ${PIPESTATUS[0]}
}
backend_job() {
local log_file="$TEMP_DIR/backend.log"
local use_prefix=$1
(
set +e
echo "==================== BACKEND JOB ===================="
log_info "Starting backend build..."
cd "$SCRIPT_DIR/legalconsenthub-backend" || exit 1
log_info "Building application..."
./gradlew build -x test
if [ $? -ne 0 ]; then
log_error "Build failed"
exit 1
fi
log_success "Build completed"
log_info "Running ktlint check..."
./gradlew ktlintCheck
if [ $? -ne 0 ]; then
log_error "ktlint check failed"
exit 1
fi
log_success "ktlint check passed"
log_info "Running tests..."
./gradlew test
if [ $? -ne 0 ]; then
log_error "Tests failed"
exit 1
fi
log_success "Tests passed"
log_info "Building Docker image..."
mkdir -p "$SCRIPT_DIR/.buildx-cache/backend"
docker buildx build \
--platform linux/amd64 \
--tag "gitea.lugnas.de/denis/legalconsenthub-backend:latest" \
--tag "gitea.lugnas.de/denis/legalconsenthub-backend:$GIT_SHA" \
--file ./Dockerfile \
--cache-from type=local,src="$SCRIPT_DIR/.buildx-cache/backend" \
--cache-to type=local,dest="$SCRIPT_DIR/.buildx-cache/backend",mode=max \
--push \
..
if [ $? -ne 0 ]; then
log_error "Docker build failed"
exit 1
fi
log_success "Docker image built and pushed successfully"
log_info "Image: gitea.lugnas.de/denis/legalconsenthub-backend:latest"
log_info "Image: gitea.lugnas.de/denis/legalconsenthub-backend:$GIT_SHA"
exit 0
) 2>&1 | if [ "$use_prefix" = true ]; then prefix_output "BACKEND" "$GREEN"; else cat; fi | tee "$log_file"
return ${PIPESTATUS[0]}
}
landing_job() {
local log_file="$TEMP_DIR/landing.log"
local use_prefix=$1
(
set +e
echo "==================== LANDING JOB ===================="
log_info "Starting landing page build..."
cd "$SCRIPT_DIR/landing" || exit 1
log_info "Installing dependencies..."
pnpm install --frozen-lockfile
if [ $? -ne 0 ]; then
log_error "Dependencies installation failed"
exit 1
fi
log_success "Dependencies installed"
log_info "Running linting..."
pnpm lint
if [ $? -ne 0 ]; then
log_error "Linting failed"
exit 1
fi
log_success "Linting passed"
log_info "Running type checking..."
pnpm type-check
if [ $? -ne 0 ]; then
log_error "Type checking failed"
exit 1
fi
log_success "Type checking passed"
log_info "Building Docker image..."
mkdir -p "$SCRIPT_DIR/.buildx-cache/landing"
docker buildx build \
--platform linux/amd64 \
--tag "gitea.lugnas.de/denis/legalconsenthub-landing:latest" \
--tag "gitea.lugnas.de/denis/legalconsenthub-landing:$GIT_SHA" \
--file ./Dockerfile \
--cache-from type=local,src="$SCRIPT_DIR/.buildx-cache/landing" \
--cache-to type=local,dest="$SCRIPT_DIR/.buildx-cache/landing",mode=max \
--push \
..
if [ $? -ne 0 ]; then
log_error "Docker build failed"
exit 1
fi
log_success "Docker image built and pushed successfully"
log_info "Image: gitea.lugnas.de/denis/legalconsenthub-landing:latest"
log_info "Image: gitea.lugnas.de/denis/legalconsenthub-landing:$GIT_SHA"
exit 0
) 2>&1 | if [ "$use_prefix" = true ]; then prefix_output "LANDING" "$MAGENTA"; else cat; fi | tee "$log_file"
return ${PIPESTATUS[0]}
}
run_jobs() {
local job_count=0
[ "$RUN_FRONTEND" = true ] && ((job_count++))
[ "$RUN_BACKEND" = true ] && ((job_count++))
[ "$RUN_LANDING" = true ] && ((job_count++))
local run_parallel=false
if [ "$job_count" -gt 1 ]; then
run_parallel=true
log_info "Starting $job_count parallel jobs..."
else
log_info "Starting job..."
fi
echo ""
local frontend_exit=0
local backend_exit=0
local landing_exit=0
if [ "$run_parallel" = true ]; then
local frontend_pid=""
local backend_pid=""
local landing_pid=""
if [ "$RUN_FRONTEND" = true ]; then
frontend_job true &
frontend_pid=$!
log_info "Frontend PID: $frontend_pid"
fi
if [ "$RUN_BACKEND" = true ]; then
backend_job true &
backend_pid=$!
log_info "Backend PID: $backend_pid"
fi
if [ "$RUN_LANDING" = true ]; then
landing_job true &
landing_pid=$!
log_info "Landing PID: $landing_pid"
fi
log_info "Waiting for jobs to complete..."
echo ""
set +e
if [ -n "$frontend_pid" ]; then
wait $frontend_pid
frontend_exit=$?
fi
if [ -n "$backend_pid" ]; then
wait $backend_pid
backend_exit=$?
fi
if [ -n "$landing_pid" ]; then
wait $landing_pid
landing_exit=$?
fi
set -e
else
if [ "$RUN_FRONTEND" = true ]; then
set +e
frontend_job false
frontend_exit=$?
set -e
fi
if [ "$RUN_BACKEND" = true ]; then
set +e
backend_job false
backend_exit=$?
set -e
fi
if [ "$RUN_LANDING" = true ]; then
set +e
landing_job false
landing_exit=$?
set -e
fi
fi
echo ""
echo "==================== JOB SUMMARY ===================="
local has_failure=false
if [ "$RUN_FRONTEND" = true ]; then
if [ "$frontend_exit" -eq 0 ]; then
log_success "Frontend job completed successfully"
else
log_error "Frontend job failed with exit code $frontend_exit"
has_failure=true
fi
fi
if [ "$RUN_BACKEND" = true ]; then
if [ "$backend_exit" -eq 0 ]; then
log_success "Backend job completed successfully"
else
log_error "Backend job failed with exit code $backend_exit"
has_failure=true
fi
fi
if [ "$RUN_LANDING" = true ]; then
if [ "$landing_exit" -eq 0 ]; then
log_success "Landing job completed successfully"
else
log_error "Landing job failed with exit code $landing_exit"
has_failure=true
fi
fi
if [ "$has_failure" = true ]; then
log_error "One or more jobs failed. Aborting pipeline."
exit 1
fi
log_success "All jobs completed successfully"
}
launch_in_iterm() {
log_info "Launching pipeline in new iTerm window..."
local script_path="$0"
local args=""
for arg in "$@"; do
args="$args $arg"
done
osascript <<EOF
tell application "iTerm"
create window with default profile
tell current session of current window
write text "cd '$SCRIPT_DIR' && PIPELINE_IN_ITERM=1 bash '$script_path'$args"
end tell
activate
end tell
EOF
log_success "Pipeline launched in iTerm window"
exit 0
}
deploy() {
if [ "$DEPLOY_FLAG" = false ]; then
log_info "Deployment skipped (use --deploy flag to enable)"
return 0
fi
echo ""
echo "==================== DEPLOYMENT ===================="
log_info "Starting deployment to server..."
ssh -i ~/.ssh/gitea_deploy -p 32766 -o StrictHostKeyChecking=accept-new deploy@ds218 "sudo /usr/local/bin/deployLegalconsenthub.sh"
log_success "Deployment triggered successfully"
log_success "Application is being deployed to production"
}
main() {
local original_args=("$@")
local only_flag_used=false
while [[ $# -gt 0 ]]; do
case $1 in
--deploy)
DEPLOY_FLAG=true
shift
;;
--frontend-only)
if [ "$only_flag_used" = true ]; then
log_error "Cannot combine multiple --*-only flags"
exit 1
fi
only_flag_used=true
RUN_FRONTEND=true
RUN_BACKEND=false
RUN_LANDING=false
shift
;;
--backend-only)
if [ "$only_flag_used" = true ]; then
log_error "Cannot combine multiple --*-only flags"
exit 1
fi
only_flag_used=true
RUN_FRONTEND=false
RUN_BACKEND=true
RUN_LANDING=false
shift
;;
--landing-only)
if [ "$only_flag_used" = true ]; then
log_error "Cannot combine multiple --*-only flags"
exit 1
fi
only_flag_used=true
RUN_FRONTEND=false
RUN_BACKEND=false
RUN_LANDING=true
shift
;;
--no-frontend)
RUN_FRONTEND=false
shift
;;
--no-backend)
RUN_BACKEND=false
shift
;;
--no-landing)
RUN_LANDING=false
shift
;;
--help)
show_help
;;
*)
log_error "Unknown option: $1"
show_help
;;
esac
done
if [ "$RUN_FRONTEND" = false ] && [ "$RUN_BACKEND" = false ] && [ "$RUN_LANDING" = false ]; then
log_error "No jobs to run. At least one job must be enabled."
exit 1
fi
if [ "$(uname)" = "Darwin" ] && [ -z "$PIPELINE_IN_ITERM" ]; then
launch_in_iterm "${original_args[@]}"
fi
echo "==================== CI/CD PIPELINE ===================="
log_info "Pipeline started at $(date)"
echo ""
validate_environment
echo ""
run_jobs
deploy
echo ""
echo "==================== PIPELINE COMPLETE ===================="
log_success "Pipeline completed successfully at $(date)"
}
main "$@"