PlusMagi's Blog By Pitt Phunsanit CI/CD,GIT,Java,Shell Script CI/CD: build java ใน Workspace

CI/CD: build java ใน Workspace

เป็น script ที่เขียนให้ไล่ดูใน workspace แล้ว build java ใหม่ถ้า code มีการเปลี่ยนแปลง
cd-java-all-projects.sh

#!/bin/bash
set -e

# Record the start time
START_TIME=$(date +%s)

echo "=========================================="
echo "☕️ Scanning for Maven / Java Projects..."
echo "=========================================="

ROOT_DIR="$(pwd)"
FAILED_LOG="$ROOT_DIR/.failed_java_projects.log"
WARNINGS_LOG="$ROOT_DIR/.java_build_warnings.log"
ERRORS_LOG="$ROOT_DIR/.java_build_errors.log"

# Clear temporary log files before starting
> "$FAILED_LOG"
> "$WARNINGS_LOG"
> "$ERRORS_LOG"

# Function to log warnings
add_warning() {
    local msg="$1"
    echo "⚠️  $msg"
    echo "$msg" >> "$WARNINGS_LOG"
}

# Encapsulate build logic in a function to allow retries
process_project() {
    local dir="$1"
    local is_retry="$2"

    # Use absolute path to prevent directory traversal issues during retry
    cd "$ROOT_DIR/$dir" || return 1

    # Check if it is a Maven project
    POM_FILE=""
    if [ -f "pom.xml" ]; then
        POM_FILE="pom.xml"
    elif [ -f "mvnw" ]; then
         # Look for a parent POM if mvnw exists
         POM_FILE=$(find . -maxdepth 3 -name "pom.xml" | grep "parent" | head -n 1 || true)
         if [ -z "$POM_FILE" ]; then
              POM_FILE=$(find . -maxdepth 3 -name "pom.xml" | head -n 1 || true)
         fi
    fi

    if [ -n "$POM_FILE" ]; then
        if [ "$is_retry" == "true" ]; then
             echo "🔄 [Retry] Checking Maven in '$dir' (POM: $POM_FILE)..."
        else
             echo "🔍 Checking Maven in '$dir' (POM: $POM_FILE)..."
        fi

        # Find latest timestamp of Source Code (Java, XML, Properties)
        # Exclude target directory
        LATEST_SRC=$(find . -type f \( -name "*.java" -o -name "*.xml" -o -name "*.properties" \) -not -path "*/target/*" -print0 | xargs -0 stat -f "%m" 2>/dev/null | sort -rn | head -1)
        if [ -z "$LATEST_SRC" ]; then LATEST_SRC=0; fi

        # Find timestamp of the built JAR artifact
        LATEST_BUILD=0
        LATEST_BUILD_FILE=$(find . -type f -name "*.jar" -path "*/target/*" -print0 | xargs -0 stat -f "%m" 2>/dev/null | sort -rn | head -1)

        if [ -n "$LATEST_BUILD_FILE" ]; then
           LATEST_BUILD=$LATEST_BUILD_FILE
        fi

        # Compare Timestamps
        if [ "$LATEST_SRC" -gt "$LATEST_BUILD" ]; then
            add_warning "[$dir] Source Code is newer than Build Artifact. Building..."

            BUILD_CMD="mvn -f $POM_FILE clean install -DskipTests"
            if [ -f "mvnw" ]; then
                BUILD_CMD="./mvnw -f $POM_FILE clean install -DskipTests"
            fi

            # Run build silently with progress updates
            $BUILD_CMD > .maven-build.log 2>&1 &
            BUILD_PID=$!

            # Check status every 5 seconds
            while kill -0 $BUILD_PID 2>/dev/null; do
                sleep 5
                # Show last log line (truncated) to indicate progress
                LAST_LOG=$(tail -n 1 .maven-build.log 2>/dev/null | cut -c1-60)
                echo "⏳ [$dir] Maven Building... ($LAST_LOG)"
            done

            wait $BUILD_PID
            EXIT_CODE=$?

            if [ $EXIT_CODE -ne 0 ]; then
                echo "❌ [$dir] Build Failed!"
                cat .maven-build.log
                rm -f .maven-build.log
                if [ "$is_retry" == "true" ]; then
                    echo "[$dir] Maven Build failed during retry." >> "$ERRORS_LOG"
                else
                    echo "$dir" >> "$FAILED_LOG"
                fi
                return 1
            fi
            rm -f .maven-build.log

            echo "✅ [$dir] Build Complete."
        else
            [ "$is_retry" != "true" ] && echo "✅ [$dir] Maven Project Up to date."
        fi
    fi
    return 0
}

pids=()

# Phase 1: Run all projects in parallel
for dir in */; do
    (
        process_project "$dir" "false"
    ) &
    pids+=($!)
done

# Wait for all parallel tasks in the first phase to complete
if [ ${#pids[@]} -gt 0 ]; then
    echo "⏳ Waiting for Java/Maven tasks to finish..."
    wait "${pids[@]}" || true
fi

# Phase 2: Retry failed projects sequentially
if [ -s "$FAILED_LOG" ]; then
    echo "=========================================="
    echo "🔄 Retrying Failed Java/Maven Projects..."
    echo "=========================================="

    sort -u "$FAILED_LOG" | while read -r failed_dir; do
        if [ -n "$failed_dir" ]; then
            process_project "$failed_dir" "true"
        fi
    done
fi

# ==========================================
# Calculate Execution Time
# ==========================================
END_TIME=$(date +%s)
DURATION=$((END_TIME - START_TIME))
MINS=$((DURATION / 60))
SECS=$((DURATION % 60))

# ==========================================
# Build Summary
# ==========================================
echo "=========================================="
echo "📊 JAVA BUILD SUMMARY"
echo "=========================================="
echo "⏱️  TOTAL TIME: ${MINS}m ${SECS}s"
echo "------------------------------------------"

HAS_ERRORS=false
if [ -s "$ERRORS_LOG" ]; then
    HAS_ERRORS=true
    echo "❌ ERRORS FOUND (Projects that failed even after retry):"
    cat "$ERRORS_LOG"
    echo "------------------------------------------"
fi

HAS_WARNINGS=false
if [ -s "$WARNINGS_LOG" ]; then
    HAS_WARNINGS=true
    echo "⚠️  WARNINGS / ACTIONS TAKEN:"
    cat "$WARNINGS_LOG"
    echo "------------------------------------------"
fi

echo "=========================================="
# Evaluate final status and exit code
if [ "$HAS_ERRORS" = true ]; then
    echo "❌ JAVA BUILD FAILED (See errors above)"
    EXIT_STATUS=1
elif [ "$HAS_WARNINGS" = true ]; then
    echo "✅ JAVA BUILD SUCCESS WITH WARNINGS"
    EXIT_STATUS=0
else
    echo "✅ JAVA BUILD SUCCESS"
    EXIT_STATUS=0
fi
echo "=========================================="

# Clean up temporary log files
rm -f "$FAILED_LOG" "$WARNINGS_LOG" "$ERRORS_LOG"

exit $EXIT_STATUS

วิธีใช้คือ เรียกใน workspace หรือ รวมกับ script ตัวอื่น ๆ


อ่านเพิ่มเติม

ป้ายกำกับ:, , , ,