1- name : Reservation Service CI/CD
1+ # Multi-stage Dockerfile for Reservation Service
22
3- on :
4- push :
5- branches : [ main ]
6- pull_request :
7- branches : [ main ]
8- workflow_dispatch :
3+ # Stage 1: Build stage
4+ FROM maven:3.9-eclipse-temurin-17 AS build
5+ WORKDIR /app
96
10- env :
11- JAVA_VERSION : ' 17'
12- MAVEN_CLI_OPTS : ' -B --no-transfer-progress'
13- DOCKER_IMAGE_NAME : reservation-service
14- REGISTRY : docker.io
7+ # Copy Maven wrapper and pom.xml first for dependency caching
8+ COPY mvnw .
9+ COPY .mvn .mvn
10+ COPY pom.xml .
1511
16- jobs :
17- # Job 1: Code Quality & Security
18- code-quality :
19- name : Code Quality & Security Checks
20- runs-on : ubuntu-latest
21-
22- steps :
23- - name : Checkout code
24- uses : actions/checkout@v4
25- with :
26- fetch-depth : 0 # Shallow clones should be disabled for better analysis
12+ # Download dependencies (cached if pom.xml hasn't changed)
13+ RUN mvn dependency:go-offline -B
2714
28- - name : Set up JDK ${{ env.JAVA_VERSION }}
29- uses : actions/setup-java@v4
30- with :
31- java-version : ${{ env.JAVA_VERSION }}
32- distribution : ' temurin'
33- cache : ' maven'
15+ # Copy source code
16+ COPY src ./src
3417
35- - name : Cache SonarCloud packages
36- uses : actions/cache@v3
37- with :
38- path : ~/.sonar/cache
39- key : ${{ runner.os }}-sonar
40- restore-keys : ${{ runner.os }}-sonar
18+ # Build the application (skip tests for faster builds)
19+ RUN mvn clean package -DskipTests
4120
42- - name : Run code style checks
43- run : mvn ${{ env.MAVEN_CLI_OPTS }} checkstyle:check
44- continue-on-error : true
21+ # Stage 2: Runtime stage
22+ FROM eclipse-temurin:17-jre
23+ WORKDIR /app
4524
46- - name : Run SpotBugs analysis
47- run : mvn ${{ env.MAVEN_CLI_OPTS }} compile spotbugs:check
48- continue-on-error : true
25+ # Add non-root user for security
26+ RUN groupadd -r spring && useradd -r -g spring spring
27+ USER spring:spring
4928
50- # Job 2: Build
51- build :
52- name : Build
53- runs-on : ubuntu-latest
54- needs : code-quality
29+ # Copy the built artifact from build stage
30+ COPY --from=build /app/target/reservation-service-*.jar app.jar
5531
56- steps :
57- - name : Checkout code
58- uses : actions/checkout@v4
32+ # Expose the application port
33+ EXPOSE 8084
5934
60- - name : Set up JDK ${{ env.JAVA_VERSION }}
61- uses : actions/setup-java@v4
62- with :
63- java-version : ${{ env.JAVA_VERSION }}
64- distribution : ' temurin'
65- cache : ' maven'
35+ # Set JVM options for containerized environment
36+ ENV JAVA_OPTS="-XX:+UseContainerSupport -XX:MaxRAMPercentage=75.0 -XX:+UseG1GC"
6637
67- - name : Build with Maven
68- run : mvn ${{ env.MAVEN_CLI_OPTS }} clean compile
38+ # Health check
39+ HEALTHCHECK --interval=30s --timeout=3s --start-period=40s --retries=3 \
40+ CMD curl -f http://localhost:8084/actuator/health || exit 1
6941
70- - name : Package application
71- run : mvn ${{ env.MAVEN_CLI_OPTS }} package -DskipTests
72-
73- - name : Upload build artifact
74- uses : actions/upload-artifact@v4
75- with :
76- name : reservation-service-jar
77- path : target/*.jar
78- retention-days : 5
79-
80- # Job 3: Docker Build & Push
81- docker-build-push :
82- name : Build & Push Docker Image
83- runs-on : ubuntu-latest
84- needs : build
85- if : github.event_name == 'push'
86- permissions :
87- contents : read
88- packages : write
89-
90- steps :
91- - name : Checkout code
92- uses : actions/checkout@v4
93-
94- - name : Set up Docker Buildx
95- uses : docker/setup-buildx-action@v3
96-
97- - name : Log in to Docker Hub
98- uses : docker/login-action@v3
99- with :
100- username : ${{ secrets.DOCKER_HUB_USERNAME }}
101- password : ${{ secrets.DOCKER_HUB_TOKEN }}
102-
103- - name : Extract metadata for Docker
104- id : meta
105- uses : docker/metadata-action@v5
106- with :
107- images : ${{ secrets.DOCKER_HUB_USERNAME }}/${{ env.DOCKER_IMAGE_NAME }}
108- tags : |
109- type=ref,event=branch
110- type=ref,event=pr
111- type=sha,prefix={{branch}}-
112- type=semver,pattern={{version}}
113- type=semver,pattern={{major}}.{{minor}}
114- type=raw,value=latest,enable={{is_default_branch}}
115-
116- - name : Build and push Docker image
117- uses : docker/build-push-action@v5
118- with :
119- context : .
120- file : ./Dockerfile
121- push : true
122- tags : ${{ steps.meta.outputs.tags }}
123- labels : ${{ steps.meta.outputs.labels }}
124- cache-from : type=gha
125- cache-to : type=gha,mode=max
126- platforms : linux/amd64,linux/arm64
127-
128- - name : Generate SBOM
129- uses : anchore/sbom-action@v0
130- with :
131- image : ${{ secrets.DOCKER_HUB_USERNAME }}/${{ env.DOCKER_IMAGE_NAME }}:${{ github.sha }}
132- format : spdx-json
133- output-file : sbom.spdx.json
134-
135- - name : Upload SBOM
136- uses : actions/upload-artifact@v4
137- with :
138- name : sbom
139- path : sbom.spdx.json
140-
141- # Job 4: Security Scan
142- security-scan :
143- name : Security Vulnerability Scan
144- runs-on : ubuntu-latest
145- needs : docker-build-push
146- if : github.event_name == 'push'
147- permissions :
148- contents : read
149- security-events : write
150-
151- steps :
152- - name : Checkout code
153- uses : actions/checkout@v4
154-
155- - name : Log in to Docker Hub
156- uses : docker/login-action@v3
157- with :
158- username : ${{ secrets.DOCKER_HUB_USERNAME }}
159- password : ${{ secrets.DOCKER_HUB_TOKEN }}
160-
161- - name : Run Trivy vulnerability scanner
162- uses : aquasecurity/trivy-action@master
163- with :
164- image-ref : ${{ secrets.DOCKER_HUB_USERNAME }}/${{ env.DOCKER_IMAGE_NAME }}:${{ github.sha }}
165- format : ' sarif'
166- output : ' trivy-results.sarif'
167- severity : ' CRITICAL,HIGH'
168-
169- - name : Upload Trivy results to GitHub Security
170- uses : github/codeql-action/upload-sarif@v3
171- if : always()
172- with :
173- sarif_file : ' trivy-results.sarif'
174-
175- - name : Dependency Check
176- uses : dependency-check/Dependency-Check_Action@main
177- with :
178- project : ' reservation-service'
179- path : ' .'
180- format : ' HTML'
181- args : >
182- --failOnCVSS 7
183- --enableRetired
184-
185- - name : Upload Dependency Check report
186- uses : actions/upload-artifact@v4
187- if : always()
188- with :
189- name : dependency-check-report
190- path : reports/
191-
192- # Job 5: Deploy to Development
193- deploy-dev :
194- name : Deploy to Development
195- runs-on : ubuntu-latest
196- needs : [docker-build-push, security-scan]
197- if : github.ref == 'refs/heads/dev' || github.ref == 'refs/heads/dev-update'
198- environment :
199- name : development
200- url : https://dev-reservation-service.exhibitflow.com
201-
202- steps :
203- - name : Checkout code
204- uses : actions/checkout@v4
205-
206- - name : Deploy to Development Server
207- uses : appleboy/ssh-action@v1.0.0
208- with :
209- host : ${{ secrets.DEV_SERVER_HOST }}
210- username : ${{ secrets.DEV_SERVER_USER }}
211- key : ${{ secrets.DEV_SERVER_SSH_KEY }}
212- port : ${{ secrets.DEV_SERVER_PORT }}
213- script : |
214- cd /opt/reservation-service
215- docker compose pull
216- docker compose up -d
217- docker system prune -f
218-
219- - name : Verify deployment
220- run : |
221- sleep 10
222- curl -f ${{ secrets.DEV_SERVER_URL }}/actuator/health || exit 1
42+ # Run the application
43+ ENTRYPOINT ["sh", "-c", "java $JAVA_OPTS -jar app.jar"]
0 commit comments