Build and Push Docker Images (Matrix Strategy) #32
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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 |