Build and Push Docker Images #1
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 | |
| # This workflow ONLY builds and pushes Docker images to GitHub Container Registry. | |
| # Deployment is handled by external systems that watch for image updates. | |
| # | |
| # Workflow Summary: | |
| # - develop branch → :develop image tag → external system deploys to dev (automatic) | |
| # - main branch → :main image tag → external system deploys to testing (automatic) | |
| # - v* tags → version image tags → external system handles production deployment (automatic) | |
| # - Any other branch → manually triggered via Actions tab (workflow_dispatch) | |
| # - v*-rc/beta/etc tags → pre-release version image tags (no :latest) | |
| # | |
| # Image Tags Created: | |
| # - Push to develop: ghcr.io/org/repo:develop, ghcr.io/org/repo:develop-abc1234 | |
| # - Push to main: ghcr.io/org/repo:main, ghcr.io/org/repo:main-def5678 | |
| # - Manual trigger on any branch: ghcr.io/org/repo:branch-name, ghcr.io/org/repo:branch-name-abc1234 | |
| # - Tag v1.0.0: ghcr.io/org/repo:v1.0.0, ghcr.io/org/repo:latest | |
| # - Tag v1.0.0-rc: ghcr.io/org/repo:v1.0.0-rc (no :latest) | |
| on: | |
| push: | |
| branches: | |
| - main | |
| - develop | |
| tags: | |
| - 'v*' # Triggered when version tags are pushed | |
| workflow_dispatch: # Manually trigger builds for feature/fix branches from the Actions tab | |
| env: | |
| REGISTRY: ghcr.io | |
| BACKEND_IMAGE_NAME: helsingborg-stad/eneo-backend | |
| FRONTEND_IMAGE_NAME: helsingborg-stad/eneo-frontend | |
| jobs: | |
| build-and-push: | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: write | |
| packages: write | |
| attestations: write | |
| id-token: write | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 # Fetch full history for tags | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@v3 | |
| - name: Install jq | |
| run: sudo apt-get update && sudo apt-get install -y jq curl | |
| - name: Install bun | |
| uses: oven-sh/setup-bun@v2 | |
| with: | |
| bun-version: 1.3.0 | |
| - name: Log in to the Container registry | |
| uses: docker/login-action@v3 | |
| with: | |
| registry: ${{ env.REGISTRY }} | |
| username: ${{ github.actor }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Determine build context | |
| id: build-context | |
| run: | | |
| if [[ "${{ github.ref }}" == "refs/tags/v"* ]]; then | |
| VERSION="${GITHUB_REF#refs/tags/}" | |
| # Check if this is a pre-release (contains hyphen after version, e.g., v1.7.0-rc) | |
| if [[ "$VERSION" == *-* ]]; then | |
| echo "Building pre-release version: $VERSION" | |
| echo "is-release=true" >> $GITHUB_OUTPUT | |
| echo "is-prerelease=true" >> $GITHUB_OUTPUT | |
| else | |
| echo "Building production version: $VERSION" | |
| echo "is-release=true" >> $GITHUB_OUTPUT | |
| echo "is-prerelease=false" >> $GITHUB_OUTPUT | |
| fi | |
| elif [[ "${{ github.ref }}" == "refs/heads/main" ]]; then | |
| echo "Building main branch for testing environment" | |
| echo "is-release=false" >> $GITHUB_OUTPUT | |
| elif [[ "${{ github.ref }}" == "refs/heads/develop" ]]; then | |
| echo "Building develop branch for dev environment" | |
| echo "is-release=false" >> $GITHUB_OUTPUT | |
| else | |
| BRANCH_NAME="${GITHUB_REF#refs/heads/}" | |
| echo "Building branch: $BRANCH_NAME" | |
| echo "is-release=false" >> $GITHUB_OUTPUT | |
| fi | |
| # Backend build and push | |
| - name: Extract backend metadata | |
| id: meta-backend | |
| uses: docker/metadata-action@v5 | |
| with: | |
| images: ${{ env.REGISTRY }}/${{ env.BACKEND_IMAGE_NAME }} | |
| tags: | | |
| # Branch-based tags | |
| type=raw,value=develop,enable=${{ github.ref == 'refs/heads/develop' }} | |
| type=raw,value=main,enable=${{ github.ref == 'refs/heads/main' }} | |
| type=ref,event=branch,enable=${{ github.ref != 'refs/heads/develop' && github.ref != 'refs/heads/main' }} | |
| # Version tags (only for releases) | |
| type=semver,pattern={{version}},enable=${{ steps.build-context.outputs.is-release == 'true' }} | |
| type=raw,value=latest,enable=${{ steps.build-context.outputs.is-release == 'true' && steps.build-context.outputs.is-prerelease == 'false' }} | |
| # Git SHA for traceability (always included) | |
| type=sha,prefix={{branch}}-,format=short,enable=${{ github.ref_type == 'branch' }} | |
| type=sha,format=short,enable=${{ github.ref_type == 'tag' }} | |
| - name: Inject backend version | |
| run: | | |
| # For branches, use the SHA-suffixed tag (second tag), for tags use first tag | |
| if [[ "${{ github.ref_type }}" == "branch" ]]; then | |
| VERSION=$(echo "${{ steps.meta-backend.outputs.tags }}" | sed -n '2p' | cut -d':' -f2) | |
| else | |
| VERSION=$(echo "${{ steps.meta-backend.outputs.tags }}" | head -n1 | cut -d':' -f2) | |
| fi | |
| ./scripts/inject-backend-version.sh "$VERSION" | |
| - name: Build and push backend Docker image | |
| uses: docker/build-push-action@v5 | |
| with: | |
| context: ./backend | |
| file: ./backend/Dockerfile | |
| push: true | |
| tags: ${{ steps.meta-backend.outputs.tags }} | |
| labels: ${{ steps.meta-backend.outputs.labels }} | |
| cache-from: type=gha | |
| cache-to: type=gha,mode=max | |
| # Frontend build and push | |
| - name: Extract frontend metadata | |
| id: meta-frontend | |
| uses: docker/metadata-action@v5 | |
| with: | |
| images: ${{ env.REGISTRY }}/${{ env.FRONTEND_IMAGE_NAME }} | |
| tags: | | |
| # Branch-based tags | |
| type=raw,value=develop,enable=${{ github.ref == 'refs/heads/develop' }} | |
| type=raw,value=main,enable=${{ github.ref == 'refs/heads/main' }} | |
| type=ref,event=branch,enable=${{ github.ref != 'refs/heads/develop' && github.ref != 'refs/heads/main' }} | |
| # Version tags (only for releases) | |
| type=semver,pattern={{version}},enable=${{ steps.build-context.outputs.is-release == 'true' }} | |
| type=raw,value=latest,enable=${{ steps.build-context.outputs.is-release == 'true' && steps.build-context.outputs.is-prerelease == 'false' }} | |
| # Git SHA for traceability (always included) | |
| type=sha,prefix={{branch}}-,format=short,enable=${{ github.ref_type == 'branch' }} | |
| type=sha,format=short,enable=${{ github.ref_type == 'tag' }} | |
| - name: Synchronize frontend with backend | |
| run: | | |
| # For branches, use the SHA-suffixed tag (second tag), for tags use first tag | |
| if [[ "${{ github.ref_type }}" == "branch" ]]; then | |
| BACKEND_TAG=$(echo "${{ steps.meta-backend.outputs.tags }}" | sed -n '2p' | cut -d':' -f2) | |
| else | |
| BACKEND_TAG=$(echo "${{ steps.meta-backend.outputs.tags }}" | head -n1 | cut -d':' -f2) | |
| fi | |
| ./scripts/sync-frontend-with-backend.sh "${{ env.REGISTRY }}/${{ env.BACKEND_IMAGE_NAME }}:$BACKEND_TAG" | |
| - name: Build and push frontend Docker image | |
| uses: docker/build-push-action@v5 | |
| with: | |
| context: ./frontend | |
| file: ./frontend/Dockerfile | |
| push: true | |
| tags: ${{ steps.meta-frontend.outputs.tags }} | |
| labels: ${{ steps.meta-frontend.outputs.labels }} | |
| cache-from: type=gha | |
| cache-to: type=gha,mode=max | |
| # Summary of what was built | |
| - name: Build Summary | |
| run: | | |
| echo "## 🐳 Docker Images Built and Pushed" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| if [[ "${{ github.ref }}" == "refs/tags/v"* ]]; then | |
| VERSION="${GITHUB_REF#refs/tags/}" | |
| if [[ "$VERSION" == *-* ]]; then | |
| echo "### Pre-release: $VERSION" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "**Backend:**" >> $GITHUB_STEP_SUMMARY | |
| echo "- \`${{ env.REGISTRY }}/${{ env.BACKEND_IMAGE_NAME }}:$VERSION\`" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "**Frontend:**" >> $GITHUB_STEP_SUMMARY | |
| echo "- \`${{ env.REGISTRY }}/${{ env.FRONTEND_IMAGE_NAME }}:$VERSION\`" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "🧪 Pre-release images built for testing" >> $GITHUB_STEP_SUMMARY | |
| else | |
| echo "### Production Release: $VERSION" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "**Backend:**" >> $GITHUB_STEP_SUMMARY | |
| echo "- \`${{ env.REGISTRY }}/${{ env.BACKEND_IMAGE_NAME }}:$VERSION\`" >> $GITHUB_STEP_SUMMARY | |
| echo "- \`${{ env.REGISTRY }}/${{ env.BACKEND_IMAGE_NAME }}:latest\`" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "**Frontend:**" >> $GITHUB_STEP_SUMMARY | |
| echo "- \`${{ env.REGISTRY }}/${{ env.FRONTEND_IMAGE_NAME }}:$VERSION\`" >> $GITHUB_STEP_SUMMARY | |
| echo "- \`${{ env.REGISTRY }}/${{ env.FRONTEND_IMAGE_NAME }}:latest\`" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "✅ Ready for production deployment" >> $GITHUB_STEP_SUMMARY | |
| fi | |
| elif [[ "${{ github.ref }}" == "refs/heads/main" ]]; then | |
| echo "### Testing Environment Build" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "**Backend:** \`${{ env.REGISTRY }}/${{ env.BACKEND_IMAGE_NAME }}:main\`" >> $GITHUB_STEP_SUMMARY | |
| echo "**Frontend:** \`${{ env.REGISTRY }}/${{ env.FRONTEND_IMAGE_NAME }}:main\`" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "🧪 Images will be deployed to testing environment by ArgoCD/deployment system" >> $GITHUB_STEP_SUMMARY | |
| elif [[ "${{ github.ref }}" == "refs/heads/develop" ]]; then | |
| echo "### Development Environment Build" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "**Backend:** \`${{ env.REGISTRY }}/${{ env.BACKEND_IMAGE_NAME }}:develop\`" >> $GITHUB_STEP_SUMMARY | |
| echo "**Frontend:** \`${{ env.REGISTRY }}/${{ env.FRONTEND_IMAGE_NAME }}:develop\`" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "🔧 Images will be deployed to dev environment by ArgoCD/deployment system" >> $GITHUB_STEP_SUMMARY | |
| else | |
| BRANCH_NAME="${GITHUB_REF#refs/heads/}" | |
| BRANCH_TAG="${BRANCH_NAME//\//-}" | |
| echo "### Branch Build: $BRANCH_NAME" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "**Backend:** \`${{ env.REGISTRY }}/${{ env.BACKEND_IMAGE_NAME }}:$BRANCH_TAG\`" >> $GITHUB_STEP_SUMMARY | |
| echo "**Frontend:** \`${{ env.REGISTRY }}/${{ env.FRONTEND_IMAGE_NAME }}:$BRANCH_TAG\`" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "🚀 Branch images built for testing and development" >> $GITHUB_STEP_SUMMARY | |
| fi |