Updates the `build-images` workflow to robustly detect and validate changes to image directories. Changes: - Implements strict validation to ensure detected image directories exist and contain a `Dockerfile` before adding them to the build matrix. - Normalizes logic for both manual inputs and automatic git-diff detection using a temporary file (`valid_images.txt`) to collect targets. - Adds specific checks to warn if a manually specified image is missing or invalid. - Prevents the build job from failing or running unnecessarily if an empty image name is passed to the matrix by adding an early exit condition.
139 lines
4.7 KiB
YAML
139 lines
4.7 KiB
YAML
name: Build and Push Docker Images
|
|
|
|
on:
|
|
push:
|
|
branches: [main]
|
|
paths:
|
|
- 'images/**'
|
|
workflow_dispatch:
|
|
inputs:
|
|
image:
|
|
description: 'Image to build (e.g., terraform-ci)'
|
|
required: false
|
|
|
|
env:
|
|
REGISTRY: gitea.arnodo.fr
|
|
|
|
jobs:
|
|
# ============================================================================
|
|
# Job 1 : Detect modified images
|
|
# ============================================================================
|
|
detect-changes:
|
|
runs-on: docker
|
|
container:
|
|
image: alpine:3.20
|
|
outputs:
|
|
matrix: ${{ steps.changes.outputs.matrix }}
|
|
has_changes: ${{ steps.changes.outputs.has_changes }}
|
|
steps:
|
|
- name: Install dependencies
|
|
run: apk add --no-cache git jq
|
|
|
|
- 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: |
|
|
# Prepare output file for valid images
|
|
> valid_images.txt
|
|
|
|
if [ -n "${{ inputs.image }}" ]; then
|
|
# Manual trigger with input
|
|
IMAGE=$(echo "${{ inputs.image }}" | xargs)
|
|
if [ -n "$IMAGE" ]; then
|
|
if [ -d "images/$IMAGE" ] && [ -f "images/$IMAGE/Dockerfile" ]; then
|
|
echo "$IMAGE" >> valid_images.txt
|
|
else
|
|
echo "Warning: Image '$IMAGE' not found or missing Dockerfile at images/$IMAGE/Dockerfile"
|
|
fi
|
|
fi
|
|
else
|
|
# Automatic detection via git diff
|
|
CHANGED_FILES=$(git diff --name-only HEAD~1 HEAD -- images/ 2>/dev/null || true)
|
|
|
|
# Extract potential image directories (first level subdirs in images/)
|
|
# cut -d'/' -f2 takes the second component: images/COMPONENT/...
|
|
CANDIDATES=$(echo "$CHANGED_FILES" | cut -d'/' -f2 | sort -u | grep -v '^$')
|
|
|
|
for CANDIDATE in $CANDIDATES; do
|
|
# Verify it's a directory with a Dockerfile
|
|
if [ -d "images/$CANDIDATE" ] && [ -f "images/$CANDIDATE/Dockerfile" ]; then
|
|
echo "$CANDIDATE" >> valid_images.txt
|
|
fi
|
|
done
|
|
fi
|
|
|
|
if [ ! -s valid_images.txt ]; then
|
|
echo "No valid images detected."
|
|
echo "has_changes=false" >> $GITHUB_OUTPUT
|
|
echo "matrix=[]" >> $GITHUB_OUTPUT
|
|
else
|
|
# Convert list to JSON array using jq
|
|
JSON=$(cat valid_images.txt | jq -R -s -c 'split("\n") | map(select(length > 0))')
|
|
echo "Detected images: $JSON"
|
|
echo "matrix=$JSON" >> $GITHUB_OUTPUT
|
|
echo "has_changes=true" >> $GITHUB_OUTPUT
|
|
fi
|
|
|
|
- name: Show detected changes
|
|
run: |
|
|
echo "Matrix: ${{ steps.changes.outputs.matrix }}"
|
|
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.matrix) }}
|
|
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: |
|
|
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"
|