Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions .github/workflows/verify-formatting.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
name: Verify Formatting
on:
pull_request:
branches:
- main

jobs:
spotless:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0

- name: Set up JDK 21
uses: actions/setup-java@v5
with:
java-version: 21
distribution: 'zulu'

- name: Cache Gradle packages
uses: actions/cache@v5
with:
path: |
~/.gradle/caches
~/.gradle/wrapper
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
restore-keys: |
${{ runner.os }}-gradle-

- name: Spotless Check
run: ./gradlew spotlessCheck
41 changes: 41 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,47 @@ RTR uses Kafka to stream change events from transactional data sources into repo

To set up a local development environment follow the guide [here](documentation/DevSetup.md)

## Code Quality and Formatting

This project uses [Spotless](https://github.com/diffplug/spotless) with [Google Java Format](https://github.com/google/google-java-format) to maintain consistent code style.

### Running Spotless Locally

To check if your code adheres to the formatting standards:
```sh
./gradlew spotlessCheck
```

To automatically apply formatting fixes:
```sh
./gradlew spotlessApply
```

**NOTE:** Spotless will automatically be applied after you compile your code with `./gradlew compileJava`

### Formatting Specific Files or Directories

To run Spotless on a specific file or set of files, you can use the `-PspotlessFiles` property. Providing this property automatically bypasses the incremental (`ratchetFrom`) check, allowing you to force-format existing files.

* **Format a specific service (bypasses the incremental check):**
```sh
./gradlew :liquibase-service:spotlessApply -PspotlessFiles='.*\.java'
```

* **Format a specific file using its relative path:**
```sh
./gradlew spotlessApply -PspotlessFiles='liquibase-service/src/main/java/MyFile.java'
```

* **Format multiple specific files (comma-separated):**
```sh
./gradlew spotlessApply -PspotlessFiles='File1.java,File2.java'
```

> **Note:** If you use a subproject task (e.g., `:common-util:spotlessApply`), you can only target files within that subproject's directory. Use the root `spotlessApply` task if you want to target files across different services using their full repository paths.

Formatting is enforced on all Pull Requests via GitHub Actions. It is recommended to run `spotlessApply` before committing your changes.

# CDCgov GitHub Organization Open Source Project Template

**Template for clearance: This project serves as a template to aid projects in starting up and moving through clearance procedures. To start, create a new repository and implement the required [open practices](open_practices.md), train on and agree to adhere to the organization's [rules of behavior](rules_of_behavior.md), and [send a request through the create repo form](https://forms.office.com/Pages/ResponsePage.aspx?id=aQjnnNtg_USr6NJ2cHf8j44WSiOI6uNOvdWse4I-C2NUNk43NzMwODJTRzA4NFpCUk1RRU83RTFNVi4u) using language from this template as a Guide.**
Expand Down
27 changes: 25 additions & 2 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,17 @@ buildscript {

plugins {
id 'org.sonarqube' version '4.2.1.3168'
id 'com.diffplug.spotless' version '8.3.0'
}

version = '1.0.1-SNAPSHOT'
apply plugin: "com.dipien.semantic-version"

subprojects {
repositories {
mavenCentral()
}

subprojects {
repositories {
mavenCentral()
maven {
Expand All @@ -29,6 +33,25 @@ subprojects {

apply plugin: 'java'
apply plugin: 'jacoco'
apply plugin: 'com.diffplug.spotless'

spotless {
// Disable incremental check if specific files are provided via CLI
if (!project.hasProperty('spotlessFiles')) {
ratchetFrom 'origin/main'
}
java {
target 'src/*/java/**/*.java'
googleJavaFormat()
formatAnnotations()
trimTrailingWhitespace()
endWithNewline()
}
}

tasks.named('compileJava') {
dependsOn tasks.named('spotlessApply')
}

jacocoTestReport {
dependsOn test
Expand All @@ -49,4 +72,4 @@ sonarqube {
property "sonar.organization", "cdcgov"
property "sonar.host.url", "https://sonarcloud.io"
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
@SpringBootApplication
public class EtlDataPipelineApplication {

public static void main(String[] args) {
SpringApplication.run(EtlDataPipelineApplication.class, args);
}
public static void main(String[] args) {
SpringApplication.run(EtlDataPipelineApplication.class, args);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,15 @@
@RestController
public class DataPipelineController {

DataPipelineStatusService dataPipelineStatusSvc;
DataPipelineStatusService dataPipelineStatusSvc;

public DataPipelineController(DataPipelineStatusService dataPipelineStatusSvc) {
this.dataPipelineStatusSvc = dataPipelineStatusSvc;
}


@GetMapping("/status")
@ResponseBody
public ResponseEntity<String> getDataPipelineStatusHealth() {
return this.dataPipelineStatusSvc.getHealthStatus();
}
public DataPipelineController(DataPipelineStatusService dataPipelineStatusSvc) {
this.dataPipelineStatusSvc = dataPipelineStatusSvc;
}

@GetMapping("/status")
@ResponseBody
public ResponseEntity<String> getDataPipelineStatusHealth() {
return this.dataPipelineStatusSvc.getHealthStatus();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,12 @@

@Service
public class DataPipelineStatusService {
private static final Logger LOG = LoggerFactory.getLogger(DataPipelineStatusService.class);
private static final Logger LOG = LoggerFactory.getLogger(DataPipelineStatusService.class);

public DataPipelineStatusService() {
}
public DataPipelineStatusService() {}

public ResponseEntity<String> getHealthStatus(){
LOG.info("Status OK");
return ResponseEntity.status(HttpStatus.OK).body("Status OK");
}
public ResponseEntity<String> getHealthStatus() {
LOG.info("Status OK");
return ResponseEntity.status(HttpStatus.OK).body("Status OK");
}
}
Original file line number Diff line number Diff line change
@@ -1,25 +1,27 @@
package gov.cdc.etldatapipeline;

import static org.mockito.Mockito.mockStatic;

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.springframework.boot.SpringApplication;

import static org.mockito.Mockito.mockStatic;

class EtlDataPipelineApplicationTests {

@Test
void testMainMethod() {
try (var springApplicationMock = mockStatic(SpringApplication.class)) {
// Act
EtlDataPipelineApplication.main(new String[]{});
@Test
void testMainMethod() {
try (var springApplicationMock = mockStatic(SpringApplication.class)) {
// Act
EtlDataPipelineApplication.main(new String[] {});

// Assert
springApplicationMock.verify(() -> SpringApplication.run(EtlDataPipelineApplication.class, new String[]{}));
}
}
@Test
void contextLoads() {
Assertions.assertTrue(true, "Unit Tests sanity check.");
// Assert
springApplicationMock.verify(
() -> SpringApplication.run(EtlDataPipelineApplication.class, new String[] {}));
}
}

@Test
void contextLoads() {
Assertions.assertTrue(true, "Unit Tests sanity check.");
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
package gov.cdc.etldatapipeline.controller;

import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import gov.cdc.etldatapipeline.service.DataPipelineStatusService;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
Expand All @@ -10,41 +14,35 @@
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;

import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

class DataPipelineControllerTest {

@Mock
private DataPipelineStatusService dataPipelineStatusService;
@Mock private DataPipelineStatusService dataPipelineStatusService;

@InjectMocks
private DataPipelineController controller;
@InjectMocks private DataPipelineController controller;

private AutoCloseable closeable;
private AutoCloseable closeable;

@BeforeEach
void setup() {
closeable = MockitoAnnotations.openMocks(this);
controller = new DataPipelineController(dataPipelineStatusService);
}
@BeforeEach
void setup() {
closeable = MockitoAnnotations.openMocks(this);
controller = new DataPipelineController(dataPipelineStatusService);
}

@AfterEach
void tearDown() throws Exception {
closeable.close();
}
@AfterEach
void tearDown() throws Exception {
closeable.close();
}

@Test
void testGetStatusHealth() {
final String responseBody = "Status OK";
when(dataPipelineStatusService.getHealthStatus()).thenReturn(ResponseEntity.ok(responseBody));
@Test
void testGetStatusHealth() {
final String responseBody = "Status OK";
when(dataPipelineStatusService.getHealthStatus()).thenReturn(ResponseEntity.ok(responseBody));

ResponseEntity<String> response = controller.getDataPipelineStatusHealth();
ResponseEntity<String> response = controller.getDataPipelineStatusHealth();

verify(dataPipelineStatusService).getHealthStatus();
assertNotNull(response);
assertEquals(HttpStatus.OK, response.getStatusCode());
assertEquals(responseBody, response.getBody());
}
}
verify(dataPipelineStatusService).getHealthStatus();
assertNotNull(response);
assertEquals(HttpStatus.OK, response.getStatusCode());
assertEquals(responseBody, response.getBody());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,9 @@

class DataPipelineStatusServiceTest {

@Test
void statusTest() {
DataPipelineStatusService statusService = new DataPipelineStatusService();
Assertions.assertEquals(HttpStatus.OK, statusService.getHealthStatus().getStatusCode());
}
@Test
void statusTest() {
DataPipelineStatusService statusService = new DataPipelineStatusService();
Assertions.assertEquals(HttpStatus.OK, statusService.getHealthStatus().getStatusCode());
}
}