name: Build and Push Docker Images on: push: branches: [main] paths: - 'images/**' workflow_dispatch: # Manual trigger builds all images env: REGISTRY: gitea.arnodo.fr jobs: # ============================================================================ # Job 1 : Detect modified images # ============================================================================ detect-changes: runs-on: docker container: image: alpine:3.20 outputs: image_list: ${{ steps.changes.outputs.image_list }} has_changes: ${{ steps.changes.outputs.has_changes }} steps: - name: Install dependencies run: apk add --no-cache git python3 - name: Checkout repository run: | git clone --depth 2 https://gitea.arnodo.fr/${{ gitea.repository }}.git . git checkout ${{ gitea.sha }} - name: Detect changed images id: changes run: | > valid_images.txt if [ "${{ github.event_name }}" == "workflow_dispatch" ]; then echo "DEBUG: Manual trigger detected. Scanning all images..." if [ -d "images" ]; then # Use find for reliable directory listing find images -mindepth 1 -maxdepth 1 -type d | while read DIR; do if [ -f "$DIR/Dockerfile" ]; then BASENAME=$(basename "$DIR") echo "DEBUG: Found image: $BASENAME" echo "$BASENAME" >> valid_images.txt fi done else echo "DEBUG: images/ directory not found." fi else echo "DEBUG: Push event detected. Analyzing git diff..." CHANGED_FILES=$(git diff --name-only HEAD~1 HEAD -- images/ 2>/dev/null || true) # Extract unique directories CANDIDATES=$(echo "$CHANGED_FILES" | cut -d'/' -f2 | sort -u | grep -v '^$') for CANDIDATE in $CANDIDATES; do if [ -d "images/$CANDIDATE" ] && [ -f "images/$CANDIDATE/Dockerfile" ]; then echo "DEBUG: Change detected in image: $CANDIDATE" echo "$CANDIDATE" >> valid_images.txt fi done # Fallback: If push event but no valid images found (e.g. change in root file but paths filter matched?), # we generally skip. But if the user wants "Simple: No diff -> Build All", we could enable it. # However, typically for push, we only want changes. # The user's comment "If no modification is detected ... build all" likely referred to the manual trigger context. # So we keep push strictly to changes. fi if [ ! -s valid_images.txt ]; then echo "No valid images detected." echo "has_changes=false" >> $GITHUB_OUTPUT echo "image_list=[]" >> $GITHUB_OUTPUT else # Use Python for reliable JSON generation JSON=$(cat valid_images.txt | python3 -c 'import json, sys; lines = [l.strip() for l in sys.stdin if l.strip()]; print(json.dumps(lines))') echo "DEBUG: Generated JSON: >$JSON<" echo "image_list=$JSON" >> $GITHUB_OUTPUT echo "has_changes=true" >> $GITHUB_OUTPUT fi - name: Show detected changes run: | echo "Image List: ${{ steps.changes.outputs.image_list }}" echo "Has changes: ${{ steps.changes.outputs.has_changes }}" # ============================================================================ # Job 2 : Build and Push (Standard Docker) # ============================================================================ build: needs: detect-changes if: needs.detect-changes.outputs.has_changes == 'true' runs-on: docker container: image: docker:cli strategy: matrix: image: ${{ fromJson(needs.detect-changes.outputs.image_list) }} fail-fast: false steps: - name: Install dependencies run: apk add --no-cache git - name: Checkout repository run: | git clone --depth 2 https://gitea.arnodo.fr/${{ gitea.repository }}.git . git checkout ${{ gitea.sha }} - name: Login to Registry run: | echo "${{ secrets.REGISTRY_TOKEN }}" | docker login ${{ env.REGISTRY }} -u ${{ gitea.actor }} --password-stdin - name: Build and Push env: IMAGE_NAME: ${{ env.REGISTRY }}/damien/${{ matrix.image }} IMAGE_PATH: images/${{ matrix.image }} run: | echo "Debug: Matrix Image is '${{ matrix.image }}'" if [ -z "${{ matrix.image }}" ]; then echo "Skipping empty image name" exit 0 fi echo "Building $IMAGE_NAME:latest from $IMAGE_PATH ..." if [ ! -d "$IMAGE_PATH" ]; then echo "Error: Directory $IMAGE_PATH does not exist." exit 1 fi if [ ! -f "$IMAGE_PATH/Dockerfile" ]; then echo "Error: Dockerfile not found in $IMAGE_PATH." exit 1 fi # Use standard docker build docker build -t "$IMAGE_NAME:latest" "$IMAGE_PATH" docker push "$IMAGE_NAME:latest" echo "✅ Pushed $IMAGE_NAME:latest"