Skip to content

Conversation

@csikb
Copy link
Contributor

@csikb csikb commented Nov 26, 2025

Summary by CodeRabbit

  • Chores

    • Centralized and extended publishing configuration to standardize artifact naming and enable Maven/GitHub package publishing across modules.
    • Updated module composition and API wiring to reflect a reorganized project layout.
  • New Features

    • Added an SBOM generation convention (CycloneDX) and applied it across relevant modules for software bill-of-materials output.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 26, 2025

Warning

Rate limit exceeded

@csikb has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 21 minutes and 39 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between e99df97 and 126f1bb.

📒 Files selected for processing (1)
  • server/file-api/README.md (1 hunks)

Walkthrough

Adds two new convention plugins (publishing and SBOM) implemented in buildSrc, introduces a java-platform build script, updates module includes and module dependencies, adjusts Java library jar naming, and applies the new conventions across client and server modules.

Changes

Cohort / File(s) Summary
Root platform build script
build.gradle.kts
Adds group = "hu.bsstudio.web", applies java-platform, maven-publish, and hu.bsstudio.gradle.sbom-convention; defines API constraints on platform dependencies and a bssWebAdminPlatform MavenPublication.
buildSrc plugin registrations
buildSrc/build.gradle.kts
Registers new convention plugins hu.bsstudio.gradle.publishing-convention and hu.bsstudio.gradle.sbom-convention; reorders/extends plugin dependency list (adds CycloneDX and related entries).
Publishing plugin implementation
buildSrc/src/main/kotlin/hu/bsstudio/gradle/PublishingConventionPlugin.kt
New PublishingConventionPlugin : Plugin<Project> that applies maven-publish, configures a GitHub Packages Maven repository (credentials from GPR_USERNAME/GPR_PASSWORD), and registers a MavenPublication publishing the java component with groupId/artifactId derived from root and project names; warns if root group is blank.
SBOM plugin implementation
buildSrc/src/main/kotlin/hu/bsstudio/gradle/SbomConventionPlugin.kt
New SbomConventionPlugin : Plugin<Project> that applies the CycloneDX plugin via the project's pluginManager.
Java library convention tweak
buildSrc/src/main/kotlin/hu/bsstudio/gradle/JavaLibraryConventionPlugin.kt
Sets jar task archiveBaseName to "<rootProject.name>-<project.name>".
Module plugin applications
client/build.gradle.kts, server/common/build.gradle.kts, server/model/build.gradle.kts, server/operation/build.gradle.kts
Apply hu.bsstudio.gradle.publishing-convention and hu.bsstudio.gradle.sbom-convention in module plugin blocks.
Module include & dependency updates
settings.gradle.kts, server/service/build.gradle.kts
Replaced included module server:client with server:file-api; updated dependency api(project(":server:client"))api(project(":server:file-api")).

Sequence Diagram

sequenceDiagram
    participant Gradle as Gradle Build
    participant PluginReg as PublishingConventionPlugin
    participant MavenPub as Maven Publish Plugin
    participant Repo as GitHub Package Registry

    Gradle->>PluginReg: apply(project)
    activate PluginReg
    PluginReg->>MavenPub: apply "maven-publish"
    PluginReg->>MavenPub: configure PublishingExtension
    PluginReg->>Repo: add repository "GitHubPackageRegistry" (URL)
    Repo-->>PluginReg: accept credentials (GPR_USERNAME/GPR_PASSWORD)
    PluginReg->>MavenPub: register MavenPublication (from components["java"])
    PluginReg->>MavenPub: set groupId / set artifactId
    alt root project group is blank
        PluginReg->>Gradle: log warning about missing group
    end
    deactivate PluginReg
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • Inspect credential handling and repository URL in PublishingConventionPlugin.kt.
  • Verify publication component name and artifactId formatting alongside JavaLibraryConventionPlugin archiveBaseName.
  • Confirm buildSrc plugin registrations and CycloneDX integration are correct.
  • Ensure module include/dependency swap (server:client → server:file-api) is consistent across build files.

Possibly related PRs

  • Binary plugins 2 #338 — Related updates to buildSrc and module build scripts introducing hu.bsstudio.* convention plugins.
  • Refactor buildSrc #396 — Related changes to buildSrc and Gradle convention plugin registrations.
  • feat: add Detekt #447 — Related modifications to buildSrc plugin registrations and module plugin applications.

Pre-merge checks and finishing touches

❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
Title check ❓ Inconclusive The title 'Publish' is too vague and generic; it doesn't clearly convey the specific changes being made. Consider using a more descriptive title that specifies what is being published (e.g., 'Add Maven publishing configuration with convention plugins' or 'Set up publishing conventions and SBOM generation').
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 45d0615 and 8f2d851.

⛔ Files ignored due to path filters (2)
  • .github/workflows/gradle-publish.yml is excluded by !**/*.yml
  • .github/workflows/gradle.yml is excluded by !**/*.yml
📒 Files selected for processing (8)
  • build.gradle.kts (1 hunks)
  • buildSrc/build.gradle.kts (1 hunks)
  • buildSrc/src/main/kotlin/hu/bsstudio/gradle/JavaLibraryConventionPlugin.kt (2 hunks)
  • buildSrc/src/main/kotlin/hu/bsstudio/gradle/PublishingConventionPlugin.kt (1 hunks)
  • client/build.gradle.kts (1 hunks)
  • server/common/build.gradle.kts (1 hunks)
  • server/model/build.gradle.kts (1 hunks)
  • server/operation/build.gradle.kts (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Build and publish
  • GitHub Check: Integration test
🔇 Additional comments (6)
client/build.gradle.kts (1)

1-8: Publishing plugin usage on client looks consistent

Applying hu.bsstudio.gradle.publishing-convention here is consistent with other Java library modules and will publish the client artifact with the shared convention. No issues from a Gradle wiring standpoint.

server/operation/build.gradle.kts (1)

1-10: Operation module publishing hook is wired correctly

Adding hu.bsstudio.gradle.publishing-convention here matches the other Java library modules and should publish server:operation without extra configuration.

build.gradle.kts (1)

1-1: Confirm that hu.bsstudio.web is the intended groupId for all modules

This root group will drive the groupId of every published artifact via the publishing convention. Please double‑check it matches any existing coordinates/consumer expectations before publishing.

server/model/build.gradle.kts (1)

1-16: Model module is correctly opted into publishing

Including hu.bsstudio.gradle.publishing-convention here is aligned with the other server modules and should publish the model JAR with the standardized conventions.

server/common/build.gradle.kts (1)

1-8: Common module publishing is wired as expected

Applying hu.bsstudio.gradle.publishing-convention here matches the pattern in other Java library modules; nothing problematic from a Gradle perspective.

buildSrc/build.gradle.kts (1)

51-54: Publishing convention plugin registration looks correct

The plugin id and implementationClass align with the new PublishingConventionPlugin implementation and its usage in subprojects. No issues here.

Comment on lines +26 to +28
project.tasks.named<Jar>("jar") {
this.archiveBaseName.set("${project.rootProject.name}-${project.name}")
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

Avoid duplicating artifact name pattern between convention plugins

This archiveBaseName pattern is duplicated in PublishingConventionPlugin (for artifactId). To reduce drift risk, consider centralizing the "${project.rootProject.name}-${project.name}" convention in a shared helper or constant used by both plugins.

🤖 Prompt for AI Agents
In buildSrc/src/main/kotlin/hu/bsstudio/gradle/JavaLibraryConventionPlugin.kt
around lines 26 to 28, the archiveBaseName is set using the literal pattern
"${project.rootProject.name}-${project.name}" which is duplicated in
PublishingConventionPlugin; extract this pattern into a shared constant or
helper function (e.g., in a common util object in buildSrc) and replace the
literal in both plugins to reference that single constant/helper so both
jar.archiveBaseName and publishing.artifactId use the same centralized value.

Comment on lines +18 to +36
project.extensions.configure(PublishingExtension::class) {
repositories {
maven {
name = "GitHubPackageRegistry"
url = project.uri("https://maven.pkg.github.com/BSStudio/bss-web-admin-backend")
credentials {
username = project.providers.environmentVariable("GPR_USERNAME").orNull
password = project.providers.environmentVariable("GPR_PASSWORD").orNull
}
}
}
publications {
register<MavenPublication>(project.name) {
from(project.components.getByName("java"))
this.groupId = project.rootProject.group.toString()
this.artifactId = "${project.rootProject.name}-${project.name}"
}
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

Make publishing configuration more robust to plugin order and reuse

The core wiring is sound, but a couple of improvements would make this safer and easier to maintain:

  • The publishing logic assumes a java component is already present and the plugin is only ever applied to Java library projects. To decouple from plugin order and avoid accidental misuse, consider guarding this with plugins.withId("java-library") { ... } / withType<JavaPlugin> before accessing components["java"].
  • The "${project.rootProject.name}-${project.name}" artifactId pattern duplicates the archiveBaseName configuration in JavaLibraryConventionPlugin. Centralizing this naming rule (shared helper/extension) would avoid divergence.
  • If GPR_USERNAME/GPR_PASSWORD are unset, the failure will appear later as an auth error. You might want to validate these providers and log a clearer warning (or fail fast) when they are missing, to make local/CI misconfiguration easier to diagnose.
🤖 Prompt for AI Agents
In buildSrc/src/main/kotlin/hu/bsstudio/gradle/PublishingConventionPlugin.kt
around lines 18 to 36, the publishing block assumes a java component, duplicates
artifact naming, and silently continues when GPR credentials are missing; fix by
wrapping the publication setup in a plugins.withId("java-library") or
project.plugins.withType<JavaPlugin> guard so components["java"] is only
accessed when present, derive artifactId from the project's archiveBaseName (or
expose a shared helper/extension used by JavaLibraryConventionPlugin) instead of
constructing "${project.rootProject.name}-${project.name}" inline, and validate
the GPR_USERNAME/GPR_PASSWORD providers up-front - log a clear warning or fail
fast if they are null/empty to surface misconfiguration early.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

♻️ Duplicate comments (2)
buildSrc/src/main/kotlin/hu/bsstudio/gradle/PublishingConventionPlugin.kt (2)

16-34: Guard component access and validate credentials up front.

The publishing configuration still has the robustness concerns flagged in the previous review:

  1. Plugin order dependency: Accessing components["java"] without a guard assumes the java-library plugin is already applied. Wrap the publication setup in plugins.withId("java-library") { ... } to make this safe regardless of plugin application order.

  2. Duplicated artifactId pattern: The "${project.rootProject.name}-${project.name}" pattern duplicates the naming logic in JavaLibraryConventionPlugin. Extract this into a shared helper to prevent divergence.

  3. Silent credential failure: If GPR_USERNAME or GPR_PASSWORD are unset, the build will fail later with an unclear auth error. Validate these providers during plugin application and fail fast with a clear message if missing.

Apply this diff to add plugin guard and credential validation:

 project.extensions.configure(PublishingExtension::class) {
     repositories {
         maven {
             name = "GitHubPackageRegistry"
             url = project.uri("https://maven.pkg.github.com/BSStudio/bss-web-admin-backend")
             credentials {
+                val gprUsername = project.providers.environmentVariable("GPR_USERNAME").orNull
+                val gprPassword = project.providers.environmentVariable("GPR_PASSWORD").orNull
+                
+                if (gprUsername.isNullOrBlank() || gprPassword.isNullOrBlank()) {
+                    project.logger.warn("WARNING: GPR_USERNAME or GPR_PASSWORD not set. Publishing to GitHub Packages will fail.")
+                }
-                username = project.providers.environmentVariable("GPR_USERNAME").orNull
-                password = project.providers.environmentVariable("GPR_PASSWORD").orNull
+                username = gprUsername
+                password = gprPassword
             }
         }
     }
-    publications {
-        register<MavenPublication>(project.name) {
-            from(project.components.getByName("java"))
-            this.groupId = project.rootProject.group.toString()
-            this.artifactId = "${project.rootProject.name}-${project.name}"
+    
+    project.plugins.withId("java-library") {
+        publications {
+            register<MavenPublication>(project.name) {
+                from(project.components.getByName("java"))
+                this.groupId = project.rootProject.group.toString()
+                this.artifactId = "${project.rootProject.name}-${project.name}"
+            }
         }
     }
 }

36-41: Fail fast when root group is missing.

Logging a warning allows the build to continue with an invalid groupId, which will fail at publish time with a less clear error. As noted in the previous review, this should be a build failure during plugin application.

Apply this diff to fail fast:

-        if (project.rootProject.group
-                .toString()
-                .isBlank()
-        ) {
-            project.logger.warn("WARNING: The root project group is not set. Please set it to ensure proper publishing configuration.")
-        }
+        if (project.rootProject.group.toString().isBlank()) {
+            throw org.gradle.api.GradleException(
+                "Root project group is not set. Please set 'group' in the root build.gradle.kts to ensure proper publishing configuration."
+            )
+        }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e033d0f and ad00641.

⛔ Files ignored due to path filters (2)
  • .github/workflows/gradle-publish.yml is excluded by !**/*.yml
  • gradle/libs.versions.toml is excluded by !**/*.toml
📒 Files selected for processing (8)
  • build.gradle.kts (1 hunks)
  • buildSrc/build.gradle.kts (3 hunks)
  • buildSrc/src/main/kotlin/hu/bsstudio/gradle/PublishingConventionPlugin.kt (1 hunks)
  • buildSrc/src/main/kotlin/hu/bsstudio/gradle/SbomConventionPlugin.kt (1 hunks)
  • client/build.gradle.kts (1 hunks)
  • server/common/build.gradle.kts (1 hunks)
  • server/model/build.gradle.kts (1 hunks)
  • server/operation/build.gradle.kts (1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2024-10-08T16:19:58.743Z
Learnt from: csikb
Repo: BSStudio/bss-web-admin-backend PR: 305
File: buildSrc/src/main/kotlin/spotless-conventions.gradle.kts:11-14
Timestamp: 2024-10-08T16:19:58.743Z
Learning: The `cleanthat()` configuration option is a valid Spotless plugin for Gradle configuration, as documented in the Spotless plugin's GitHub README.

Applied to files:

  • buildSrc/build.gradle.kts
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: Build and publish
  • GitHub Check: Gradle
  • GitHub Check: Build
  • GitHub Check: Integration test
🔇 Additional comments (10)
server/operation/build.gradle.kts (1)

9-10: LGTM! Convention plugins applied correctly.

The addition of publishing-convention and sbom-convention enables Maven publishing and SBOM generation for this module. The plugin order (java-library-convention applied first) is appropriate.

server/common/build.gradle.kts (1)

7-8: LGTM! Convention plugins applied correctly.

The publishing and SBOM conventions are properly applied to enable artifact publishing for this module.

server/model/build.gradle.kts (1)

9-12: LGTM! Convention plugins applied correctly.

The publishing and SBOM conventions are properly added to enable artifact publishing for the model module.

client/build.gradle.kts (1)

7-8: LGTM! Convention plugins applied correctly.

The client module now has publishing and SBOM generation enabled through the convention plugins.

buildSrc/src/main/kotlin/hu/bsstudio/gradle/SbomConventionPlugin.kt (1)

8-12: LGTM! Simple delegation pattern is appropriate.

The plugin cleanly delegates to CyclonedxPlugin to provide SBOM generation. If you need to customize CycloneDX behavior (output format, component analysis depth, etc.) in the future, you can add configuration here.

buildSrc/build.gradle.kts (2)

1-1: Verify the need for buildSrc version.

Setting a version on the buildSrc module is unusual since it's not typically published as a separate artifact. If this is for internal tracking or documentation, it's fine. Otherwise, this line may be unnecessary.


54-61: LGTM! Plugin registration is correct.

The two new convention plugins are properly registered with matching IDs and implementation classes. The plugin IDs follow the existing naming convention and are used correctly in the module build scripts.

build.gradle.kts (3)

1-1: LGTM! Root group properly configured.

Setting the root project group is essential for the publishing conventions to work correctly. The group "hu.bsstudio.web" will be inherited by all subprojects.


3-7: LGTM! Plugin configuration appropriate for platform module.

The root project correctly uses java-platform for BOM functionality and applies maven-publish directly (rather than publishing-convention) since it publishes from the javaPlatform component instead of the java component.


9-16: LGTM! Platform constraints correctly defined.

The dependency constraints enable consumers to import the platform and get aligned versions of all library modules. This is the correct pattern for a Gradle platform module.

Comment on lines +18 to +26
publishing {
publications {
create<MavenPublication>("bssWebAdminPlatform") {
from(components["javaPlatform"])
this.groupId = project.rootProject.group.toString()
this.artifactId = "${project.rootProject.name}-${project.name}"
}
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

Consider using dynamic publication name and centralizing artifactId pattern.

Two observations:

  1. Hardcoded publication name: The publication is named "bssWebAdminPlatform" but could use project.name for consistency. If the root project is renamed, this would need manual updating.

  2. ArtifactId pattern duplication: The "${project.rootProject.name}-${project.name}" pattern now appears in three places: JavaLibraryConventionPlugin, PublishingConventionPlugin, and here. Consider extracting this into a shared helper or extension property to maintain consistency.

Apply this diff for the publication name:

 publishing {
     publications {
-        create<MavenPublication>("bssWebAdminPlatform") {
+        create<MavenPublication>(project.name) {
             from(components["javaPlatform"])
             this.groupId = project.rootProject.group.toString()
             this.artifactId = "${project.rootProject.name}-${project.name}"
         }
     }
 }

For the artifactId pattern, consider creating a shared extension in buildSrc that all three locations can use.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
publishing {
publications {
create<MavenPublication>("bssWebAdminPlatform") {
from(components["javaPlatform"])
this.groupId = project.rootProject.group.toString()
this.artifactId = "${project.rootProject.name}-${project.name}"
}
}
}
publishing {
publications {
create<MavenPublication>(project.name) {
from(components["javaPlatform"])
this.groupId = project.rootProject.group.toString()
this.artifactId = "${project.rootProject.name}-${project.name}"
}
}
}
🤖 Prompt for AI Agents
In build.gradle.kts around lines 18–26, the publication uses a hardcoded name
("bssWebAdminPlatform") and duplicates the artifactId pattern
("${project.rootProject.name}-${project.name}") used in multiple places; change
the publication name to use project.name (e.g.,
create<MavenPublication>(project.name)) and replace the inline artifactId
expression with a shared property; add a small extension/helper in buildSrc
(e.g., project.extensions.create or a Kotlin object) that exposes the artifactId
pattern (computed from rootProject.name and project.name) and update
JavaLibraryConventionPlugin, PublishingConventionPlugin and this
build.gradle.kts to read the artifactId from that centralized helper so the
pattern is maintained in one place.

@sonarqubecloud
Copy link

sonarqubecloud bot commented Nov 30, 2025

Quality Gate Passed Quality Gate passed

Issues
0 New issues
0 Accepted issues

Measures
0 Security Hotspots
No data about Coverage
0.0% Duplication on New Code

See analysis details on SonarQube Cloud

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants