1+ # ============================================================
2+ # .github/workflows/docker.yml
3+ #
4+ # Builds the Django dev container image and pushes to Docker Hub.
5+ # Cross-platform: linux/amd64 (Windows/Linux) + linux/arm64 (Apple Silicon)
6+ #
7+ # Triggers:
8+ # - Push to main → builds + pushes :latest + :sha-xxx
9+ # - PR targeting main → builds only (no push) — validates Dockerfile
10+ # - Manual dispatch → optional push, optional force rebuild
11+ #
12+ # Required GitHub Secrets:
13+ # DOCKERHUB_USERNAME Docker Hub username
14+ # DOCKERHUB_TOKEN Docker Hub access token (Read/Write)
15+ #
16+ # Platforms:
17+ # linux/amd64 — Windows / Linux / GCP
18+ # linux/arm64 — Apple Silicon Macs
19+ # ============================================================
20+
21+ name : Docker
22+
23+ on :
24+ push :
25+ branches :
26+ - main
27+ paths :
28+ - " docker/Dockerfile.dev"
29+ - " scripts/**"
30+ - " .github/workflows/docker.yml"
31+
32+ pull_request :
33+ branches :
34+ - main
35+ paths :
36+ - " docker/Dockerfile.dev"
37+ - " scripts/**"
38+ - " .github/workflows/docker.yml"
39+
40+ workflow_dispatch :
41+ inputs :
42+ push_image :
43+ description : " Push image to Docker Hub?"
44+ required : true
45+ default : " true"
46+ type : choice
47+ options :
48+ - " true"
49+ - " false"
50+ force_rebuild :
51+ description : " Bypass layer cache (full rebuild)"
52+ required : false
53+ type : boolean
54+ default : false
55+
56+ concurrency :
57+ group : docker-${{ github.ref }}
58+ cancel-in-progress : false
59+
60+ env :
61+ IMAGE_NAME : alihaidar199527/django-devcontainer
62+
63+ jobs :
64+
65+ build-and-push :
66+ name : Build & Push Dev Image
67+ runs-on : ubuntu-latest
68+
69+ permissions :
70+ contents : read
71+
72+ steps :
73+
74+ - name : Checkout
75+ uses : actions/checkout@v6
76+
77+ - name : Set up QEMU
78+ uses : docker/setup-qemu-action@v4
79+
80+ - name : Set up Docker Buildx
81+ uses : docker/setup-buildx-action@v4
82+
83+ - name : Log in to Docker Hub
84+ # Skip login on PR builds — we are not pushing, no credentials needed
85+ if : github.event_name != 'pull_request'
86+ uses : docker/login-action@v4
87+ with :
88+ username : ${{ secrets.DOCKERHUB_USERNAME }}
89+ password : ${{ secrets.DOCKERHUB_TOKEN }}
90+
91+ - name : Extract image metadata
92+ id : meta
93+ uses : docker/metadata-action@v6
94+ with :
95+ images : ${{ env.IMAGE_NAME }}
96+ tags : |
97+ type=raw,value=latest,enable=${{ github.ref == 'refs/heads/main' }}
98+ type=sha,prefix=sha-,format=short
99+
100+ - name : Build and push
101+ id : build
102+ uses : docker/build-push-action@v7
103+ with :
104+ context : .
105+ file : docker/Dockerfile.dev
106+ platforms : linux/amd64,linux/arm64
107+ # Push only on a real push to main or an approved manual dispatch
108+ # PR builds compile the image to validate it but never push
109+ push : ${{ github.event_name == 'push' || (github.event_name == 'workflow_dispatch' && inputs.push_image == 'true') }}
110+ tags : ${{ steps.meta.outputs.tags }}
111+ labels : ${{ steps.meta.outputs.labels }}
112+ cache-from : type=gha
113+ cache-to : type=gha,mode=max
114+ no-cache : ${{ inputs.force_rebuild == true }}
115+ provenance : true
116+ sbom : true
117+
118+ - name : Write job summary
119+ if : always()
120+ run : |
121+ echo "## 🐳 Docker Build Summary" >> $GITHUB_STEP_SUMMARY
122+ echo "" >> $GITHUB_STEP_SUMMARY
123+ echo "| Field | Value |" >> $GITHUB_STEP_SUMMARY
124+ echo "|-------|-------|" >> $GITHUB_STEP_SUMMARY
125+ echo "| **Image** | \`${{ env.IMAGE_NAME }}\` |" >> $GITHUB_STEP_SUMMARY
126+ echo "| **Digest** | \`${{ steps.build.outputs.digest }}\` |" >> $GITHUB_STEP_SUMMARY
127+ echo "| **Tags** | \`${{ steps.meta.outputs.tags }}\` |" >> $GITHUB_STEP_SUMMARY
128+ echo "| **Platforms** | \`linux/amd64, linux/arm64\` |" >> $GITHUB_STEP_SUMMARY
129+ echo "| **Triggered by** | \`${{ github.event_name }}\` on \`${{ github.ref_name }}\` |" >> $GITHUB_STEP_SUMMARY
130+ echo "| **Commit** | \`${{ github.sha }}\` |" >> $GITHUB_STEP_SUMMARY
131+ echo "| **Pushed to Docker Hub** | \`${{ github.event_name == 'push' || (github.event_name == 'workflow_dispatch' && inputs.push_image == 'true') }}\` |" >> $GITHUB_STEP_SUMMARY
0 commit comments