Skip to content

refactor: extract sigstore-common module - #1288

Draft
aaronlew02 wants to merge 1 commit into
tuf-gson-supplierfrom
extract-sigstore-common
Draft

aaronlew02 wants to merge 1 commit into
tuf-gson-supplierfrom
extract-sigstore-common

Conversation

@aaronlew02

Copy link
Copy Markdown
Collaborator

Summary

This change extracts common utilities (including HTTP and JSON utilities) from sigstore-java into a new :sigstore-common module.

@aaronlew02
aaronlew02 changed the base branch from main to tuf-gson-supplier September 9, 2026 17:32
@aaronlew02
aaronlew02 force-pushed the extract-sigstore-common branch from c0f9d4c to 1dbe606 Compare September 9, 2026 17:43
@loosebazooka

Copy link
Copy Markdown
Member

Given that we just introduced module information, can we make sure this is module safe? packages should not be repeated across modules, etc.

@aaronlew02
aaronlew02 added this pull request to stack #1290 September 9, 2026 18:37
@aaronlew02
aaronlew02 force-pushed the extract-sigstore-common branch from 1dbe606 to 93b56e7 Compare September 9, 2026 18:58
@aaronlew02

Copy link
Copy Markdown
Collaborator Author

@loosebazooka I've moved all packages in :sigstore-common under a new dev.sigstore.common.* package hierarchy for module safety.

@loosebazooka

Copy link
Copy Markdown
Member

So once we arrange things, we need to make sure sigstore-common is built and published locally when needed and also is still part of the public release.

  • Add nmcpAggregation(project(":sigstore-common")) to build.gradle.kts
  • Our ci tries to install sigstore-java locally and it will requires teh sub moduels now, but I think that line can be replaced with :nmcpPublishAggregationToMavenLocal (or whatever) and have the nmcp plugin just handle this stuff.
  • Add a test project with module-info.java or a dedicated Gradle validation task in CI to enforce module boundaries and prevent split packages.

Some minor inconsistencies discovered by gemini:

  • Remove the unused api("io.github.erdtman:java-json-canonicalization:1.1") dependency from sigstore-common's -- it's json canonicalization for tuf only.
  • Downgrade Guava to compileOnly (or remove it) in sigstore-common it is only referenced for a single @VisibleForTesting annotation. (This one is a little iffy)

@aaronlew02
aaronlew02 force-pushed the extract-sigstore-common branch from c7e45bf to 8192495 Compare September 15, 2026 18:42
@aaronlew02

Copy link
Copy Markdown
Collaborator Author
  • Added nmcpAggregation(project(":sigstore-common")) to build.gradle.kts.
  • Replaced sigstore-java:publishToMavenLocal with nmcpPublishAggregationToMavenLocal in ci.yaml
  • Added test project module-test with module-info.java in sandbox
  • Removed unused api("io.github.erdtman:java-json-canonicalization:1.1") dependency from :sigstore-common
  • Removed Guava dependency and the single @VisibleForTesting annotation from :sigstore-common

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

It looks like GrpcChannels could be package private to the fulcio client now.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Correct. Made GrpcChannels and its methods package-private.

Comment thread sigstore-common/build.gradle.kts Outdated
forbiddenApis {
signaturesFiles = files("$rootDir/config/forbiddenApis.txt")
suppressAnnotations = setOf("dev.sigstore.common.forbidden.SuppressForbidden")
ignoreSignaturesOfMissingClasses = true

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Lets remove this actually. Looking at it again, I feel like it leaves us open to making mistakes. We can just have separate signature files for common.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Removed and added separate signature files for :sigstore-common.

val sigstoreVersion = "2.4.0-SNAPSHOT"

dependencies {
implementation("dev.sigstore:sigstore-common:$sigstoreVersion")

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

can we check that this actually fails? like if we add a conflicting package somewhere and then checking for failure?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

I had Gemini run two tests, both of which I verified:

Test 1:

  • Two minimal JARs were compiled and packaged in a temporary directory:
    • mod1.jar with Automatic-Module-Name: mod.one containing a class in package pkg.
    • mod2.jar with Automatic-Module-Name: mod.two containing a class in package pkg.
  • Created a modular consumer project with a module-info.java requiring both:
    module app {
      requires mod.one;
      requires mod.two;
    }
  • Running javac -p mod1.jar:mod2.jar module-info.java Main.java failed with:
    error: the unnamed module reads package pkg from both mod.two and mod.one
    error: module mod.two reads package pkg from both mod.one and mod.two
    error: module mod.one reads package pkg from both mod.two and mod.one
    error: module app reads package pkg from both mod.one and mod.two
    

Test 2:

  • A temporary file was created at sandbox/module-test/src/main/java/dev/sigstore/Conflict.java containing:
    package dev.sigstore;
    public class Conflict {}
  • Because sandbox/module-test/src/main/java/module-info.java specifies requires dev.sigstore;, defining a class in package dev.sigstore causes a package collision.
  • Running ./gradlew :module-test:compileJava in sandbox/ failed as expected:
    error: package exists in another module: dev.sigstore
    package dev.sigstore;
    ^
    

@@ -50,7 +49,6 @@ public static UnsuccessfulResponseHandler newUnsuccessfulResponseHandler() {
return new UnsuccessfulResponseHandler(Sleeper.DEFAULT, new ExponentialBackOff());
}

@VisibleForTesting

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

perhaps a comment here if we're removing the annotation

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Added a comment.

}

dependencies {
api(project(":sigstore-common"))

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think it shouldn't be api if we can avoid it, depending on what we need to expose to the users of sigstore-java, maybe stuff that needs to be exposed should be in it's own lib (like http). So http is "api" and maybe the rest of common is just "implementation"

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

For now, I'd like to keep it api, to keep this PR within scope, but I agree that things like HTTP should be extracted into their own modules.

var reposBuilder = new StringBuilder();
var pluginReposBuilder = new StringBuilder();
int idx = 0;
for (String pathStr :

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I can't tell why this change is necessary? Any insight?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Each module publishes its own build/local-maven-repo directory, and these are split by a path separator (see here).


testImplementation(project(":sigstore-testkit"))

sigstoreJavaRuntime(project(":sigstore-common"))

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

this seems like it should've been pulled in transitively through sigstore-java?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

sigstoreJavaRuntime only resolves directory-type artifacts (see here), for which Gradle does not traverse transitively.

Signed-off-by: Aaron Lew <64337293+aaronlew02@users.noreply.github.com>
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