Skip to content

Commit 38b52e7

Browse files
authored
Merge pull request #3 from premtsd-code/feature/phase4-tests-quality
feat: Phase 4 — Tests, Code Quality, E2E, SonarCloud
2 parents 2b8fe7b + b3d911f commit 38b52e7

49 files changed

Lines changed: 4192 additions & 322 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/develop-ci-cd.yml

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,3 +120,33 @@ jobs:
120120
cd ~/personal/linkedin
121121
docker compose up -d
122122
echo "Rolled back ✅"
123+
124+
e2e-tests:
125+
name: E2E Tests
126+
runs-on: ubuntu-latest
127+
needs: deploy-dev
128+
continue-on-error: true
129+
steps:
130+
- uses: actions/checkout@v4
131+
- name: Set up JDK 17
132+
uses: actions/setup-java@v4
133+
with:
134+
java-version: '17'
135+
distribution: 'corretto'
136+
cache: maven
137+
- name: Wait for services to be ready
138+
run: |
139+
echo "Waiting for DEV to be ready..."
140+
sleep 30
141+
curl -f http://${{ secrets.HETZNER_IP }}:10000/actuator/health || echo "Health check failed, running tests anyway"
142+
echo "Services ready!"
143+
- name: Run E2E tests
144+
run: |
145+
cd e2e-tests
146+
mvn test -De2e.base.url=http://${{ secrets.HETZNER_IP }}:10000
147+
- name: Upload E2E results
148+
uses: actions/upload-artifact@v4
149+
if: always()
150+
with:
151+
name: e2e-test-results
152+
path: e2e-tests/target/surefire-reports/

.github/workflows/pr-checks.yml

Lines changed: 63 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -6,45 +6,9 @@ on:
66

77
jobs:
88

9-
detect-changes:
10-
name: Detect Changed Services
11-
runs-on: ubuntu-latest
12-
outputs:
13-
api-gateway: ${{ steps.changes.outputs.api-gateway }}
14-
user-service: ${{ steps.changes.outputs.user-service }}
15-
post-service: ${{ steps.changes.outputs.post-service }}
16-
connections-service: ${{ steps.changes.outputs.connections-service }}
17-
notification-service: ${{ steps.changes.outputs.notification-service }}
18-
uploader-service: ${{ steps.changes.outputs.uploader-service }}
19-
config-server: ${{ steps.changes.outputs.config-server }}
20-
discovery-server: ${{ steps.changes.outputs.discovery-server }}
21-
steps:
22-
- uses: actions/checkout@v4
23-
- uses: dorny/paths-filter@v3
24-
id: changes
25-
with:
26-
filters: |
27-
api-gateway:
28-
- 'api-gateway/**'
29-
user-service:
30-
- 'user-service/**'
31-
post-service:
32-
- 'post-service/**'
33-
connections-service:
34-
- 'connections-service/**'
35-
notification-service:
36-
- 'notification-service/**'
37-
uploader-service:
38-
- 'uploader-service/**'
39-
config-server:
40-
- 'config-server/**'
41-
discovery-server:
42-
- 'discovery-server/**'
43-
449
unit-tests:
4510
name: Unit Tests
4611
runs-on: ubuntu-latest
47-
continue-on-error: true
4812
steps:
4913
- uses: actions/checkout@v4
5014
- name: Set up JDK 17
@@ -55,23 +19,21 @@ jobs:
5519
cache: maven
5620
- name: Run unit tests
5721
run: |
58-
if [ -f "pom.xml" ]; then
59-
mvn test -DskipIntegrationTests=true || true
60-
else
61-
echo "No root pom.xml found — skipping tests"
62-
fi
22+
for svc in user-service post-service connections-service notification-service uploader-service; do
23+
echo "=== Testing $svc ==="
24+
cd $svc && mvn test -q && cd ..
25+
done
6326
- name: Upload test results
6427
uses: actions/upload-artifact@v4
6528
if: always()
66-
continue-on-error: true
6729
with:
6830
name: unit-test-results
6931
path: '**/target/surefire-reports/*.xml'
7032

7133
code-coverage:
7234
name: Code Coverage
7335
runs-on: ubuntu-latest
74-
continue-on-error: true
36+
needs: unit-tests
7537
steps:
7638
- uses: actions/checkout@v4
7739
- name: Set up JDK 17
@@ -82,14 +44,12 @@ jobs:
8244
cache: maven
8345
- name: Run tests with coverage
8446
run: |
85-
if [ -f "pom.xml" ]; then
86-
mvn verify jacoco:report -DskipIntegrationTests=true || true
87-
else
88-
echo "No root pom.xml — skipping coverage"
89-
fi
47+
for svc in user-service post-service connections-service notification-service uploader-service; do
48+
echo "=== Coverage for $svc ==="
49+
cd $svc && mvn test jacoco:report -q && cd ..
50+
done
9051
- name: Upload coverage report
9152
uses: actions/upload-artifact@v4
92-
continue-on-error: true
9353
with:
9454
name: coverage-report
9555
path: '**/target/site/jacoco/'
@@ -108,18 +68,14 @@ jobs:
10868
cache: maven
10969
- name: OWASP Dependency Check
11070
run: |
111-
if [ -f "pom.xml" ]; then
112-
mvn dependency-check:check \
113-
-DfailBuildOnCVSS=7 \
114-
-DskipTestScope=true || true
115-
else
116-
echo "No root pom.xml — skipping OWASP"
117-
fi
118-
continue-on-error: true
71+
for svc in user-service post-service connections-service notification-service uploader-service; do
72+
echo "=== OWASP scan for $svc ==="
73+
cd $svc && mvn dependency-check:check -DfailBuildOnCVSS=7 -DskipTestScope=true || true
74+
cd ..
75+
done
11976
- name: Upload OWASP report
12077
uses: actions/upload-artifact@v4
12178
if: always()
122-
continue-on-error: true
12379
with:
12480
name: owasp-report
12581
path: '**/target/dependency-check-report.html'
@@ -130,8 +86,6 @@ jobs:
13086
continue-on-error: true
13187
steps:
13288
- uses: actions/checkout@v4
133-
with:
134-
fetch-depth: 0
13589
- name: Set up JDK 17
13690
uses: actions/setup-java@v4
13791
with:
@@ -140,17 +94,54 @@ jobs:
14094
cache: maven
14195
- name: Checkstyle
14296
run: |
143-
if [ -f "pom.xml" ]; then
144-
mvn checkstyle:check || true
145-
else
146-
echo "No root pom.xml — skipping checkstyle"
147-
fi
148-
continue-on-error: true
97+
for svc in user-service post-service connections-service notification-service uploader-service; do
98+
echo "=== Checkstyle for $svc ==="
99+
cd $svc && mvn checkstyle:check -q || true
100+
cd ..
101+
done
149102
- name: SpotBugs
150103
run: |
151-
if [ -f "pom.xml" ]; then
152-
mvn spotbugs:check || true
153-
else
154-
echo "No root pom.xml — skipping spotbugs"
155-
fi
156-
continue-on-error: true
104+
for svc in user-service post-service connections-service notification-service uploader-service; do
105+
echo "=== SpotBugs for $svc ==="
106+
cd $svc && mvn compile spotbugs:check -q || true
107+
cd ..
108+
done
109+
110+
sonarcloud:
111+
name: SonarCloud Analysis
112+
runs-on: ubuntu-latest
113+
needs: unit-tests
114+
continue-on-error: true
115+
steps:
116+
- uses: actions/checkout@v4
117+
with:
118+
fetch-depth: 0
119+
- name: Set up JDK 17
120+
uses: actions/setup-java@v4
121+
with:
122+
java-version: '17'
123+
distribution: 'corretto'
124+
cache: maven
125+
- name: Cache SonarCloud packages
126+
uses: actions/cache@v4
127+
with:
128+
path: ~/.sonar/cache
129+
key: ${{ runner.os }}-sonar
130+
restore-keys: ${{ runner.os }}-sonar
131+
- name: SonarCloud Scan
132+
env:
133+
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
134+
run: |
135+
for svc in user-service post-service connections-service notification-service uploader-service; do
136+
echo "=== Scanning $svc ==="
137+
cd $svc
138+
mvn verify jacoco:report sonar:sonar -DskipTests \
139+
-Dsonar.projectKey=premtsd-code_LinkedIn_${svc} \
140+
-Dsonar.organization=premtsd-code \
141+
-Dsonar.host.url=https://sonarcloud.io \
142+
-Dsonar.projectName="${svc}" \
143+
-Dsonar.java.coveragePlugin=jacoco \
144+
-Dsonar.coverage.jacoco.xmlReportPaths=target/site/jacoco/jacoco.xml \
145+
|| true
146+
cd ..
147+
done

connections-service/pom.xml

Lines changed: 76 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
<url/>
2828
</scm>
2929
<properties>
30-
<java.version>21</java.version>
30+
<java.version>17</java.version>
3131
<spring-cloud.version>2023.0.3</spring-cloud.version>
3232
</properties>
3333
<dependencies>
@@ -73,6 +73,21 @@
7373
<artifactId>spring-kafka-test</artifactId>
7474
<scope>test</scope>
7575
</dependency>
76+
<dependency>
77+
<groupId>org.testcontainers</groupId>
78+
<artifactId>kafka</artifactId>
79+
<scope>test</scope>
80+
</dependency>
81+
<dependency>
82+
<groupId>com.h2database</groupId>
83+
<artifactId>h2</artifactId>
84+
<scope>test</scope>
85+
</dependency>
86+
<dependency>
87+
<groupId>org.springframework.security</groupId>
88+
<artifactId>spring-security-test</artifactId>
89+
<scope>test</scope>
90+
</dependency>
7691
<dependency>
7792
<groupId>org.springframework.kafka</groupId>
7893
<artifactId>spring-kafka</artifactId>
@@ -122,7 +137,7 @@
122137
<dependency>
123138
<groupId>org.testcontainers</groupId>
124139
<artifactId>testcontainers-bom</artifactId>
125-
<version>1.19.0</version>
140+
<version>1.19.3</version>
126141
<type>pom</type>
127142
<scope>import</scope>
128143
</dependency>
@@ -164,6 +179,65 @@
164179
</execution>
165180
</executions>
166181
</plugin>
182+
<plugin>
183+
<groupId>org.jacoco</groupId>
184+
<artifactId>jacoco-maven-plugin</artifactId>
185+
<version>0.8.11</version>
186+
<executions>
187+
<execution>
188+
<goals><goal>prepare-agent</goal></goals>
189+
</execution>
190+
<execution>
191+
<id>report</id>
192+
<phase>test</phase>
193+
<goals><goal>report</goal></goals>
194+
</execution>
195+
<execution>
196+
<id>check</id>
197+
<goals><goal>check</goal></goals>
198+
<configuration>
199+
<rules>
200+
<rule>
201+
<element>BUNDLE</element>
202+
<limits>
203+
<limit>
204+
<counter>LINE</counter>
205+
<value>COVEREDRATIO</value>
206+
<minimum>0.70</minimum>
207+
</limit>
208+
</limits>
209+
</rule>
210+
</rules>
211+
</configuration>
212+
</execution>
213+
</executions>
214+
</plugin>
215+
<plugin>
216+
<groupId>org.apache.maven.plugins</groupId>
217+
<artifactId>maven-checkstyle-plugin</artifactId>
218+
<version>3.3.1</version>
219+
<configuration>
220+
<configLocation>google_checks.xml</configLocation>
221+
<failOnViolation>false</failOnViolation>
222+
</configuration>
223+
</plugin>
224+
<plugin>
225+
<groupId>com.github.spotbugs</groupId>
226+
<artifactId>spotbugs-maven-plugin</artifactId>
227+
<version>4.8.3.1</version>
228+
<configuration>
229+
<threshold>High</threshold>
230+
<failOnError>false</failOnError>
231+
</configuration>
232+
</plugin>
233+
<plugin>
234+
<groupId>org.owasp</groupId>
235+
<artifactId>dependency-check-maven</artifactId>
236+
<version>9.0.9</version>
237+
<configuration>
238+
<failBuildOnCVSS>7</failBuildOnCVSS>
239+
</configuration>
240+
</plugin>
167241
</plugins>
168242
</build>
169243

connections-service/src/test/java/com/premtsd/linkedin/connectionservice/ConnectionsServiceApplicationTests.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
package com.premtsd.linkedin.connectionservice;
22

33
import org.junit.jupiter.api.Test;
4+
import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable;
45
import org.springframework.boot.test.context.SpringBootTest;
56

67
@SpringBootTest
8+
@EnabledIfEnvironmentVariable(named = "DOCKER_AVAILABLE", matches = "true")
79
class ConnectionsServiceApplicationTests {
810

911
@Test

connections-service/src/test/java/com/premtsd/linkedin/connectionservice/integration/ConnectionsControllerIntegrationTest.java

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,16 @@
11
package com.premtsd.linkedin.connectionservice.integration;
22

3-
import com.fasterxml.jackson.databind.ObjectMapper;
43
import com.premtsd.linkedin.connectionservice.entity.Person;
54
import com.premtsd.linkedin.connectionservice.exception.BusinessRuleViolationException;
65
import com.premtsd.linkedin.connectionservice.service.ConnectionsService;
76
import org.junit.jupiter.api.Test;
87
import org.springframework.beans.factory.annotation.Autowired;
9-
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureWebMvc;
10-
import org.springframework.boot.test.context.SpringBootTest;
8+
import com.premtsd.linkedin.connectionservice.controller.ConnectionsController;
9+
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
10+
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
1111
import org.springframework.boot.test.mock.mockito.MockBean;
1212
import org.springframework.http.MediaType;
13+
import org.springframework.test.context.ActiveProfiles;
1314
import org.springframework.test.web.servlet.MockMvc;
1415

1516
import java.util.Arrays;
@@ -20,8 +21,9 @@
2021
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
2122
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
2223

23-
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
24-
@AutoConfigureWebMvc
24+
@WebMvcTest(ConnectionsController.class)
25+
@AutoConfigureMockMvc(addFilters = false)
26+
@ActiveProfiles("test")
2527
class ConnectionsControllerIntegrationTest {
2628

2729
@Autowired
@@ -30,9 +32,6 @@ class ConnectionsControllerIntegrationTest {
3032
@MockBean
3133
private ConnectionsService connectionsService;
3234

33-
@Autowired
34-
private ObjectMapper objectMapper;
35-
3635
private static final String X_USER_ID_HEADER = "X-User-Id";
3736

3837
@Test

0 commit comments

Comments
 (0)