Skip to content

Build and Push Docker Images (Matrix Strategy) #34

Build and Push Docker Images (Matrix Strategy)

Build and Push Docker Images (Matrix Strategy) #34

Workflow file for this run

name: Build and Push Docker Images (Matrix Strategy)
on:
repository_dispatch:
types: [custom-release-trigger]
workflow_dispatch:
inputs:
build_type:
description: 'Build type selection'
required: true
default: 'both'
type: choice
options:
- 'standard'
- 'multistage'
- 'both'
use_cache:
description: 'Use Docker cache (disable for fresh build)'
required: true
default: true
type: boolean
cache_bust:
description: 'Force cache invalidation (enter any text to bust cache)'
required: false
default: ''
type: string
jobs:
# Determine which builds to run based on input
determine-builds:
runs-on: ubuntu-latest
outputs:
matrix: ${{ steps.set-matrix.outputs.matrix }}
steps:
- name: Set build matrix
id: set-matrix
run: |
BUILD_TYPE="${{ github.event.inputs.build_type || 'both' }}"
if [ "$BUILD_TYPE" = "standard" ]; then
MATRIX='{"include":[{"dockerfile":"Dockerfile.mod","tag":"latest","build_type":"standard","cache_scope":"standard"}]}'
elif [ "$BUILD_TYPE" = "multistage" ]; then
MATRIX='{"include":[{"dockerfile":"Dockerfile.multi","tag":"multi","build_type":"multistage","cache_scope":"multistage"}]}'
else
MATRIX='{"include":[{"dockerfile":"Dockerfile.mod","tag":"latest","build_type":"standard","cache_scope":"standard"},{"dockerfile":"Dockerfile.multi","tag":"multi","build_type":"multistage","cache_scope":"multistage"}]}'
fi
echo "matrix=$MATRIX" >> $GITHUB_OUTPUT
echo "Selected build matrix: $MATRIX"
build:
needs: determine-builds
runs-on: ubuntu-latest
strategy:
fail-fast: false # This is the key - builds continue even if one fails
matrix: ${{ fromJson(needs.determine-builds.outputs.matrix) }}
steps:
- uses: actions/checkout@v4
- name: Get latest release
id: get_release
uses: pozetroninc/github-action-get-latest-release@master
with:
repository: 42mgr/OO_CommunityServer
token: ${{ secrets.PAT_TOKEN }}
- name: Display release information
run: |
echo "🏷️ RELEASE INFORMATION FOR ${{ matrix.build_type }} BUILD:"
echo "📋 Release Tag: ${{ steps.get_release.outputs.release }}"
echo "📅 Release Date: $(curl -s https://api.github.com/repos/42mgr/OO_CommunityServer/releases/tags/${{ steps.get_release.outputs.release }} | jq -r '.created_at')"
echo "📦 Build Type: ${{ matrix.build_type }}"
echo "🐳 Docker Tag: ${{ matrix.tag }}"
echo ""
echo "📊 Recent releases for context:"
curl -s https://api.github.com/repos/42mgr/OO_CommunityServer/releases | jq -r '.[:5] | .[] | "\(.tag_name) - \(.created_at) - \(.name)"'
echo ""
- name: Download .deb from latest release
run: |
echo "📦 Downloading .deb for ${{ matrix.build_type }} build..."
echo "🏷️ Using release: ${{ steps.get_release.outputs.release }}"
DOWNLOAD_URL="https://github.com/42mgr/OO_CommunityServer/releases/download/${{ steps.get_release.outputs.release }}/onlyoffice-communityserver-mail-custom.deb"
echo "🔗 Download URL: $DOWNLOAD_URL"
# Check if the asset exists before downloading
if curl -s -f -I -H "Authorization: Bearer ${{ secrets.PAT_TOKEN }}" "$DOWNLOAD_URL" >/dev/null; then
echo "✅ Asset found, downloading..."
curl -L -o onlyoffice-communityserver-mail-custom.deb \
-H "Authorization: Bearer ${{ secrets.PAT_TOKEN }}" \
"$DOWNLOAD_URL"
else
echo "❌ Asset not found at expected URL, checking available assets..."
curl -s -H "Authorization: Bearer ${{ secrets.PAT_TOKEN }}" \
"https://api.github.com/repos/42mgr/OO_CommunityServer/releases/tags/${{ steps.get_release.outputs.release }}" | \
jq -r '.assets[] | .name'
exit 1
fi
echo ""
echo "✅ Downloaded .deb file details:"
ls -lh onlyoffice-communityserver-mail-custom.deb
# Create a build info file for the Docker image
cat > build-info.txt << EOF
DOCKER_BUILD_INFO
=================
Build Date: $(date -u +%Y-%m-%dT%H:%M:%SZ)
Build Type: ${{ matrix.build_type }}
Source Release: ${{ steps.get_release.outputs.release }}
Docker Tag: ${{ matrix.tag }}
Workflow Run: ${{ github.run_number }}
Commit SHA: ${{ github.sha }}
Repository: ${{ github.repository }}
EOF
echo ""
echo "📋 Build information created:"
cat build-info.txt
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Prepare cache configuration
id: cache-config
run: |
USE_CACHE="${{ github.event.inputs.use_cache || 'true' }}"
CACHE_BUST="${{ github.event.inputs.cache_bust || '' }}"
CACHE_SCOPE="${{ matrix.cache_scope }}"
# Add cache busting and commit hash to scope for better invalidation
if [ -n "$CACHE_BUST" ]; then
CACHE_SCOPE="${CACHE_SCOPE}-${CACHE_BUST}"
fi
CACHE_SCOPE="${CACHE_SCOPE}-${{ github.sha }}"
echo "use_cache=$USE_CACHE" >> $GITHUB_OUTPUT
echo "cache_scope=$CACHE_SCOPE" >> $GITHUB_OUTPUT
if [ "$USE_CACHE" = "true" ]; then
echo "✅ Cache enabled with scope: $CACHE_SCOPE"
else
echo "🚫 Cache disabled - fresh build"
fi
- name: Build and push Docker image (with cache)
if: steps.cache-config.outputs.use_cache == 'true'
uses: docker/build-push-action@v5
with:
context: .
file: ${{ matrix.dockerfile }}
push: true
target: ${{ matrix.build_type == 'multistage' && 'final' || '' }}
tags: |
mgr42/oo_crm:${{ matrix.tag }}
mgr42/oo_crm:${{ matrix.tag }}-${{ steps.get_release.outputs.release }}
cache-from: |
type=gha,scope=${{ steps.cache-config.outputs.cache_scope }}
type=registry,ref=mgr42/oo_crm:cache-${{ matrix.tag }}
cache-to: |
type=gha,mode=max,scope=${{ steps.cache-config.outputs.cache_scope }}
type=registry,ref=mgr42/oo_crm:cache-${{ matrix.tag }},mode=max
labels: |
org.opencontainers.image.source=https://github.com/${{ github.repository }}
org.opencontainers.image.created=$(date -u +'%Y-%m-%dT%H:%M:%SZ')
org.opencontainers.image.revision=${{ github.sha }}
build.type=${{ matrix.build_type }}
build.dockerfile=${{ matrix.dockerfile }}
build.source_release=${{ steps.get_release.outputs.release }}
build.workflow_run=${{ github.run_number }}
build.deb_source=42mgr/OO_CommunityServer
onlyoffice.custom.source_release=${{ steps.get_release.outputs.release }}
onlyoffice.custom.build_date=$(date -u +'%Y-%m-%dT%H:%M:%SZ')
onlyoffice.custom.build_type=${{ matrix.build_type }}
- name: Build and push Docker image (no cache)
if: steps.cache-config.outputs.use_cache == 'false'
uses: docker/build-push-action@v5
with:
context: .
file: ${{ matrix.dockerfile }}
push: true
target: ${{ matrix.build_type == 'multistage' && 'final' || '' }}
no-cache: true
tags: |
mgr42/oo_crm:${{ matrix.tag }}
mgr42/oo_crm:${{ matrix.tag }}-${{ steps.get_release.outputs.release }}
labels: |
org.opencontainers.image.source=https://github.com/${{ github.repository }}
org.opencontainers.image.created=$(date -u +'%Y-%m-%dT%H:%M:%SZ')
org.opencontainers.image.revision=${{ github.sha }}
build.type=${{ matrix.build_type }}
build.source_release=${{ steps.get_release.outputs.release }}
build.workflow_run=${{ github.run_number }}
build.deb_source=42mgr/OO_CommunityServer
onlyoffice.custom.source_release=${{ steps.get_release.outputs.release }}
onlyoffice.custom.build_date=$(date -u +'%Y-%m-%dT%H:%M:%SZ')
onlyoffice.custom.build_type=${{ matrix.build_type }}
build.dockerfile=${{ matrix.dockerfile }}
- name: Build success summary
if: success()
run: |
echo "🎉 Docker build completed successfully!"
echo ""
echo "📦 DOCKER IMAGE DETAILS:"
echo " 🐳 Image: mgr42/oo_crm:${{ matrix.tag }}"
echo " 🏷️ Tagged: ${{ matrix.tag }}-${{ steps.get_release.outputs.release }}"
echo " 📋 Build Type: ${{ matrix.build_type }}"
echo " 🔗 Source Release: ${{ steps.get_release.outputs.release }}"
echo " 🏗️ Workflow Run: ${{ github.run_number }}"
echo ""
echo "📋 RELEASE TRACEABILITY:"
echo " ✅ This Docker image was built from:"
echo " - Source: 42mgr/OO_CommunityServer"
echo " - Release: ${{ steps.get_release.outputs.release }}"
echo " - .deb Package: onlyoffice-communityserver-mail-custom.deb"
echo " - Docker Build: ${{ github.run_number }}"
echo ""
echo "🔍 TO CHECK WHAT'S INSIDE THIS IMAGE:"
echo " docker inspect mgr42/oo_crm:${{ matrix.tag }} | jq '.Config.Labels'"
echo " docker run --rm mgr42/oo_crm:${{ matrix.tag }} cat /app/build-info.txt"
- name: Build success notification
if: success()
run: |
echo "✅ ${{ matrix.build_type }} build completed successfully!"
echo "🏷️ Tags: mgr42/oo_crm:${{ matrix.tag }}, mgr42/oo_crm:${{ matrix.tag }}-${{ steps.get_release.outputs.release }}"
echo "📁 Dockerfile: ${{ matrix.dockerfile }}"
echo "💾 Cache: ${{ steps.cache-config.outputs.use_cache == 'true' && 'Enabled' || 'Disabled' }}"
if [ "${{ steps.cache-config.outputs.use_cache }}" = "true" ]; then
echo "🔧 Cache scope: ${{ steps.cache-config.outputs.cache_scope }}"
fi
- name: Build failure notification
if: failure()
run: |
echo "❌ ${{ matrix.build_type }} build failed!"
echo "📁 Dockerfile: ${{ matrix.dockerfile }}"
echo "💾 Cache: ${{ steps.cache-config.outputs.use_cache == 'true' && 'Enabled' || 'Disabled' }}"
echo "ℹ️ Other builds will continue due to fail-fast: false"
# Summary job that always runs
summary:
needs: build
runs-on: ubuntu-latest
if: always()
steps:
- name: Build Results Summary
run: |
echo "## 📊 Build Results Summary"
echo ""
# Check results from the matrix
STANDARD_RESULT="${{ needs.build.result }}"
# Note: In matrix builds, you get the overall result
# Individual matrix job results aren't directly accessible
# But the build will show individual status in the UI
echo "**Overall Matrix Build Result:** $STANDARD_RESULT"
echo ""
if [ "$STANDARD_RESULT" == "success" ]; then
echo "🎉 All builds completed successfully!"
elif [ "$STANDARD_RESULT" == "failure" ]; then
echo "⚠️ Some builds failed, but others may have succeeded."
echo "Check individual matrix job results above."
else
echo "❓ Unexpected build result: $STANDARD_RESULT"
fi