A containerized Spring Boot service that monitors GitHub repositories for first-timer issues (status: first-timers-only) and logs/alerts when a match is found. Seen issues are persisted to an embedded file-backed H2 database to prevent duplicate alerts across restarts.
- GitHub REST API Polling: Periodically queries GitHub for open issues with target labels (ignoring pull requests).
- Persistent Storage: Uses Spring Data JPA and an embedded H2 database saved to disk/volumes to track seen issues.
- Dockerized: Multi-stage Docker build targeting lightweight Alpine images on OpenJDK / Java 21 (
aarch64&x86_64). - Automated Test Suite: Unit and integration tests powered by JUnit 5, MockWebServer, and Spring Data JPA test slices.
- Slack Alert Ready: Formatted notification pipeline ready to integrate with incoming Slack webhooks.
spring_boot_issue_tracker/
├── Dockerfile
├── docker-compose.yml
├── build.gradle
├── settings.gradle
├── src/
│ ├── main/
│ │ ├── java/
│ │ │ └── com/
│ │ │ └── tracker/
│ │ │ ├── TrackerApplication.java
│ │ │ ├── config/
│ │ │ │ └── TrackerProperties.java
│ │ │ ├── model/
│ │ │ │ ├── GitHubIssueDto.java
│ │ │ │ └── TrackedIssue.java
│ │ │ ├── repository/
│ │ │ │ └── TrackedIssueRepository.java
│ │ │ └── service/
│ │ │ └── IssueTrackerScheduler.java
│ │ └── resources/
│ │ └── application.properties
│ └── test/
│ └── java/
│ └── com/
│ └── tracker/
│ ├── repository/
│ │ └── TrackedIssueRepositoryTest.java
│ └── service/
│ └── IssueTrackerSchedulerTest.java
└── README.md
- Java: OpenJDK 21 (Amazon Corretto, Eclipse Temurin, or similar)
- Gradle: 8.6+ (or using
./gradlew) - Docker & Docker Compose: Modern Docker Desktop or CLI engine
Configuration values are mapped to application.properties and can be overridden via environment variables:
| Variable | Property Key | Default Value | Description |
|---|---|---|---|
DB_PATH |
spring.datasource.url |
./data/issues_db |
Path where H2 database writes persistent files (/data/issues_db inside Docker). |
TRACKER_REPO |
tracker.repo |
spring-projects/spring-boot |
Target repository in owner/repo format. |
TRACKER_LABEL |
tracker.label |
status: first-timers-only |
Target issue label to monitor. |
TRACKER_POLL_INTERVAL_MS |
tracker.poll-interval-ms |
300000 (5 min) |
Polling interval in milliseconds. |
TRACKER_GITHUB_TOKEN |
tracker.github-token |
(empty) | Optional Personal Access Token to raise rate limits (60/hr to 5,000/hr). |
The test suite validates data persistence and GitHub API parsing without making live network calls to GitHub:
TrackedIssueRepositoryTest:@DataJpaTestslice test verifying H2 entity persistence, lookup, and existence checks.IssueTrackerSchedulerTest: Uses OkHttpMockWebServerto mock the GitHub REST API, verifying proper URL encoding, query parameter construction, exclusion of pull requests, and deduplication of previously recorded issues.
Run tests using the Gradle wrapper:
./gradlew testAn HTML test report is generated at build/reports/tests/test/index.html.
-
Build and Run via Gradle:
./gradlew bootRun
-
Run in IntelliJ IDEA:
- Open the project directory in IntelliJ.
- Set the Project SDK to Java 21 (File > Project Structure > Project).
- Locate
com.tracker.TrackerApplicationand click the green Run (▶) button.
Database files will automatically be created in ./data/issues_db.mv.db in your local project directory.
-
Build and launch container in the background:
docker compose up -d --build
-
Inspect application logs:
docker compose logs -f
-
Stop the tracker:
docker compose down
Data persists between container rebuilds via the named volume tracker-data mounted at /data.
Because spring-projects/spring-boot rarely has open status: first-timers-only issues, you can verify alert triggering and database deduplication by temporarily modifying the target label:
- Update
TRACKER_LABELindocker-compose.yml(ortracker.labelinapplication.properties) to an active label:TRACKER_LABEL: "status: waiting-for-triage"
- Restart the app. You will see formatted logs for every detected issue:
======================================== [NEW FIRST-TIMERS ISSUE DETECTED] Issue: #40123 - Sample Issue Title URL: https://github.com/spring-projects/spring-boot/issues/40123 Created: 2026-11-01T22:30:00Z ======================================== - Restart it again with the same label. The application will recognize existing entries in the database and suppress duplicate alerts.
To forward new issue detections to Slack:
- Set up an Incoming Webhook in your Slack workspace.
- Add
SLACK_WEBHOOK_URLto your environment configuration indocker-compose.yml. - In
IssueTrackerScheduler.java, post the payload directly inside thenotify()method:
String webhookUrl = System.getenv("SLACK_WEBHOOK_URL");
if (webhookUrl != null && !webhookUrl.isBlank()) {
Map<String, String> payload = Map.of(
"text", String.format("New Spring Boot issue found: <%s|#%d %s>",
issue.getHtmlUrl(), issue.getNumber(), issue.getTitle())
);
webClient.post()
.uri(webhookUrl)
.bodyValue(payload)
.retrieve()
.toBodilessEntity()
.subscribe();
}This project is licensed under the ISC License.