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) if [[ ${#ALL_LANES[@]} -eq 0 ]]; then echo "No lanes found under docker/. Nothing to do." echo "should_build=false" >> $GITHUB_OUTPUT echo 'matrix={"dir":[]}' >> $GITHUB_OUTPUT exit 0 fi # Determine changed files (PR vs push vs manual dispatch) if [[ "${{ github.event_name }}" == "pull_request" ]]; then BASE_SHA="${{ github.event.pull_request.base.sha }}" HEAD_SHA="${{ github.event.pull_request.head.sha }}" elif [[ "${{ github.event_name }}" == "push" ]]; then # For push events try to get the previous commit; fall back to empty BASE_SHA="$(git rev-parse HEAD~1 2>/dev/null || true)" HEAD_SHA="$(git rev-parse HEAD 2>/dev/null || true)" else # For workflow_dispatch and other events treat as "all files changed" BASE_SHA="" HEAD_SHA="$(git rev-parse HEAD 2>/dev/null || true)" fi if [[ -n "$BASE_SHA" ]]; then CHANGED=$(git diff --name-only "$BASE_SHA" "$HEAD_SHA") else # First commit or shallow: treat everything as changed CHANGED=$(git ls-files) fi echo "Changed files:" echo "$CHANGED" # If workflow changed, rebuild all lanes if grep -qx ".github/workflows/build.yml" <<< "$CHANGED"; then echo "Workflow changed; rebuilding all lanes." TARGET_DIRS=("${ALL_LANES[@]}") else # Build only lanes with changes under their directories TARGET_DIRS=() for lane in "${ALL_LANES[@]}"; do # Any change directly under lane dir counts; include Dockerfile or subpaths if grep -q "^${lane}/" <<< "$CHANGED"; then TARGET_DIRS+=("$lane") fi done fi # De-duplicate mapfile -t TARGET_DIRS < <(printf "%s\n" "${TARGET_DIRS[@]}" | awk 'NF && !x[$0]++') if [[ ${#TARGET_DIRS[@]} -eq 0 ]]; then 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: Derive image name and tags id: meta shell: bash run: | set -euo pipefail DIR="${{ matrix.dir }}" # Ensure DIR is set and use basename to derive a reliable NAME if [[ -z "${DIR}" || "${DIR}" == "." ]]; then echo "matrix.dir is empty or '.'; treating as repo root" DIR='.' fi NAME="$(basename "${DIR}")" # e.g. '7.4' or 'nginx' SHA=${GITHUB_SHA::7} # Decide repository and tag scheme: # - nginx lane -> gitea.auvem.com/auvem/wordpress-nginx:stable # - other lanes (assumed php variants) -> gitea.auvem.com/auvem/wordpress-php-fpm:-stable if [[ "${NAME}" == "nginx" ]]; then IMAGE="gitea.auvem.com/auvem/wordpress-docker/nginx" TAG="stable" else IMAGE="gitea.auvem.com/auvem/wordpress-docker/php-fpm" # Extract version like 7.4 or 8.1 from the lane name; otherwise use lane name if [[ -n "${NAME}" && "${NAME}" =~ ([0-9]+\.[0-9]+) ]]; then VERSION="${BASH_REMATCH[1]}" TAG="${VERSION}-stable" elif [[ -n "${NAME}" && "${NAME}" =~ ([0-9]+) ]]; then VERSION="${BASH_REMATCH[1]}" TAG="${VERSION}-stable" elif [[ -n "${NAME}" ]]; then TAG="${NAME}-stable" else TAG="stable" fi fi 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