1+ name : DevSecOps CI Pipeline
2+
3+ on :
4+ push :
5+ branches : [ "main" ]
6+ paths-ignore :
7+ - ' kubernetes/**' # Ignore changes to this file to prevent loops
8+ - ' README.md'
9+ - ' assets/**'
10+ pull_request :
11+ branches : [ "main" ]
12+ workflow_dispatch :
13+
14+ jobs :
15+ security-prechecks :
16+ name : Security Prechecks
17+ runs-on : ubuntu-latest
18+ steps :
19+ # Git Checkout
20+ - name : Checkout Repository
21+ uses : actions/checkout@v4
22+ with :
23+ fetch-depth : 0 # fetch all history for all branches and tags
24+
25+ # Secrets Scanning (Gitleaks)
26+ - name : Gitleaks
27+ uses : gitleaks/gitleaks-action@v2
28+ with :
29+ fail : true
30+ env :
31+ GITHUB_TOKEN : ${{ secrets.GITHUB_TOKEN }}
32+
33+ # Dependency & IaC Scan (Trivy FS)
34+ - name : Trivy FS Scan
35+ uses : aquasecurity/trivy-action@0.33.1
36+ with :
37+ scan-type : ' fs'
38+ scan-ref : ' .'
39+ severity : CRITICAL,HIGH
40+ exit-code : 1
41+ ignore-unfixed : true
42+
43+ unit-test :
44+ name : Unit Testing
45+ needs : security-prechecks
46+ runs-on : ubuntu-latest
47+ steps :
48+ - name : Checkout Repository
49+ uses : actions/checkout@v4
50+
51+ # SetUp NodeJs Env
52+ - name : Setup Node.js environment
53+ uses : actions/setup-node@v6
54+ with :
55+ node-version : 20
56+ cache : npm
57+
58+ # Install Dependencies
59+ - name : Install Dependencies
60+ run : npm ci
61+
62+ # Run Unit Tests
63+ - name : Run Unit Tests
64+ run : npm test
65+
66+ static-testing :
67+ name : Static Code Quality
68+ needs : unit-test
69+ runs-on : ubuntu-latest
70+ steps :
71+ # Checkout
72+ - name : Checkout Repository
73+ uses : actions/checkout@v4
74+ with :
75+ fetch-depth : 0
76+
77+ # SonarCloud Analysis
78+ - name : SonarCloud Scan
79+ uses : sonarsource/sonarqube-scan-action@v2
80+ env :
81+ SONAR_TOKEN : ${{ secrets.SONAR_TOKEN }}
82+
83+ # Quality Gate Enforcement
84+ - name : SonarCloud Quality Gate
85+ uses : sonarsource/sonarqube-quality-gate-action@v1
86+ timeout-minutes : 5
87+ env :
88+ SONAR_TOKEN : ${{ secrets.SONAR_TOKEN }}
89+
90+ build-artifacts :
91+ name : Build and Store Artifacts
92+ runs-on : ubuntu-latest
93+ needs : static-testing
94+ steps :
95+ - name : Checkout Repository
96+ uses : actions/checkout@v4
97+
98+ # SetUp NodeJs Env
99+ - name : Setup Node.js environment
100+ uses : actions/setup-node@v6
101+ with :
102+ node-version : 20
103+ cache : npm
104+
105+ # Install Dependencies
106+ - name : Install Dependencies
107+ run : npm ci
108+
109+ # Build Project
110+ - name : Build Project
111+ run : npm run build
112+
113+ # Upload Artifacts
114+ - name : Upload build artifacts
115+ uses : actions/upload-artifact@v4
116+ with :
117+ name : build-artifacts
118+ path : dist/
119+
120+ docker :
121+ name : Container Build & Security
122+ runs-on : ubuntu-latest
123+ needs : build-artifacts
124+ permissions :
125+ contents : read
126+ packages : write
127+ env :
128+ REGISTRY : ghcr.io
129+ IMAGE_NAME : ${{ github.repository }}
130+ IMAGE_TAG : ${{ github.sha }}
131+ outputs :
132+ image_tag : ${{ steps.export-image-tag.outputs.image_tag }}
133+ steps :
134+ - name : Checkout code
135+ uses : actions/checkout@v4
136+
137+ # Download build artifacts
138+ - name : Download build artifacts
139+ uses : actions/download-artifact@v4
140+ with :
141+ name : build-artifacts
142+ path : dist/
143+
144+ # Setup Docker Buildx
145+ - name : Set up Docker Buildx
146+ uses : docker/setup-buildx-action@v3
147+
148+ # Login to GHCR
149+ - name : Login to GitHub Container Registry
150+ uses : docker/login-action@v3
151+ with :
152+ registry : ghcr.io
153+ username : ${{ github.actor }}
154+ password : ${{ secrets.GITHUB_TOKEN }}
155+
156+ # Build Docker Image
157+ - name : Build Docker image
158+ uses : docker/build-push-action@v5
159+ with :
160+ context : .
161+ file : Dockerfile.ci
162+ load : true # load image into the local Docker daemon of this GitHub runner
163+ push : false
164+ tags : ghcr.io/${{ env.IMAGE_NAME }}:${{ env.IMAGE_TAG }}
165+
166+ # Trivy Image Scan
167+ - name : Trivy Image Scan
168+ uses : aquasecurity/trivy-action@0.33.1
169+ with :
170+ image-ref : ghcr.io/${{ env.IMAGE_NAME }}:${{ env.IMAGE_TAG }}
171+ severity : CRITICAL,HIGH
172+ exit-code : 1
173+ ignore-unfixed : true
174+ vuln-type : os,library
175+
176+ # Push Image
177+ - name : Push Docker image
178+ uses : docker/build-push-action@v5
179+ with :
180+ context : .
181+ push : true
182+ tags : ghcr.io/${{ env.IMAGE_NAME }}:${{ env.IMAGE_TAG }}
183+
184+ # Export image tag as job output
185+ - name : Export image tag
186+ id : export-image-tag
187+ run : |
188+ echo "image_tag=${{ github.sha }}" >> $GITHUB_OUTPUT
189+
190+ update-k8s-manifest :
191+ name : Update Kubernetes Manifest
192+ runs-on : ubuntu-latest
193+ needs : docker
194+ permissions :
195+ contents : write # required to push commit
196+ steps :
197+ - name : Checkout repository
198+ uses : actions/checkout@v4
199+
200+ # Update image tag in deployment.yml
201+ - name : Update image tag
202+ run : |
203+ sed -i "s|image: .*tic-tac-toe-app:.*|image: ghcr.io/atkaridarshan04/tic-tac-toe-app:${{ needs.docker.outputs.image_tag }}|" kubernetes/deployment.yml
204+
205+ # Commit and push change
206+ - name : Commit and push changes
207+ run : |
208+ git config user.name "github-actions"
209+ git config user.email "github-actions@github.com"
210+
211+ git add kubernetes/deployment.yml
212+ git commit -m "chore: Update deployment image tag to ${{ needs.docker.outputs.image_tag }}"
213+ git push
0 commit comments