name: Docker Build description: Build a Docker image with tags inputs: image: description: Full image name (registry/org/name) required: true tags: description: Comma-separated list of tags default: 'latest' context: description: Build context path default: '.' dockerfile: description: Path to Dockerfile default: 'Dockerfile' build-args: description: Build arguments (KEY=value, newline-separated) default: '' outputs: images: description: Built image references value: ${{ steps.build.outputs.images }} runs: using: composite steps: - id: build shell: bash run: | IMAGE="${{ inputs.image }}" TAGS="${{ inputs.tags }}" CONTEXT="${{ inputs.context }}" DOCKERFILE="${{ inputs.dockerfile }}" BUILD_ARGS="${{ inputs.build-args }}" # Build tag arguments TAG_ARGS="" IMAGES="" IFS=',' read -ra TAG_ARRAY <<< "$TAGS" for tag in "${TAG_ARRAY[@]}"; do tag=$(echo "$tag" | xargs) # trim whitespace TAG_ARGS="$TAG_ARGS -t $IMAGE:$tag" IMAGES="$IMAGES$IMAGE:$tag," done IMAGES="${IMAGES%,}" # remove trailing comma # Build build-arg arguments BUILD_ARG_ARGS="" if [ -n "$BUILD_ARGS" ]; then while IFS= read -r arg; do if [ -n "$arg" ]; then BUILD_ARG_ARGS="$BUILD_ARG_ARGS --build-arg $arg" fi done <<< "$BUILD_ARGS" fi # Build the image; retry on failure. Base-image pulls from external # registries flake on transient runner DNS/network issues, and the # BuildKit layer cache makes a retry of a failed build cheap. for attempt in 1 2; do if docker build $TAG_ARGS $BUILD_ARG_ARGS -f "$DOCKERFILE" "$CONTEXT"; then break fi if [ "$attempt" -eq 2 ]; then exit 1 fi echo "build failed, retrying in 30s..." sleep 30 done echo "images=$IMAGES" >> $GITHUB_OUTPUT