name: build on: push: branches: [main] pull_request: branches: [main] workflow_dispatch: workflow_call: inputs: REGISTRY_USER: required: true type: string secrets: REGISTRY_TOKEN: required: true jobs: plan: runs-on: ubuntu-latest outputs: matrix: ${{ steps.compute.outputs.matrix }} should_build: ${{ steps.compute.outputs.should_build }} steps: - uses: actions/checkout@v4 with: fetch-depth: 0 - id: compute shell: bash run: | set -euo pipefail # Discover lanes: immediate subdirs under docker/ mapfile -t ALL_LANES < <(find docker -mindepth 1 -maxdepth 1 -type d | sort) # Filter to only directories that contain a Dockerfile (real lanes) FILTERED_LANES=() SKIPPED_LANES=() build: needs: plan if: needs.plan.outputs.should_build == 'true' runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: docker/setup-buildx-action@v3 - name: DEBUG registry username source run: | echo "Selected registry username source: $SOURCE" env: SOURCE: ${{ inputs.REGISTRY_USER != '' && 'inputs' || secrets.REGISTRY_USER != '' && 'secrets' || vars.REGISTRY_USER != '' && 'vars' || 'actor' }} - uses: docker/login-action@v3 with: registry: gitea.auvem.com username: ${{ inputs.REGISTRY_USER != '' && inputs.REGISTRY_USER || secrets.REGISTRY_USER != '' && secrets.REGISTRY_USER || vars.REGISTRY_USER != '' && vars.REGISTRY_USER || github.actor }} password: ${{ secrets.REGISTRY_TOKEN }} - name: Show plan matrix run: | echo "Plan matrix: $MATRIX_JSON" jq -C . dir <<< "$MATRIX_JSON" 2>/dev/null || true env: MATRIX_JSON: ${{ needs.plan.outputs.matrix }} - name: Loop: build and push per-lane shell: bash env: MATRIX_JSON: ${{ needs.plan.outputs.matrix }} GIT_SHA_SHORT: ${GITHUB_SHA::7} run: | set -euo pipefail if [[ -z "$MATRIX_JSON" ]]; then echo "ERROR: plan matrix is empty. Aborting." >&2 exit 1 fi # Iterate lanes lanes=$(jq -r '.dir[]' <<< "$MATRIX_JSON") echo "Lanes to build:" echo "$lanes" for lane in $lanes; do echo "\n--- Building lane: $lane ---" if [[ ! -f "$lane/Dockerfile" ]]; then echo "ERROR: No Dockerfile at $lane/Dockerfile" >&2 exit 1 fi NAME=$(basename "$lane") if [[ "$NAME" == "nginx" ]]; then IMAGE="gitea.auvem.com/auvem/wordpress-docker/nginx" TAG="stable" else IMAGE="gitea.auvem.com/auvem/wordpress-docker/php-fpm" if [[ "$NAME" =~ ^([0-9]+\.[0-9]+)$ ]]; then VERSION="${BASH_REMATCH[1]}" TAG="${VERSION}-stable" elif [[ "$NAME" =~ ^([0-9]+)$ ]]; then VERSION="${BASH_REMATCH[1]}" TAG="${VERSION}-stable" else echo "ERROR: Cannot deterministically derive a version tag from lane name '$NAME'." >&2 exit 1 fi fi echo "Computed: lane='$lane' name='$NAME' image='$IMAGE' tags='$IMAGE:${TAG},$IMAGE:git-${GIT_SHA_SHORT}'" # Buildx build and push docker buildx build \ --push \ --platform linux/amd64 \ --tag "$IMAGE:${TAG}" \ --tag "$IMAGE:git-${GIT_SHA_SHORT}" \ --file "$lane/Dockerfile" \ . done echo "No lane directories changed. Skipping build." echo "should_build=false" >> $GITHUB_OUTPUT echo 'matrix={"dir":[]}' >> $GITHUB_OUTPUT exit 0 fi # Produce JSON matrix JSON=$(jq -nc --argjson arr "$(printf '%s\n' "${TARGET_DIRS[@]}" | jq -R . | jq -s .)" '{dir: $arr}') echo "Matrix: $JSON" echo "should_build=true" >> $GITHUB_OUTPUT echo "matrix=$JSON" >> $GITHUB_OUTPUT build: needs: plan if: needs.plan.outputs.should_build == 'true' runs-on: ubuntu-latest strategy: fail-fast: false matrix: ${{ fromJson(needs.plan.outputs.matrix) }} steps: - uses: actions/checkout@v4 - uses: docker/setup-buildx-action@v3 - name: DEBUG registry username source run: | echo "Selected registry username source: $SOURCE" # Do NOT echo the username or any secret values — only indicate which source will be used env: SOURCE: ${{ inputs.REGISTRY_USER != '' && 'inputs' || secrets.REGISTRY_USER != '' && 'secrets' || vars.REGISTRY_USER != '' && 'vars' || 'actor' }} - uses: docker/login-action@v3 with: registry: gitea.auvem.com # Resolve username in this order: workflow input -> repo/secret -> repo var -> actor username: ${{ inputs.REGISTRY_USER != '' && inputs.REGISTRY_USER || secrets.REGISTRY_USER != '' && secrets.REGISTRY_USER || vars.REGISTRY_USER != '' && vars.REGISTRY_USER || github.actor }} password: ${{ secrets.REGISTRY_TOKEN }} - name: Show matrix payload received by this job run: | echo "Expression toJson(matrix): ${{ toJson(matrix) }}" echo "Expression matrix.dir: '${{ matrix.dir }}'" echo "ENV MATRIX_DIR: '${MATRIX_DIR}'" echo "Dockerfile path expression: '${{ matrix.dir }}/Dockerfile'" env: MATRIX_DIR: ${{ matrix.dir }} - name: Derive image name and tags id: meta shell: bash run: | set -euo pipefail DIR="${{ matrix.dir }}" # Fail fast on ambiguous/empty matrix.dir. We require a deterministic lane. if [[ -z "${DIR}" || "${DIR}" == "." ]]; then echo "ERROR: Ambiguous lane: matrix.dir is empty or '.'." echo "Provide a specific lane directory under docker/ (e.g. '7.4' or 'nginx')." exit 1 fi NAME="$(basename "${DIR}")" # e.g. '7.4' or 'nginx' SHA=${GITHUB_SHA::7} # Decide repository and tag scheme. Must be deterministic. if [[ "${NAME}" == "nginx" ]]; then IMAGE="gitea.auvem.com/auvem/wordpress-docker/nginx" TAG="stable" else IMAGE="gitea.auvem.com/auvem/wordpress-docker/php-fpm" # Accept only lanes that encode a numeric version like '7.4' or '8'. if [[ "${NAME}" =~ ^([0-9]+\.[0-9]+)$ ]]; then VERSION="${BASH_REMATCH[1]}" TAG="${VERSION}-stable" elif [[ "${NAME}" =~ ^([0-9]+)$ ]]; then VERSION="${BASH_REMATCH[1]}" TAG="${VERSION}-stable" else echo "ERROR: Cannot deterministically derive a version tag from lane name '${NAME}'." echo "Expected lane names like '7.4' or '8' for php-fpm lanes." exit 1 fi fi # Debug output for name resolution echo "Computed values: DIR='${DIR}', NAME='${NAME}', IMAGE='${IMAGE}', TAG='${TAG}', SHA='${SHA}'" echo "image=$IMAGE" >> $GITHUB_OUTPUT echo "tags=$IMAGE:${TAG},$IMAGE:git-${SHA}" >> $GITHUB_OUTPUT - name: Build and push uses: docker/build-push-action@v6 with: context: . file: ${{ matrix.dir }}/Dockerfile push: true tags: ${{ steps.meta.outputs.tags }} platforms: linux/amd64 cache-from: type=registry,ref=${{ steps.meta.outputs.image }}:cache cache-to: type=registry,ref=${{ steps.meta.outputs.image }}:cache,mode=max