[ISSUE-86] Multi-module Gradle restructure — Refactor CFTunnels into :common, :cftunnels-service, :portainer-automation #125

Merged
hitanshu merged 6 commits from Dave/CFTunnels:ISSUE-86 into test 2026-07-05 10:23:25 +00:00
Member

Summary

Restructured CFTunnels from a single-module Gradle project into a multi-module project with 3 modules:

  • :common — shared library with RestTemplateConfig extracted from the service
  • :cftunnels-service — the existing Cloudflare Tunnel service (moved and package-renamed)
  • :portainer-automation — scaffolded placeholder Spring Boot app (port 8081)

Changes Made

  1. Root scaffolding: settings.gradle, root build.gradle (coordinating subprojects), gradle.properties
  2. Source migration: All existing source moved from src/cftunnels-service/src/ with package rename com.hithomelabs.CFTunnelscom.hithomelabs.cftunnels
  3. :common module: Extracted RestTemplateConfig to com.hithomelabs.common.config with updated imports in service classes
  4. :portainer-automation scaffold: Minimal Spring Boot application on port 8081
  5. CI workflow: Updated test_image_build_push.ymlbootBuildImage:cftunnels-service:bootBuildImage
  6. Dockerfile: New multi-stage cftunnels-service/Dockerfile that builds the whole project and produces the service JAR

Files Changed

  • Added: settings.gradle, gradle.properties
  • Added: cftunnels-service/ (build.gradle, Dockerfile, all moved/renamed sources)
  • Added: common/ (build.gradle, RestTemplateConfig)
  • Added: portainer-automation/ (build.gradle, Application class, properties)
  • Modified: root build.gradle, .gitea/workflows/test_image_build_push.yml
  • Removed: root Dockerfile, old src/ directory

Issues

Testing

All 31 unit tests pass:

  • CfTunnelsApplicationTests (1) ✓

  • TunnelControllerTest (19) ✓

  • RequestRepositoryTest (2) ✓

  • CloudflareAPIServiceTest (9) ✓

  • ./gradlew :cftunnels-service:build — compiles and passes all unit tests

  • ./gradlew :common:build — compiles

  • ./gradlew :portainer-automation:build — compiles

  • ./gradlew build — everything builds

  • test_build.yml and integration_test.yaml were NOT modified

  • Only test_image_build_push.yml has a 1-line change (bootBuildImage:cftunnels-service:bootBuildImage)

## Summary Restructured CFTunnels from a single-module Gradle project into a multi-module project with 3 modules: - **`:common`** — shared library with `RestTemplateConfig` extracted from the service - **`:cftunnels-service`** — the existing Cloudflare Tunnel service (moved and package-renamed) - **`:portainer-automation`** — scaffolded placeholder Spring Boot app (port 8081) ### Changes Made 1. **Root scaffolding**: `settings.gradle`, root `build.gradle` (coordinating subprojects), `gradle.properties` 2. **Source migration**: All existing source moved from `src/` → `cftunnels-service/src/` with package rename `com.hithomelabs.CFTunnels` → `com.hithomelabs.cftunnels` 3. **`:common` module**: Extracted `RestTemplateConfig` to `com.hithomelabs.common.config` with updated imports in service classes 4. **`:portainer-automation` scaffold**: Minimal Spring Boot application on port 8081 5. **CI workflow**: Updated `test_image_build_push.yml` — `bootBuildImage` → `:cftunnels-service:bootBuildImage` 6. **Dockerfile**: New multi-stage `cftunnels-service/Dockerfile` that builds the whole project and produces the service JAR ### Files Changed - Added: `settings.gradle`, `gradle.properties` - Added: `cftunnels-service/` (build.gradle, Dockerfile, all moved/renamed sources) - Added: `common/` (build.gradle, RestTemplateConfig) - Added: `portainer-automation/` (build.gradle, Application class, properties) - Modified: root `build.gradle`, `.gitea/workflows/test_image_build_push.yml` - Removed: root `Dockerfile`, old `src/` directory ## Issues - Hithomelabs/HomeLabDocker#86 ## Testing All 31 unit tests pass: - CfTunnelsApplicationTests (1) ✓ - TunnelControllerTest (19) ✓ - RequestRepositoryTest (2) ✓ - CloudflareAPIServiceTest (9) ✓ - [x] `./gradlew :cftunnels-service:build` — compiles and passes all unit tests - [x] `./gradlew :common:build` — compiles - [x] `./gradlew :portainer-automation:build` — compiles - [x] `./gradlew build` — everything builds - [x] `test_build.yml` and `integration_test.yaml` were NOT modified - [x] Only `test_image_build_push.yml` has a 1-line change (`bootBuildImage` → `:cftunnels-service:bootBuildImage`)
Dave added 6 commits 2026-07-05 10:08:22 +00:00
Linus approved these changes 2026-07-05 10:20:29 +00:00
Linus left a comment
Member

PR Review: [ISSUE-86] Multi-module Gradle restructure

Overview

Restructures CFTunnels from a single-module to a 3-module Gradle project (:common, :cftunnels-service, :portainer-automation) with package rename from com.hithomelabs.CFTunnelscom.hithomelabs.cftunnels. 56 files changed (+266/-201).

Code Quality

  • Root build.gradle: Properly uses apply false on plugins in root, common config via subprojects {}, shared BOM management — clean multi-module setup.
  • settings.gradle: Correctly includes all 3 subprojects.
  • common/build.gradle: Minimal, correct dependencies for a library module (spring-context, spring-web, jackson-databind, httpclient5). No boot plugin — correct.
  • cftunnels-service/build.gradle: Applies Spring Boot plugin, depends on :common, preserves all original dependencies and test configuration (ci profile, integrationTestOnly task, etc.).
  • portainer-automation/build.gradle: Clean scaffold — Spring Boot on 8081 with validation support.

Package Migration

  • All source files correctly renamed from com.hithomelabs.CFTunnelscom.hithomelabs.cftunnels
  • CfTunnelsApplication uses @SpringBootApplication(scanBasePackages = "com.hithomelabs") — this correctly picks up beans from the :common module's com.hithomelabs.common.config package
  • Test files properly migrated with matching package/import updates

Extract to :common

  • RestTemplateConfig with Jackson customization (WRAP_ROOT_VALUE, NON_NULL) extracted to com.hithomelabs.common.config
  • All service classes reference RestTemplate via injection — clean separation

Dockerfile

  • Old single-stage Dockerfile deleted, replaced with multi-stage cftunnels-service/Dockerfile
  • Stage 1: Builds full project, runs :cftunnels-service:bootJar
  • Stage 2: Minimal runtime with openjdk:17-jdk-slim — best practice

CI Workflow Changes

  • test_build.yml: Unchanged (verified same SHA ae070cde)
  • integration_test.yaml: Unchanged (verified same SHA 4c4ee37f)
  • test_image_build_push.yml: Only 1-line changebootBuildImage:cftunnels-service:bootBuildImage

Observations & Minor Suggestions

  1. portainer-automation component scanning: PortainerAutomationApplication does not set scanBasePackages. If it later needs beans from :common, it would need scanBasePackages = "com.hithomelabs" since its package com.hithomelabs.portainer is not a parent of com.hithomelabs.common.config. Not a blocker for the scaffold.
  2. OAuth2 client version: Old build.gradle pinned spring-boot-starter-oauth2-client at 3.5.5 (higher than Boot BOM 3.4.5). The new setup correctly lets the BOM manage this. Minor improvement, not a regression.
  3. httpclient5 in :common: The dependency is declared but not directly used in RestTemplateConfig. It enables Apache HttpClient 5 as the underlying transport for RestTemplate. Consider adding a comment noting why it's included.

Approval Status

APPROVED — Ready for human merge.

All constraints verified:

  • All 31 existing tests pass with new structure
  • test_build.yml and integration_test.yaml untouched
  • Only test_image_build_push.yml has the required 1-line change
  • Every source file properly migrated with correct package rename
  • Build compiles cleanly for all subprojects

This is a well-executed multi-module restructuring. Good work.

## PR Review: [ISSUE-86] Multi-module Gradle restructure ### Overview Restructures CFTunnels from a single-module to a 3-module Gradle project (`:common`, `:cftunnels-service`, `:portainer-automation`) with package rename from `com.hithomelabs.CFTunnels` → `com.hithomelabs.cftunnels`. 56 files changed (+266/-201). ### Code Quality ✅ - **Root `build.gradle`**: Properly uses `apply false` on plugins in root, common config via `subprojects {}`, shared BOM management — clean multi-module setup. - **`settings.gradle`**: Correctly includes all 3 subprojects. - **`common/build.gradle`**: Minimal, correct dependencies for a library module (spring-context, spring-web, jackson-databind, httpclient5). No boot plugin — correct. - **`cftunnels-service/build.gradle`**: Applies Spring Boot plugin, depends on `:common`, preserves all original dependencies and test configuration (`ci` profile, `integrationTestOnly` task, etc.). - **`portainer-automation/build.gradle`**: Clean scaffold — Spring Boot on 8081 with validation support. ### Package Migration ✅ - All source files correctly renamed from `com.hithomelabs.CFTunnels` → `com.hithomelabs.cftunnels` - `CfTunnelsApplication` uses `@SpringBootApplication(scanBasePackages = "com.hithomelabs")` — this correctly picks up beans from the `:common` module's `com.hithomelabs.common.config` package - Test files properly migrated with matching package/import updates ### Extract to `:common` ✅ - `RestTemplateConfig` with Jackson customization (WRAP_ROOT_VALUE, NON_NULL) extracted to `com.hithomelabs.common.config` - All service classes reference `RestTemplate` via injection — clean separation ### Dockerfile ✅ - Old single-stage `Dockerfile` deleted, replaced with multi-stage `cftunnels-service/Dockerfile` - Stage 1: Builds full project, runs `:cftunnels-service:bootJar` - Stage 2: Minimal runtime with `openjdk:17-jdk-slim` — best practice ### CI Workflow Changes ✅ - `test_build.yml`: **Unchanged** (verified same SHA ae070cde) - `integration_test.yaml`: **Unchanged** (verified same SHA 4c4ee37f) - `test_image_build_push.yml`: Only **1-line change** — `bootBuildImage` → `:cftunnels-service:bootBuildImage` ✓ ### Observations & Minor Suggestions 1. **`portainer-automation` component scanning**: `PortainerAutomationApplication` does not set `scanBasePackages`. If it later needs beans from `:common`, it would need `scanBasePackages = "com.hithomelabs"` since its package `com.hithomelabs.portainer` is not a parent of `com.hithomelabs.common.config`. Not a blocker for the scaffold. 2. **OAuth2 client version**: Old `build.gradle` pinned `spring-boot-starter-oauth2-client` at `3.5.5` (higher than Boot BOM `3.4.5`). The new setup correctly lets the BOM manage this. Minor improvement, not a regression. 3. **`httpclient5` in `:common`**: The dependency is declared but not directly used in `RestTemplateConfig`. It enables Apache HttpClient 5 as the underlying transport for `RestTemplate`. Consider adding a comment noting why it's included. ### Approval Status **APPROVED** ✅ — Ready for human merge. All constraints verified: - All 31 existing tests pass with new structure - `test_build.yml` and `integration_test.yaml` untouched - Only `test_image_build_push.yml` has the required 1-line change - Every source file properly migrated with correct package rename - Build compiles cleanly for all subprojects This is a well-executed multi-module restructuring. Good work.
Linus added the
complexity:medium
effort:l
labels 2026-07-05 10:20:57 +00:00
Member

Lead Agent Review Complete

Decision: APPROVED — Ready for human merge.

Key Review Points

  • Clean multi-module Gradle structure (:common, :cftunnels-service, :portainer-automation)
  • All 31 existing tests preserved and passing
  • Package rename CFTunnelscftunnels applied consistently across all files
  • @SpringBootApplication(scanBasePackages = "com.hithomelabs") ensures cross-module bean discovery
  • test_build.yml and integration_test.yaml untouched (verified by SHA)
  • Only test_image_build_push.yml has the required 1-line change
  • Multi-stage Dockerfile replaces old single-stage
  • RestTemplateConfig properly extracted to :common

Labels Added

  • effort:l (2-4 weeks — major restructure effort)
  • complexity:medium (well-defined but many coordinated changes)

Minor Suggestion

  • PortainerAutomationApplication may need scanBasePackages = "com.hithomelabs" when it starts consuming beans from :common (not needed for scaffold)

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Reviewed by Linus (Lead Engineer Agent)

## Lead Agent Review Complete ✅ **Decision: APPROVED** — Ready for human merge. ### Key Review Points - ✅ Clean multi-module Gradle structure (`:common`, `:cftunnels-service`, `:portainer-automation`) - ✅ All 31 existing tests preserved and passing - ✅ Package rename `CFTunnels` → `cftunnels` applied consistently across all files - ✅ `@SpringBootApplication(scanBasePackages = "com.hithomelabs")` ensures cross-module bean discovery - ✅ `test_build.yml` and `integration_test.yaml` untouched (verified by SHA) - ✅ Only `test_image_build_push.yml` has the required 1-line change - ✅ Multi-stage Dockerfile replaces old single-stage - ✅ `RestTemplateConfig` properly extracted to `:common` ### Labels Added - **effort:l** (2-4 weeks — major restructure effort) - **complexity:medium** (well-defined but many coordinated changes) ### Minor Suggestion - `PortainerAutomationApplication` may need `scanBasePackages = "com.hithomelabs"` when it starts consuming beans from `:common` (not needed for scaffold) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Reviewed by **Linus** (Lead Engineer Agent)
hitanshu requested review from hitanshu 2026-07-05 10:23:04 +00:00
hitanshu approved these changes 2026-07-05 10:23:16 +00:00
hitanshu left a comment
Owner

looks good to me

looks good to me
hitanshu merged commit 4a3e2777db into test 2026-07-05 10:23:25 +00:00
Sign in to join this conversation.
No reviewers
No Milestone
No project
No Assignees
3 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: Hithomelabs/CFTunnels#125
No description provided.